about summary refs log tree commit diff stats
path: root/eval.lua
diff options
context:
space:
mode:
authorCase Duckworth2024-03-30 22:20:36 -0500
committerCase Duckworth2024-03-30 22:20:36 -0500
commitab8a02fd30451207578927c7e69aa397ad596459 (patch)
tree24803910776ed692f1610f44e35d0f23b9712ca3 /eval.lua
parentSpecial-case '.', '...', '+', '-' (diff)
downloadlam-ab8a02fd30451207578927c7e69aa397ad596459.tar.gz
lam-ab8a02fd30451207578927c7e69aa397ad596459.zip
Read from ports now
Diffstat (limited to 'eval.lua')
-rw-r--r--eval.lua102
1 files changed, 44 insertions, 58 deletions
diff --git a/eval.lua b/eval.lua index 610b902..4a4ad0e 100644 --- a/eval.lua +++ b/eval.lua
@@ -1,114 +1,100 @@
1--- lam.eval 1--- lam.eval
2 2
3local eval = {} 3local m = {}
4local base = require "base" 4local core = require "core"
5local type = require "type" 5local type = require "type"
6local isNull, isList, isa, List, Cons =
7 type.isNull, type.isList, type.isa, type.List, type.Cons
8local unpack = table.unpack or unpack
9 6
10function eval.Env (inner, outer) 7function m.environ (inner, outer)
11 local mt = { 8 local mt = {
12 __type = "Environment", 9 __type = "environment",
13 __index = outer, 10 __index = outer,
14 __newindex = 11 __newindex =
15 function (self, key, value) 12 function (self, key, val)
16 if rawget(self, key) then 13 if rawget(self, key) then
17 -- Set the current environment's value 14 rawset(self, key, val)
18 rawset(self, key, value)
19 else 15 else
20 -- Set the outer value 16 getmetatable(self).__index[key] = val
21 getmetatable(self).__index[key] = value
22 end 17 end
23 end, 18 end,
24 } 19 }
25 return setmetatable(inner, mt) 20 return setmetatable(inner, mt)
26end 21end
27 22
28function eval.Proc (params, body, env) 23function m.procedure (params, body, env)
29 local v = { 24 local t = {
30 params = params, 25 params = params,
31 body = body, 26 body = body,
32 env = env, 27 env = env,
33 } 28 }
34 local mt = { 29 local mt = {
35 __type = "Procedure", 30 __type = "procedure",
36 __call = 31 __call =
37 function (self, args) 32 function (self, args)
38 local inner = {} 33 local inner = {}
39 local p, a = self.params, args 34 local p, a = self.params, args
40 while p.cdr and a.cdr do 35 while p[2] and a[2] do
41 inner[p.car] = a.car 36 inner[p[1]] = a[1]
42 p, a = p.cdr, a.cdr 37 p, a = p[2], a[2]
43 end 38 end
44 local b = self.body 39 local b = self.body
45 local e = eval.Env(inner, self.env) 40 local e = m.environ(inner, self.env)
46 while not isNull(b.cdr) do 41 while not b[2] == type.null do
47 eval.eval(b.car, e) 42 m.eval(b[1], e)
48 b = b.cdr 43 b = b[2]
49 end 44 end
50 return eval.eval(b.car, e) 45 return m.eval(b[1], e)
51 end, 46 end,
52 } 47 }
53 return setmetatable(v, mt) 48 return setmetatable(t, mt)
54end 49end
55 50
56local specials = { 51local specials = {
52 -- each of these takes R (a list of args) and E (an environment)
57 quote = 53 quote =
58 function (args, env) 54 function (r, e) return r[1] end,
59 return args.car
60 end,
61 define = 55 define =
62 function (args, env) 56 function (r, e) rawset(e, r[1], m.eval(r[2][1], e)) end,
63 rawset(env, args.car, eval(args.cdr.car, env))
64 return nil
65 end,
66 lambda = 57 lambda =
67 function (args, env) 58 function (r, e) return m.procedure(r[1], r[2], e) end,
68 return Proc(args.car, args.cdr, env)
69 end,
70 ["set!"] = 59 ["set!"] =
71 function (args, env) 60 function (r, e) e[r[1]] = m.eval(r[2][1], e) end,
72 env[args.car] = eval(args.cdr.car, env)
73 return nil
74 end,
75 ["if"] = 61 ["if"] =
76 function (args, env) 62 function (r, e)
77 local test, conseq, alt = 63 local test, conseq, alt =
78 args.car, args.cdr.car, args.cdr.cdr.car 64 r[1], r[2][1], r[2][2][1]
79 if eval(test) 65 if m.eval(test)
80 then return eval(conseq) 66 then return m.eval(conseq)
81 else return eval(alt) 67 else return m.eval(alt)
82 end 68 end
83 end, 69 end,
84 -- TODO: include, import, define-syntax, define-values(?) ... 70 -- TODO: include, import, define-syntax, ...
85} 71}
86-- Aliases 72-- Aliases
87specials.lam = specials.lambda 73specials.lam = specials.lambda
88specials.def = specials.define 74specials.def = specials.define
89 75
90function eval.eval (x, env) 76function m.eval (x, env)
91 env = env or base.env 77 local env = env or core.env
92 if isa(x, "Symbol") then 78 if type.isa(x, "symbol") then
93 return env[x] 79 return env[x]
94 elseif not isList(x) then 80 elseif not type.islist(x) then
95 return x 81 return x
96 else 82 else
97 local op, args = x.car, x.cdr 83 local op, args = x[1], x[2]
98 if specials[op] then 84 if specials[op] then
99 return specials[op](args, env) 85 return specials[op](args, env)
100 else -- procedure 86 else -- procedure call
101 local proc = eval.eval(op, env) 87 local fn = m.eval(op, env)
102 local params = {} 88 local params = {}
103 local a = args 89 local r = args
104 while a.cdr do 90 while r[2] do
105 table.insert(params, eval.eval(a.car, env)) 91 table.insert(params, m.eval(r[1], env))
106 a = a.cdr 92 r = r[2]
107 end 93 end
108 return proc(List(params)) 94 return fn(type.list(params))
109 end 95 end
110 end 96 end
111end 97end
112 98
113--- 99--------
114return eval 100return m