about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--eval.lua95
-rw-r--r--readme.txt16
-rw-r--r--types.lua37
3 files changed, 55 insertions, 93 deletions
diff --git a/eval.lua b/eval.lua index 3decded..d441859 100644 --- a/eval.lua +++ b/eval.lua
@@ -2,36 +2,53 @@
2 2
3local eval = {} 3local eval = {}
4local read = require "read" 4local read = require "read"
5local types = require "types"
6local util = require "util" 5local util = require "util"
7local pp = require "pp" 6local pp = require "pp"
8 7
9Env = types.Object:new { 8local function Type (x)
10 __type = "Environment", 9 if type(x) == "string" then
11 __extend = 10 return "Symbol"
12 function(self, parms, args, outer) 11 elseif type(x) == "number" then
13 for _, p in ipairs(parms) do 12 return "Number"
14 for _, a in ipairs(args) do 13 elseif getmetatable(x) and getmetatable(x).__type then
15 self[p] = a 14 return x.__type
16 end 15 elseif type(x) == "table" then
17 end 16 return "List"
18 getmetatable(self).__index = outer 17 else
19 end, 18 return type(x)
20} 19 end
20end
21 21
22Proc = types.Object:new { 22local Symbol = tostring
23 __type = "Procedure", 23local Number = tonumber
24 __call = 24
25 function (self, args) 25local function Env(inner, outer)
26 local e = Env:new() 26 return setmetatable(inner, { __type = "Environment", __index = outer, })
27 e:__extend(self.parms, 27end
28 util.table(args), 28
29 self.env) 29local function Proc(params, body, env)
30 return eval(self.body[1], e) 30 local p = {
31 end 31 params = params,
32} 32 body = body,
33 env = env,
34 }
35 local mt = {
36 __type = "Procedure",
37 __call =
38 function (self, ...)
39 local inner = {}
40 for _, p in ipairs(self.params) do
41 for _, a in ipairs({...}) do
42 inner[p] = a
43 end
44 end
45 return eval(self.body, Env(inner, self.env))
46 end,
47 }
48 return setmetatable(p, mt)
49end
33 50
34global_env = Env:new { 51local global_env = {
35 -- constants 52 -- constants
36 ["#t"] = true, 53 ["#t"] = true,
37 ["#f"] = false, 54 ["#f"] = false,
@@ -56,11 +73,11 @@ global_env = Env:new {
56 end, 73 end,
57 ["number?"] = 74 ["number?"] =
58 function(x) 75 function(x)
59 return types.Type(x) == "Number" 76 return Type(x) == "Number"
60 end, 77 end,
61 ["symbol?"] = 78 ["symbol?"] =
62 function(x) 79 function(x)
63 return types.Type(x) == "Symbol" 80 return Type(x) == "Symbol"
64 end, 81 end,
65 -- scheme functions 82 -- scheme functions
66 ["apply"] = 83 ["apply"] =
@@ -95,9 +112,9 @@ end
95 112
96function eval.eval (x, env) 113function eval.eval (x, env)
97 env = env or global_env 114 env = env or global_env
98 if types.Type(x) == "Symbol" then 115 if Type(x) == "Symbol" then
99 return env[x] 116 return env[x]
100 elseif types.Type(x) ~= "List" then 117 elseif type(x) ~= "table" then
101 return x 118 return x
102 else 119 else
103 local op = util.car(x) 120 local op = util.car(x)
@@ -107,19 +124,15 @@ function eval.eval (x, env)
107 elseif op == "define" then 124 elseif op == "define" then
108 local sym, exp = table.unpack(args) 125 local sym, exp = table.unpack(args)
109 env[sym] = eval(exp, env) 126 env[sym] = eval(exp, env)
110 elseif op == "set!" then 127 --[[
111 local sym, exp = table.unpack(args) 128 elseif op == "set!" then
112 env[sym] = eval(exp, env) 129 local sym, exp = table.unpack(args)
130 env[sym] = eval(exp, env) --]]
113 elseif op == "lambda" then 131 elseif op == "lambda" then
114 local parms = util.car(args) 132 local params = util.car(args)
115 local body = util.cdr(args) 133 local body = util.cdr(args)[1]
116 return Proc:new { 134 return Proc(params, body, env)
117 parms = parms,
118 body = body,
119 env = env,
120 }
121 else -- procedure call 135 else -- procedure call
122 pp(op)
123 local proc = eval(op, env) 136 local proc = eval(op, env)
124 local vals = util.map( 137 local vals = util.map(
125 function(v) return eval(v, env) end, 138 function(v) return eval(v, env) end,
@@ -142,4 +155,4 @@ return setmetatable(eval, { __call =
142 155
143--[[ 156--[[
144 (begin (define sq (lambda (x) (* x x))) (define rep (lambda (f) (lambda (x) (f (f x)))))) 157 (begin (define sq (lambda (x) (* x x))) (define rep (lambda (f) (lambda (x) (f (f x))))))
145-- ]] 158 -- ]]
diff --git a/readme.txt b/readme.txt index 20b41cf..76f571f 100644 --- a/readme.txt +++ b/readme.txt
@@ -3,20 +3,6 @@ by C. Duckworth
3 3
4lam(n.) -- where you go when a scheme goes bad 4lam(n.) -- where you go when a scheme goes bad
5 5
6major work in progress. as of right now ( 2024-02-21 ): 6this is /very much/ a work in progress
7- (define sq (lambda (x) (* x x)))
8
9(sq 4) ;=> 16
10(sq (sq 4)) ;=> 256
11
12- (define rep (lambda (f) (lambda (x) (f (f x)))))
13
14((rep sq) 4) ;=> ERROR -- trying to call a string value (Symbol, I think, x)
15
16sad face.
17
18however, +, *, all math.* functions and constants, begin, define, work.
19
20apply also works, i'm pretty sure. scheme-style.(was up late last night, think i got that in)
21 7
22contributions/help WELCOME! 8contributions/help WELCOME!
diff --git a/types.lua b/types.lua deleted file mode 100644 index 042edce..0000000 --- a/types.lua +++ /dev/null
@@ -1,37 +0,0 @@
1--- lam.types
2
3local types = {}
4
5function types.Type(x)
6 if type(x) == "string" then
7 -- Symbols are Lua strings
8 return "Symbol"
9 elseif type(x) == "number" then
10 -- Numbers are Lua numbers
11 return "Number"
12 elseif x.__type then
13 return x.__type
14 elseif type(x) == "table" then
15 -- Lists are Lua tables (non-adorned)
16 return "List"
17 else
18 return type(x)
19 end
20end
21
22types.Object = { __type = "Object" }
23function types.Object:new(o)
24 o = o or {}
25 setmetatable(o, self)
26 self.__index = self
27 return o
28end
29
30--- Boxed types
31
32-- Strings
33
34-- Lists
35
36---
37return types