diff options
-rw-r--r-- | eval.lua | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/eval.lua b/eval.lua index c2945bf..53292d0 100644 --- a/eval.lua +++ b/eval.lua | |||
@@ -20,6 +20,28 @@ function m.environ (inner, outer) | |||
20 | return setmetatable(inner, mt) | 20 | return setmetatable(inner, mt) |
21 | end | 21 | end |
22 | 22 | ||
23 | local function call_proc (proc, r) | ||
24 | local function doargs (p, r, e) | ||
25 | if p == type.null and r == type.null then return e end | ||
26 | if type.isa(p, "symbol") then | ||
27 | e[p] = r | ||
28 | return e | ||
29 | end | ||
30 | if p[1] == nil then error("Too many arguments") end | ||
31 | if r[1] == nil then error("Too few arguments") end | ||
32 | e[p[1]] = r[1] | ||
33 | doargs(p[2], r[2], e) | ||
34 | end | ||
35 | |||
36 | local e = doargs(proc.params, r, m.environ({}, proc.env)) | ||
37 | local b = proc.body | ||
38 | while b[2] ~= type.null do | ||
39 | m.eval(b[1], e) | ||
40 | b = b[2] | ||
41 | end | ||
42 | return m.eval(b[1], e) | ||
43 | end | ||
44 | |||
23 | function m.procedure (params, body, env) | 45 | function m.procedure (params, body, env) |
24 | local t = { | 46 | local t = { |
25 | params = params, | 47 | params = params, |
@@ -28,22 +50,7 @@ function m.procedure (params, body, env) | |||
28 | } | 50 | } |
29 | local mt = { | 51 | local mt = { |
30 | __type = "procedure", | 52 | __type = "procedure", |
31 | __call = | 53 | __call = call_proc, |
32 | function (self, args) | ||
33 | local inner = {} | ||
34 | local p, a = self.params, args | ||
35 | while p[2] and a[2] do | ||
36 | inner[p[1]] = a[1] | ||
37 | p, a = p[2], a[2] | ||
38 | end | ||
39 | local b = self.body | ||
40 | local e = m.environ(inner, self.env) | ||
41 | while not b[2] == type.null do | ||
42 | m.eval(b[1], e) | ||
43 | b = b[2] | ||
44 | end | ||
45 | return m.eval(b[1], e) | ||
46 | end, | ||
47 | } | 54 | } |
48 | return setmetatable(t, mt) | 55 | return setmetatable(t, mt) |
49 | end | 56 | end |