forked from Fundament-Software/Alicorn0
-
Notifications
You must be signed in to change notification settings - Fork 0
/
testlanguage.lua
129 lines (109 loc) · 3.11 KB
/
testlanguage.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
local metalang = require "./metalanguage"
local eval
local function eval_passhandler(env, val)
--print("eval pass handler", val, env)
return true, val, env
end
local eval
local function Eval(syntax, matcher, environment)
return eval(syntax, environment)
end
local evaluates = metalang.reducer(Eval, "evaluates")
local function eval_pairhandler(env, a, b)
--print("in eval pairhandler", a, b, env)
local ok, combiner, _ = a:match({
evaluates(eval_passhandler, env),
}, metalang.failure_handler, env)
if not ok then
return false, combiner
end
local ok, val, newenv = combiner:apply(b, env)
--print("eval pair", ok, val, newenv)
return ok, val, newenv
end
local function symbolenvhandler(env, name)
--print("symbolenvhandler(", name, env, ")")
local res = env:get(name)
if res ~= nil then
return true, res
else
return false, "environment does not contain a binding for " .. name
end
end
local function SymbolInEnvironment(syntax, environment)
--print("in symbol in environment reducer", matcher.kind, matcher[1], matcher)
return syntax:match({
metalang.issymbol(symbolenvhandler),
}, metalang.failure_handler, environment)
end
local symbol_in_environment = metalang.reducer(SymbolInEnvironment, "symbol in env")
function eval(syntax, environment)
return syntax:match({
symbol_in_environment(eval_passhandler, environment),
metalang.isvalue(eval_passhandler),
metalang.ispair(eval_pairhandler),
}, metalang.failure_handler, environment)
end
local function syntax_args_val_handler(_, val, newenv)
return true, val, newenv
end
local function syntax_args_nil_handler(data)
return true, false
end
local function syntax_args_pair_handler(env, a, b)
local ok, val, _ = a:match({
evaluates(syntax_args_val_handler, env),
}, metalang.failure_handler, nil)
--print("args pair handler", ok, val, _, b)
return true, true, val, b
end
local function EvalArgs(syntax, matcher, environment)
local args = {}
local ok, ispair, val, tail = true, true, nil, nil
while ok and ispair do
ok, ispair, val, tail = syntax:match({
metalang.ispair(syntax_args_pair_handler),
metalang.isnil(syntax_args_nil_handler),
}, metalang.failure_handler, environment)
if not ok then
return false, ispair
end
if ispair then
args[#args + 1] = val
syntax = tail
end
end
return true, args
end
local evalargs = metalang.reducer(EvalArgs, "evalargs")
local primitive_applicative_mt = {
__index = {
apply = function(self, ops, env)
local ok, args = ops:match({
evalargs(metalang.accept_handler, env),
}, metalang.failure_handler, nil)
local res = self.fn(table.unpack(args))
return true, metalang.value(res), env
end,
},
}
local function primitive_applicative(fn)
return setmetatable({ fn = fn }, primitive_applicative_mt)
end
local primitive_operative_mt = {
__index = {
apply = function(self, ops, env)
return self.fn(ops, env)
end,
},
}
local function primitive_operative(fn)
return setmetatable({ fn = fn }, primitive_operative_mt)
end
return {
eval = eval,
evalargs = evalargs,
evaluates = evaluates,
primitive_applicative = primitive_applicative,
primitive_operative = primitive_operative,
}