1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
--- lam.eval
local eval = {}
local base = require "base"
local type = require "type"
local isNull, isList, isa, List, Cons =
type.isNull, type.isList, type.isa, type.List, type.Cons
local unpack = table.unpack or unpack
function eval.Env (inner, outer)
local mt = {
__type = "Environment",
__index = outer,
}
return setmetatable(inner, mt)
end
function eval.Proc (params, body, env)
local v = {
params = params,
body = body,
env = env,
}
local mt = {
__type = "Procedure",
__call =
function (self, args)
local inner = {}
local p, a = self.params, args
while p.cdr and a.cdr do
inner[p.car] = a.car
p, a = p.cdr, a.cdr
end
local b = self.body
local e = eval.Env(inner, self.env)
while not isNull(b.cdr) do
eval.eval(b.car, e)
b = b.cdr
end
return eval.eval(b.car, e)
end,
}
return setmetatable(v, mt)
end
function eval.eval (x, env)
env = env or base.env
if isa(x, "Symbol") then
return env[x]
elseif not isList(x) then
return x
else
local op, args = x.car, x.cdr
if op == "quote" then
return args.car
elseif op == "define" or op == "def" then
env[args.car] = eval.eval(args.cdr.car, env)
return nil
elseif op == "lambda" or op == "lam" then
return eval.Proc(args.car, args.cdr, env)
elseif op == "if" then
assert(not isNull(args.cdr), "Malformed 'if'")
local test, conseq, alt =
args.car, args.cdr.car, args.cdr.cdr.car
if eval.eval(test)
then return eval.eval(conseq)
else return eval.eval(alt)
end
else -- procedure
local proc = eval.eval(op, env)
local params = {}
local a = args
while a.cdr do
table.insert(params, eval.eval(a.car, env))
a = a.cdr
end
return proc(List(params))
end
end
end
---
return eval
|