9 | 9 |
--[[ ========== EVALUATOR ========== ]]--
|
10 | 10 |
|
11 | 11 |
list_p = function(value)
|
12 | |
if value == nil then
|
|
12 |
if type(value) == "function" then
|
|
13 |
return false
|
|
14 |
elseif value.class == Nil then
|
13 | 15 |
return true
|
14 | |
elseif type(value) == "function" then
|
15 | |
return false
|
16 | 16 |
elseif value.class == Cons then
|
17 | 17 |
return list_p(value.tail())
|
18 | 18 |
else
|
|
21 | 21 |
end
|
22 | 22 |
|
23 | 23 |
equal_p = function(a, b)
|
24 | |
if a == nil and b == nil then
|
|
24 |
if type(a) == "function" or type(b) == "function" then
|
|
25 |
return false
|
|
26 |
elseif a.class ~= b.class then
|
|
27 |
return false
|
|
28 |
elseif a.class == Nil then
|
25 | 29 |
return true
|
26 | |
elseif a == nil or b == nil then
|
27 | |
return false
|
28 | |
elseif a.class ~= b.class then
|
29 | |
return false
|
30 | 30 |
elseif a.class == String or a.class == Symbol then
|
31 | 31 |
return a.text() == b.text()
|
32 | 32 |
elseif a.class == Number or a.class == Boolean then
|
|
66 | 66 |
|
67 | 67 |
bind_all = function(bindings, env)
|
68 | 68 |
local binding, value
|
69 | |
while bindings ~= nil do
|
|
69 |
while bindings.class ~= Nil do
|
70 | 70 |
binding = bindings.head()
|
71 | 71 |
value = eval_expr(binding.tail().head(), env)
|
72 | 72 |
env = bind(binding.head(), value, env)
|
|
77 | 77 |
|
78 | 78 |
eval_exprs = function(sexp, env)
|
79 | 79 |
local exprs = {}
|
80 | |
while sexp ~= nil do
|
|
80 |
while sexp.class ~= Nil do
|
81 | 81 |
if sexp.class == Cons then
|
82 | 82 |
table.insert(exprs, eval_expr(sexp.head(), env))
|
83 | 83 |
else
|
|
89 | 89 |
end
|
90 | 90 |
|
91 | 91 |
eval_expr = function(ast, env)
|
92 | |
if ast == nil then
|
93 | |
return nil
|
|
92 |
-- TODO: isn't this an "illegal empty application"?
|
|
93 |
if ast.class == Nil then
|
|
94 |
return Nil
|
94 | 95 |
elseif ast.class == Cons then
|
95 | 96 |
local head = ast.head()
|
96 | 97 |
if head.class == Symbol then
|
|
123 | 124 |
return eval_expr(body, new_env)
|
124 | 125 |
elseif head.text() == "cond" then
|
125 | 126 |
local branch = ast.tail()
|
126 | |
while branch ~= nil do
|
|
127 |
while branch.class ~= Nil do
|
127 | 128 |
local b = branch.head()
|
128 | 129 |
local test = b.head()
|
129 | 130 |
if test.class == Symbol and test.text() == "else" then
|
|
170 | 171 |
elseif ast.class == Symbol then
|
171 | 172 |
local value = env[ast.text()]
|
172 | 173 |
if value == nil then
|
173 | |
-- FIXME: this is not quite right as 'nil' is also a Decoy value
|
174 | 174 |
error("Unbound symbol: " .. ast.text())
|
175 | 175 |
end
|
176 | 176 |
return value
|