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