-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
Copy pathstep3_env.wren
81 lines (74 loc) · 2.13 KB
/
step3_env.wren
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
import "./env" for Env
import "./readline" for Readline
import "./reader" for MalReader
import "./printer" for Printer
import "./types" for MalSymbol, MalList, MalVector, MalMap
class Mal {
static read(str) {
return MalReader.read_str(str)
}
static eval(ast, env) {
var dbgenv = env.find("DEBUG-EVAL")
if (dbgenv && env.get("DEBUG-EVAL")) {
System.print("EVAL: %(print(ast))")
}
// Process non-list types.
if (ast is MalSymbol) {
return env.get(ast.value)
} else if (ast is MalList) {
// The only case leading after this switch.
} else if (ast is MalVector) {
return MalVector.new(ast.elements.map { |e| eval(e, env) }.toList)
} else if (ast is MalMap) {
var m = {}
for (e in ast.data) {
m[e.key] = eval(e.value, env)
}
return MalMap.new(m)
} else {
return ast
}
// ast is a list, search for special forms
if (ast.isEmpty) return ast
if (ast[0] is MalSymbol) {
if (ast[0].value == "def!") {
return env.set(ast[1].value, eval(ast[2], env))
} else if (ast[0].value == "let*") {
var letEnv = Env.new(env)
var i = 0
while (i < ast[1].count) {
letEnv.set(ast[1][i].value, eval(ast[1][i + 1], letEnv))
i = i + 2
}
return eval(ast[2], letEnv)
}
}
var evaled_ast = ast.elements.map { |e| eval(e, env) }.toList
var f = evaled_ast[0]
return f.call(evaled_ast[1..-1])
}
static print(ast) {
return Printer.pr_str(ast)
}
static rep(str) {
return print(eval(read(str), __repl_env))
}
static main() {
__repl_env = Env.new()
__repl_env.set("+", Fn.new { |a| a[0] + a[1] })
__repl_env.set("-", Fn.new { |a| a[0] - a[1] })
__repl_env.set("*", Fn.new { |a| a[0] * a[1] })
__repl_env.set("/", Fn.new { |a| a[0] / a[1] })
while (true) {
var line = Readline.readLine("user> ")
if (line == null) break
if (line != "") {
var fiber = Fiber.new { System.print(rep(line)) }
fiber.try()
if (fiber.error) System.print("Error: %(fiber.error)")
}
}
System.print()
}
}
Mal.main()