diff options
-rw-r--r-- | eval.lua | 95 | ||||
-rw-r--r-- | readme.txt | 16 | ||||
-rw-r--r-- | types.lua | 37 |
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 | ||
3 | local eval = {} | 3 | local eval = {} |
4 | local read = require "read" | 4 | local read = require "read" |
5 | local types = require "types" | ||
6 | local util = require "util" | 5 | local util = require "util" |
7 | local pp = require "pp" | 6 | local pp = require "pp" |
8 | 7 | ||
9 | Env = types.Object:new { | 8 | local 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 |
20 | end | ||
21 | 21 | ||
22 | Proc = types.Object:new { | 22 | local Symbol = tostring |
23 | __type = "Procedure", | 23 | local Number = tonumber |
24 | __call = | 24 | |
25 | function (self, args) | 25 | local function Env(inner, outer) |
26 | local e = Env:new() | 26 | return setmetatable(inner, { __type = "Environment", __index = outer, }) |
27 | e:__extend(self.parms, | 27 | end |
28 | util.table(args), | 28 | |
29 | self.env) | 29 | local 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) | ||
49 | end | ||
33 | 50 | ||
34 | global_env = Env:new { | 51 | local 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 | ||
96 | function eval.eval (x, env) | 113 | function 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 | ||
4 | lam(n.) -- where you go when a scheme goes bad | 4 | lam(n.) -- where you go when a scheme goes bad |
5 | 5 | ||
6 | major work in progress. as of right now ( 2024-02-21 ): | 6 | this 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 | |||
16 | sad face. | ||
17 | |||
18 | however, +, *, all math.* functions and constants, begin, define, work. | ||
19 | |||
20 | apply also works, i'm pretty sure. scheme-style.(was up late last night, think i got that in) | ||
21 | 7 | ||
22 | contributions/help WELCOME! | 8 | contributions/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 | |||
3 | local types = {} | ||
4 | |||
5 | function 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 | ||
20 | end | ||
21 | |||
22 | types.Object = { __type = "Object" } | ||
23 | function types.Object:new(o) | ||
24 | o = o or {} | ||
25 | setmetatable(o, self) | ||
26 | self.__index = self | ||
27 | return o | ||
28 | end | ||
29 | |||
30 | --- Boxed types | ||
31 | |||
32 | -- Strings | ||
33 | |||
34 | -- Lists | ||
35 | |||
36 | --- | ||
37 | return types | ||