diff options
-rw-r--r-- | eval.lua | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/eval.lua b/eval.lua index 6179842..5e897e2 100644 --- a/eval.lua +++ b/eval.lua | |||
@@ -1,9 +1,9 @@ | |||
1 | --- lam.eval | 1 | --- lam.eval |
2 | 2 | ||
3 | local eval = {} | 3 | local eval = {} |
4 | local read = require "read" | ||
5 | local type = require "type" | 4 | local type = require "type" |
6 | local util = require "util" | 5 | local isNull, isList, isa, List, Cons = |
6 | type.isNull, type.isList, type.isa, type.List, type.Cons | ||
7 | local unpack = table.unpack or unpack | 7 | local unpack = table.unpack or unpack |
8 | 8 | ||
9 | function eval.Env (inner, outer) | 9 | function eval.Env (inner, outer) |
@@ -30,7 +30,6 @@ function eval.Proc (params, body, env) | |||
30 | inner[p.car] = a.car | 30 | inner[p.car] = a.car |
31 | p, a = p.cdr, a.cdr | 31 | p, a = p.cdr, a.cdr |
32 | end | 32 | end |
33 | -- pp.pp(self.body) | ||
34 | return eval.eval( | 33 | return eval.eval( |
35 | self.body, | 34 | self.body, |
36 | eval.Env(inner, self.env)) | 35 | eval.Env(inner, self.env)) |
@@ -41,47 +40,59 @@ end | |||
41 | 40 | ||
42 | local global = { | 41 | local global = { |
43 | begin = | 42 | begin = |
44 | function (args) | 43 | function (r) |
45 | local a = args | 44 | local r = r |
46 | while not type.isNull(a.cdr) do | 45 | while not isNull(r.cdr) do |
47 | a = a.cdr | 46 | r = r.cdr |
48 | end | 47 | end |
49 | return a.car | 48 | return r.car |
50 | end, | 49 | end, |
51 | ["+"] = | 50 | ["+"] = |
52 | function (args) | 51 | function (r) |
53 | local acc = 0 | 52 | local r, a = r, 0 |
54 | local car, cdr = args.car, args.cdr | 53 | while r.cdr do |
55 | while cdr do | 54 | r, a = r.cdr, a + r.car |
56 | acc = acc + car | ||
57 | car, cdr = cdr.car, cdr.cdr | ||
58 | end | 55 | end |
59 | return acc | 56 | return a |
60 | end, | 57 | end, |
61 | ["-"] = | 58 | ["-"] = |
62 | function (args) | 59 | function (r) |
63 | return args.car - args.cdr.car | 60 | if isNull(r) then return -1 end |
61 | if isNull(r.cdr) then return (- r.car) end | ||
62 | local r, a = r.cdr, r.car | ||
63 | while r.cdr do | ||
64 | r, a = r.cdr, a - r.car | ||
65 | end | ||
66 | return a | ||
64 | end, | 67 | end, |
65 | } | 68 | } |
66 | 69 | ||
67 | function eval.eval (x, env) | 70 | function eval.eval (x, env) |
68 | env = env or global | 71 | env = env or global |
69 | if type.isa(x, "Symbol") then | 72 | if isa(x, "Symbol") then |
70 | return env[x] | 73 | return env[x] |
71 | elseif not type.isList(x) then | 74 | elseif not isList(x) then |
72 | return x | 75 | return x |
73 | else | 76 | else |
74 | local op, args = x.car, x.cdr | 77 | local op, args = x.car, x.cdr |
75 | if op == "quote" then | 78 | if op == "quote" then |
76 | return args | 79 | return args.car |
77 | elseif op == "define" then | 80 | elseif op == "define" then |
78 | env[args.car] = eval.eval(args.cdr.car, env) | 81 | env[args.car] = eval.eval(args.cdr.car, env) |
79 | return nil | 82 | return nil |
80 | elseif op == "lambda" then | 83 | elseif op == "lambda" then |
81 | return eval.Proc( | 84 | return eval.Proc( |
82 | args.car, | 85 | args.car, |
83 | type.Cons("begin", args.cdr), | 86 | Cons("begin", args.cdr), |
84 | env) | 87 | env) |
88 | elseif op == "if" then | ||
89 | assert(not isNull(args.cdr), "Malformed 'if'") | ||
90 | local test, conseq, alt = | ||
91 | args.car, args.cdr.car, args.cdr.cdr.car | ||
92 | if eval.eval(test) | ||
93 | then return eval.eval(conseq) | ||
94 | else return eval.eval(alt) | ||
95 | end | ||
85 | else -- procedure | 96 | else -- procedure |
86 | local proc = eval.eval(op, env) | 97 | local proc = eval.eval(op, env) |
87 | local params = {} | 98 | local params = {} |
@@ -90,7 +101,7 @@ function eval.eval (x, env) | |||
90 | table.insert(params, eval.eval(a.car, env)) | 101 | table.insert(params, eval.eval(a.car, env)) |
91 | a = a.cdr | 102 | a = a.cdr |
92 | end | 103 | end |
93 | return proc(type.List(params)) | 104 | return proc(List(params)) |
94 | end | 105 | end |
95 | end | 106 | end |
96 | end | 107 | end |