diff options
-rw-r--r-- | eval.lua | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/eval.lua b/eval.lua index e13fb97..714c67e 100644 --- a/eval.lua +++ b/eval.lua | |||
@@ -48,17 +48,43 @@ function m.procedure (params, body, env) | |||
48 | return setmetatable(t, mt) | 48 | return setmetatable(t, mt) |
49 | end | 49 | end |
50 | 50 | ||
51 | local specials = { | ||
52 | m.specials = { | 51 | m.specials = { |
53 | -- each of these takes R (a list of args) and E (an environment) | 52 | -- each of these takes R (a list of args) and E (an environment) |
54 | quote = | 53 | quote = function (r, e) return r[1] end, |
55 | function (r, e) return r[1] end, | 54 | quasiquote = |
56 | define = | 55 | function (r, e) |
57 | function (r, e) rawset(e, r[1], m.eval(r[2][1], e)) end, | 56 | local x = r[1] |
58 | lambda = | 57 | if not type.islist(x) or x == type.null then |
59 | function (r, e) return m.procedure(r[1], r[2], e) end, | 58 | return x |
60 | ["set!"] = | 59 | end |
61 | function (r, e) e[r[1]] = m.eval(r[2][1], e) end, | 60 | local QQ, fin = {}, nil |
61 | local car, cdr = x[1], x[2] | ||
62 | while cdr do | ||
63 | if type.islist(car) then | ||
64 | if car[1] == "unquote" then | ||
65 | table.insert(QQ, | ||
66 | m.eval(car[2][1], e)) | ||
67 | elseif car[1] == "unquote-splicing" then | ||
68 | local usl = m.eval(car[2][1], e) | ||
69 | if not type.islist(usl) then | ||
70 | fin = usl | ||
71 | break | ||
72 | end | ||
73 | while usl[2] do | ||
74 | table.insert(QQ, usl[1]) | ||
75 | usl = usl[2] | ||
76 | end | ||
77 | end | ||
78 | else | ||
79 | table.insert(QQ, car) | ||
80 | end | ||
81 | car, cdr = cdr[1], cdr[2] | ||
82 | end | ||
83 | return type.list(QQ, fin) | ||
84 | end, | ||
85 | define = function (r, e) rawset(e, r[1], m.eval(r[2][1], e)) end, | ||
86 | lambda = function (r, e) return m.procedure(r[1], r[2], e) end, | ||
87 | ["set!"] = function (r, e) e[r[1]] = m.eval(r[2][1], e) end, | ||
62 | ["if"] = | 88 | ["if"] = |
63 | function (r, e) | 89 | function (r, e) |
64 | local test, conseq, alt = | 90 | local test, conseq, alt = |