about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--eval.lua119
-rw-r--r--global.lua141
-rw-r--r--types.lua27
3 files changed, 190 insertions, 97 deletions
diff --git a/eval.lua b/eval.lua index d441859..cdf4612 100644 --- a/eval.lua +++ b/eval.lua
@@ -4,23 +4,10 @@ local eval = {}
4local read = require "read" 4local read = require "read"
5local util = require "util" 5local util = require "util"
6local pp = require "pp" 6local pp = require "pp"
7local global = require "global"
8local types = require("types")
7 9
8local function Type (x) 10if not table.unpack then table.unpack = unpack end
9 if type(x) == "string" then
10 return "Symbol"
11 elseif type(x) == "number" then
12 return "Number"
13 elseif getmetatable(x) and getmetatable(x).__type then
14 return x.__type
15 elseif type(x) == "table" then
16 return "List"
17 else
18 return type(x)
19 end
20end
21
22local Symbol = tostring
23local Number = tonumber
24 11
25local function Env(inner, outer) 12local function Env(inner, outer)
26 return setmetatable(inner, { __type = "Environment", __index = outer, }) 13 return setmetatable(inner, { __type = "Environment", __index = outer, })
@@ -48,73 +35,11 @@ local function Proc(params, body, env)
48 return setmetatable(p, mt) 35 return setmetatable(p, mt)
49end 36end
50 37
51local global_env = { 38function eval.eval (x, e)
52 -- constants 39 e = e or global
53 ["#t"] = true, 40 if types.lamtype(x) == "Symbol" then
54 ["#f"] = false, 41 return e[x]
55 -- basic math 42 elseif types.luatype(x) ~= "table" then
56 ["+"] =
57 function (...)
58 print(...)
59 return util.reduce(
60 {...}, 0,
61 function (a, b) return a + b end)
62 end,
63 ["*"] =
64 function (...)
65 return util.reduce(
66 {...}, 1,
67 function (a, b) return a * b end)
68 end,
69 -- scheme predicates
70 ["null?"] =
71 function(x)
72 return x == {}
73 end,
74 ["number?"] =
75 function(x)
76 return Type(x) == "Number"
77 end,
78 ["symbol?"] =
79 function(x)
80 return Type(x) == "Symbol"
81 end,
82 -- scheme functions
83 ["apply"] =
84 function(fn, ...)
85 local args = {...}
86 local last = args[#args]
87 assert(type(last)=="table", "Bad apply")
88 table.remove(args)
89 for _,v in ipairs(last) do
90 table.insert(args, v)
91 end
92 return fn(table.unpack(args))
93 end,
94 ["begin"] =
95 function(...)
96 local xs = {...}
97 return xs[#xs]
98 end,
99 ["map"] =
100 function(fn, ...)
101 return util.map(fn, {...})
102 end,
103 ["car"] = util.car,
104 ["cdr"] = util.cdr,
105 ["list"] = function(...) return {...} end,
106}
107
108-- Math
109for k, v in pairs(math) do
110 global_env[k] = v
111end
112
113function eval.eval (x, env)
114 env = env or global_env
115 if Type(x) == "Symbol" then
116 return env[x]
117 elseif type(x) ~= "table" then
118 return x 43 return x
119 else 44 else
120 local op = util.car(x) 45 local op = util.car(x)
@@ -123,20 +48,24 @@ function eval.eval (x, env)
123 return args[1] 48 return args[1]
124 elseif op == "define" then 49 elseif op == "define" then
125 local sym, exp = table.unpack(args) 50 local sym, exp = table.unpack(args)
126 env[sym] = eval(exp, env) 51 e[sym] = eval(exp, e)
127 --[[ 52 --[[
128 elseif op == "set!" then 53 elseif op == "set!" then
129 local sym, exp = table.unpack(args) 54 local sym, exp = table.unpack(args)
130 env[sym] = eval(exp, env) --]] 55 e[sym] = eval(exp, e) --]]
131 elseif op == "lambda" then 56 elseif op == "lambda" then
132 local params = util.car(args) 57 local params = util.car(args)
133 local body = util.cdr(args)[1] 58 local body = util.cdr(args)
134 return Proc(params, body, env) 59 table.insert(body, 1, "begin")
60 return Proc(params,
61 body,
62 e)
135 else -- procedure call 63 else -- procedure call
136 local proc = eval(op, env) 64 local proc = eval(op, e)
137 local vals = util.map( 65 local vals = {}
138 function(v) return eval(v, env) end, 66 for k, v in pairs(args) do
139 args) 67 vals[k] = eval(v, e)
68 end
140 return proc(table.unpack(vals)) 69 return proc(table.unpack(vals))
141 end 70 end
142 end 71 end
@@ -144,15 +73,11 @@ end
144 73
145--- 74---
146return setmetatable(eval, { __call = 75return setmetatable(eval, { __call =
147 function(_, x, env) 76 function(_, x, e)
148 local success, result = 77 local success, result =
149 pcall(eval.eval, x, env) 78 pcall(eval.eval, x, e)
150 if success then return result 79 if success then return result
151 else return ("ERROR: " .. result) 80 else return ("ERROR: " .. result)
152 end 81 end
153 end 82 end
154}) 83})
155
156--[[
157 (begin (define sq (lambda (x) (* x x))) (define rep (lambda (f) (lambda (x) (f (f x))))))
158 -- ]]
diff --git a/global.lua b/global.lua new file mode 100644 index 0000000..3805912 --- /dev/null +++ b/global.lua
@@ -0,0 +1,141 @@
1--- lam.environment
2
3local util = require "util"
4local types = require("types")
5
6if not table.unpack then table.unpack = unpack end
7
8local global = {
9 -- constants
10 ["#t"] = true,
11 ["#f"] = false,
12}
13
14--- Types ---
15
16for name, func in pairs(types) do
17 if name == "lamtype" then
18 global.type = func
19 else
20 global[name] = func
21 end
22end
23
24--- Basic functions ---
25
26global.begin = function(...)
27 local xs = {...}
28 return xs[#xs]
29end
30
31global.car = util.car
32global.cdr = util.cdr
33
34global.list = function(...) return {...} end
35
36--- Higher-order functions ---
37
38global.apply = function(fn, ...)
39 local args = {...}
40 local last = args[#args]
41 assert(types.luatype(last) == "table", "Bad apply")
42 table.remove(args)
43 for _, v in ipairs(last) do
44 table.insert(args, v)
45 end
46 return fn(table.unpack(args))
47end
48
49global.map = function(fn, list)
50 return util.map(fn, list)
51end
52
53--- Math ---
54-- NOTE: we do not have the full numeric tower yet!
55
56for name, func in pairs(math) do
57 global[name] = func
58end
59
60global["+"] = function (...)
61 return util.reduce({...}, 0, function (a, b) return a + b end)
62end
63
64global["-"] = function (...)
65 local args = {...}
66 if #args == 0 then
67 error("Too few arguments: need at least 1")
68 elseif #args == 1 then
69 return (-args[1])
70 else
71 local result = args[1]
72 for v = 2, #args do
73 result = result - args[v]
74 end
75 return result
76 end
77end
78
79global["*"] = function (...)
80 local result = 1
81 for _, v in ipairs({...}) do
82 if v == 0 then return 0 end
83 result = result * v
84 end
85 return result
86end
87
88global["/"] = function (...)
89 local args = {...}
90 if #args == 0 then
91 error("Too few arguments: need at least 1")
92 elseif #args == 1 then
93 if args[1] == 0 then error("Division by zero") end
94 return (1/args[1])
95 else
96 local result = args[1]
97 for v = 2, #args do
98 if args[v] == 0 then error("Division by zero") end
99 result = result / args[v]
100 end
101 return result
102 end
103end
104
105global["="] = function (...)
106 for _, v in ipairs({...}) do
107 if not a == b then return false end
108 end
109 return true
110end
111
112global["<"] = function (...)
113 for _, v in ipairs({...}) do
114 if not a < b then return false end
115 end
116 return true
117end
118
119global["<="] = function (...)
120 for _, v in ipairs({...}) do
121 if not a <= b then return false end
122 end
123 return true
124end
125
126global[">"] = function (...)
127 for _, v in ipairs({...}) do
128 if not a > b then return false end
129 end
130 return true
131end
132
133global[">="] = function (...)
134 for _, v in ipairs({...}) do
135 if not a >= b then return false end
136 end
137 return true
138end
139
140---
141return global
diff --git a/types.lua b/types.lua new file mode 100644 index 0000000..dd105cf --- /dev/null +++ b/types.lua
@@ -0,0 +1,27 @@
1--- lam.types
2
3local types = {}
4
5types.luatype = type
6
7function types.lamtype (x)
8 if types.luatype(x) == "string" then
9 return "Symbol"
10 elseif types.luatype(x) == "number" then
11 return "Number"
12 elseif getmetatable(x) and getmetatable(x).__type then
13 return getmetatable(x).__type
14 elseif types.luatype(x) == "table" then
15 return "List"
16 else
17 return types.luatype(x)
18 end
19end
20
21types["number?"] = function (x) return types.lamtype(x) == "Number" end
22types["symbol?"] = function (x) return types.lamtype(x) == "Symbol" end
23types["list?"] = function (x) return types.lamtype(x) == "List" end
24types["null?"] = function (x) return x == {} end
25
26---
27return types