Commit | Line | Data |
---|---|---|
a04e7a78 DM |
1 | import .Env; |
2 | import .Printer; | |
3 | import .Reader; | |
4 | import .Readline; | |
5 | import .Types; | |
6 | ||
7 | Val READ(string str) | |
8 | { | |
9 | return read_str(str); | |
10 | } | |
11 | ||
12 | Val eval_ast(Val ast, Env env) | |
13 | { | |
14 | switch(ast.mal_type) | |
15 | { | |
16 | case MALTYPE_SYMBOL: | |
17 | return env.get(ast); | |
18 | case MALTYPE_LIST: | |
19 | return List(map(ast.data, lambda(Val e) { return EVAL(e, env); })); | |
20 | case MALTYPE_VECTOR: | |
21 | return Vector(map(ast.data, lambda(Val e) { return EVAL(e, env); })); | |
22 | case MALTYPE_MAP: | |
23 | array(Val) elements = ({ }); | |
24 | foreach(ast.data; Val k; Val v) | |
25 | { | |
26 | elements += ({ k, EVAL(v, env) }); | |
27 | } | |
28 | return Map(elements); | |
29 | default: | |
30 | return ast; | |
31 | } | |
32 | } | |
33 | ||
34 | Val EVAL(Val ast, Env env) | |
35 | { | |
36 | if(ast.mal_type != MALTYPE_LIST) return eval_ast(ast, env); | |
37 | if(ast.emptyp()) return ast; | |
38 | if(ast.data[0].mal_type == MALTYPE_SYMBOL) { | |
39 | switch(ast.data[0].value) | |
40 | { | |
41 | case "def!": | |
42 | return env.set(ast.data[1], EVAL(ast.data[2], env)); | |
43 | case "let*": | |
44 | Env let_env = Env(env); | |
45 | Val ast1 = ast.data[1]; | |
46 | for(int i = 0; i < sizeof(ast1.data); i += 2) | |
47 | { | |
48 | let_env.set(ast1.data[i], EVAL(ast1.data[i + 1], let_env)); | |
49 | } | |
50 | return EVAL(ast.data[2], let_env); | |
51 | } | |
52 | } | |
53 | Val evaled_ast = eval_ast(ast, env); | |
54 | function f = evaled_ast.data[0]; | |
55 | return f(@evaled_ast.data[1..]); | |
56 | } | |
57 | ||
58 | string PRINT(Val exp) | |
59 | { | |
60 | return pr_str(exp, true); | |
61 | } | |
62 | ||
63 | string rep(string str, Env env) | |
64 | { | |
65 | return PRINT(EVAL(READ(str), env)); | |
66 | } | |
67 | ||
68 | int main() | |
69 | { | |
70 | Env repl_env = Env(0); | |
71 | repl_env.set(Symbol("+"), lambda(Val a, Val b) { return Number(a.value + b.value); }); | |
72 | repl_env.set(Symbol("-"), lambda(Val a, Val b) { return Number(a.value - b.value); }); | |
73 | repl_env.set(Symbol("*"), lambda(Val a, Val b) { return Number(a.value * b.value); }); | |
74 | repl_env.set(Symbol("/"), lambda(Val a, Val b) { return Number(a.value / b.value); }); | |
75 | while(1) | |
76 | { | |
77 | string line = readline("user> "); | |
78 | if(!line) break; | |
79 | if(strlen(line) == 0) continue; | |
80 | if(mixed err = catch { write(({ rep(line, repl_env), "\n" })); } ) | |
81 | { | |
82 | if(arrayp(err)) err = err[0]; | |
83 | write(({ "Error: ", err, "\n" })); | |
84 | } | |
85 | } | |
86 | write("\n"); | |
87 | return 0; | |
88 | } |