diff options
author | Case Duckworth | 2024-02-22 00:23:32 -0600 |
---|---|---|
committer | Case Duckworth | 2024-02-22 00:23:32 -0600 |
commit | 5328b62221a3839dca117d71a4703f3ad719c9ce (patch) | |
tree | 7212235f569e765d3a4ebed0e8d21b64d905bf3a /eval.lua | |
parent | Remove spurious require (diff) | |
download | lam-5328b62221a3839dca117d71a4703f3ad719c9ce.tar.gz lam-5328b62221a3839dca117d71a4703f3ad719c9ce.zip |
Add global and types libraries
Diffstat (limited to 'eval.lua')
-rw-r--r-- | eval.lua | 119 |
1 files changed, 22 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 = {} | |||
4 | local read = require "read" | 4 | local read = require "read" |
5 | local util = require "util" | 5 | local util = require "util" |
6 | local pp = require "pp" | 6 | local pp = require "pp" |
7 | local global = require "global" | ||
8 | local types = require("types") | ||
7 | 9 | ||
8 | local function Type (x) | 10 | if 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 | ||
20 | end | ||
21 | |||
22 | local Symbol = tostring | ||
23 | local Number = tonumber | ||
24 | 11 | ||
25 | local function Env(inner, outer) | 12 | local 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) |
49 | end | 36 | end |
50 | 37 | ||
51 | local global_env = { | 38 | function 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 | ||
109 | for k, v in pairs(math) do | ||
110 | global_env[k] = v | ||
111 | end | ||
112 | |||
113 | function 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 | --- |
146 | return setmetatable(eval, { __call = | 75 | return 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 | -- ]] | ||