about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--eval.lua75
1 files changed, 27 insertions, 48 deletions
diff --git a/eval.lua b/eval.lua index 39a5bbe..9b1c315 100644 --- a/eval.lua +++ b/eval.lua
@@ -1,12 +1,13 @@
1--- lam.eval 1--- lam.eval
2 2
3local eval = {}
3local base = require "base" 4local base = require "base"
4local type = require "type" 5local type = require "type"
5local isNull, isList, isa, List, Cons = 6local isNull, isList, isa, List, Cons =
6 type.isNull, type.isList, type.isa, type.List, type.Cons 7 type.isNull, type.isList, type.isa, type.List, type.Cons
7local unpack = table.unpack or unpack 8local unpack = table.unpack or unpack
8 9
9local function Env (inner, outer) 10function eval.Env (inner, outer)
10 local mt = { 11 local mt = {
11 __type = "Environment", 12 __type = "Environment",
12 __index = outer, 13 __index = outer,
@@ -24,7 +25,7 @@ local function Env (inner, outer)
24 return setmetatable(inner, mt) 25 return setmetatable(inner, mt)
25end 26end
26 27
27local function Proc (params, body, env) 28function eval.Proc (params, body, env)
28 local v = { 29 local v = {
29 params = params, 30 params = params,
30 body = body, 31 body = body,
@@ -41,51 +42,18 @@ local function Proc (params, body, env)
41 p, a = p.cdr, a.cdr 42 p, a = p.cdr, a.cdr
42 end 43 end
43 local b = self.body 44 local b = self.body
44 local e = Env(inner, self.env) 45 local e = eval.Env(inner, self.env)
45 while not isNull(b.cdr) do 46 while not isNull(b.cdr) do
46 eval(b.car, e) 47 eval.eval(b.car, e)
47 b = b.cdr 48 b = b.cdr
48 end 49 end
49 return eval(b.car, e) 50 return eval.eval(b.car, e)
50 end, 51 end,
51 } 52 }
52 return setmetatable(v, mt) 53 return setmetatable(v, mt)
53end 54end
54 55
55local specials = { 56function eval.eval (x, env)
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)
89 env = env or base.env 57 env = env or base.env
90 if isa(x, "Symbol") then 58 if isa(x, "Symbol") then
91 return env[x] 59 return env[x]
@@ -93,14 +61,29 @@ local function eval (x, env)
93 return x 61 return x
94 else 62 else
95 local op, args = x.car, x.cdr 63 local op, args = x.car, x.cdr
96 if specials[op] then 64 if op == "quote" then
97 return specials[op](args, env) 65 return args.car
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
98 else -- procedure 81 else -- procedure
99 local proc = eval(op, env) 82 local proc = eval.eval(op, env)
100 local params = {} 83 local params = {}
101 local a = args 84 local a = args
102 while a.cdr do 85 while a.cdr do
103 table.insert(params, eval(a.car, env)) 86 table.insert(params, eval.eval(a.car, env))
104 a = a.cdr 87 a = a.cdr
105 end 88 end
106 return proc(List(params)) 89 return proc(List(params))
@@ -109,8 +92,4 @@ local function eval (x, env)
109end 92end
110 93
111--- 94---
112return { 95return eval
113 Env = Env,
114 Proc = Proc,
115 eval = eval,
116}