about summary refs log tree commit diff stats
path: root/eval.lua
diff options
context:
space:
mode:
authorCase Duckworth2024-03-21 22:34:12 -0500
committerCase Duckworth2024-03-21 22:34:12 -0500
commit1d5041ff7bf92458d6d07ac6a03f2747dce9b9b1 (patch)
tree912c54baf0ac453dc9f77d3dd43ce94b53803503 /eval.lua
parentImplment set! (diff)
downloadlam-1d5041ff7bf92458d6d07ac6a03f2747dce9b9b1.tar.gz
lam-1d5041ff7bf92458d6d07ac6a03f2747dce9b9b1.zip
Refactor eval
Localize stuff and also break out specials
Diffstat (limited to 'eval.lua')
-rw-r--r--eval.lua75
1 files changed, 48 insertions, 27 deletions
diff --git a/eval.lua b/eval.lua index 9b1c315..39a5bbe 100644 --- a/eval.lua +++ b/eval.lua
@@ -1,13 +1,12 @@
1--- lam.eval 1--- lam.eval
2 2
3local eval = {}
4local base = require "base" 3local base = require "base"
5local type = require "type" 4local type = require "type"
6local isNull, isList, isa, List, Cons = 5local isNull, isList, isa, List, Cons =
7 type.isNull, type.isList, type.isa, type.List, type.Cons 6 type.isNull, type.isList, type.isa, type.List, type.Cons
8local unpack = table.unpack or unpack 7local unpack = table.unpack or unpack
9 8
10function eval.Env (inner, outer) 9local function Env (inner, outer)
11 local mt = { 10 local mt = {
12 __type = "Environment", 11 __type = "Environment",
13 __index = outer, 12 __index = outer,
@@ -25,7 +24,7 @@ function eval.Env (inner, outer)
25 return setmetatable(inner, mt) 24 return setmetatable(inner, mt)
26end 25end
27 26
28function eval.Proc (params, body, env) 27local function Proc (params, body, env)
29 local v = { 28 local v = {
30 params = params, 29 params = params,
31 body = body, 30 body = body,
@@ -42,18 +41,51 @@ function eval.Proc (params, body, env)
42 p, a = p.cdr, a.cdr 41 p, a = p.cdr, a.cdr
43 end 42 end
44 local b = self.body 43 local b = self.body
45 local e = eval.Env(inner, self.env) 44 local e = Env(inner, self.env)
46 while not isNull(b.cdr) do 45 while not isNull(b.cdr) do
47 eval.eval(b.car, e) 46 eval(b.car, e)
48 b = b.cdr 47 b = b.cdr
49 end 48 end
50 return eval.eval(b.car, e) 49 return eval(b.car, e)
51 end, 50 end,
52 } 51 }
53 return setmetatable(v, mt) 52 return setmetatable(v, mt)
54end 53end
55 54
56function eval.eval (x, env) 55local specials = {
56 quote =
57 function (args, env)
58 return args.car
59 end,
60 define =
61 function (args, env)
62 rawset(env, args.car, eval(args.cdr.car, env))
63 return nil
64 end,
65 lambda =
66 function (args, env)
67 return Proc(args.car, args.cdr, env)
68 end,
69 ["set!"] =
70 function (args, env)
71 env[args.car] = eval(args.cdr.car, env)
72 return nil
73 end,
74 ["if"] =
75 function (args, env)
76 local test, conseq, alt =
77 args.car, args.cdr.car, args.cdr.cdr.car
78 if eval(test)
79 then return eval(conseq)
80 else return eval(alt)
81 end
82 end,
83}
84-- Aliases
85specials.lam = specials.lambda
86specials.def = specials.define
87
88local function eval (x, env)
57 env = env or base.env 89 env = env or base.env
58 if isa(x, "Symbol") then 90 if isa(x, "Symbol") then
59 return env[x] 91 return env[x]
@@ -61,29 +93,14 @@ function eval.eval (x, env)
61 return x 93 return x
62 else 94 else
63 local op, args = x.car, x.cdr 95 local op, args = x.car, x.cdr
64 if op == "quote" then 96 if specials[op] then
65 return args.car 97 return specials[op](args, env)
66 elseif op == "define" or op == "def" then
67 rawset(env, args.car, eval.eval(args.cdr.car, env))
68 return nil
69 elseif op == "set!" then
70 env[args.car] = eval.eval(args.cdr.car, env)
71 elseif op == "lambda" or op == "lam" then
72 return eval.Proc(args.car, args.cdr, env)
73 elseif op == "if" then
74 assert(not isNull(args.cdr), "Malformed 'if'")
75 local test, conseq, alt =
76 args.car, args.cdr.car, args.cdr.cdr.car
77 if eval.eval(test)
78 then return eval.eval(conseq)
79 else return eval.eval(alt)
80 end
81 else -- procedure 98 else -- procedure
82 local proc = eval.eval(op, env) 99 local proc = eval(op, env)
83 local params = {} 100 local params = {}
84 local a = args 101 local a = args
85 while a.cdr do 102 while a.cdr do
86 table.insert(params, eval.eval(a.car, env)) 103 table.insert(params, eval(a.car, env))
87 a = a.cdr 104 a = a.cdr
88 end 105 end
89 return proc(List(params)) 106 return proc(List(params))
@@ -92,4 +109,8 @@ function eval.eval (x, env)
92end 109end
93 110
94--- 111---
95return eval 112return {
113 Env = Env,
114 Proc = Proc,
115 eval = eval,
116}