Commit | Line | Data |
---|---|---|
034e82ad DM |
1 | def READ(str string) MalVal { |
2 | return read_str(str) | |
3 | } | |
4 | ||
5 | def eval_ast(ast MalVal, env StringMap<MalVal>) MalVal { | |
6 | if ast is MalSymbol { | |
7 | const name = (ast as MalSymbol).val | |
8 | if !(name in env) { | |
9 | throw MalError.new("'" + name + "' not found") | |
10 | } | |
11 | return env[name] | |
12 | } else if ast is MalList { | |
13 | return MalList.new((ast as MalList).val.map<MalVal>(e => EVAL(e, env))) | |
14 | } else if ast is MalVector { | |
15 | return MalVector.new((ast as MalVector).val.map<MalVal>(e => EVAL(e, env))) | |
16 | } else if ast is MalHashMap { | |
17 | var result List<MalVal> = [] | |
18 | (ast as MalHashMap).val.each((k string, v MalVal) => { | |
19 | result.append(EVAL(MalVal.fromHashKey(k), env)) | |
20 | result.append(EVAL(v, env)) | |
21 | }) | |
22 | return MalHashMap.fromList(result) | |
23 | } else { | |
24 | return ast | |
25 | } | |
26 | } | |
27 | ||
28 | def EVAL(ast MalVal, env StringMap<MalVal>) MalVal { | |
29 | if !(ast is MalList) { return eval_ast(ast, env) } | |
30 | var astList = ast as MalList | |
31 | if astList.isEmpty { return ast } | |
32 | var evaledList = eval_ast(ast, env) as MalList | |
33 | var fn = evaledList[0] as MalNativeFunc | |
34 | return fn.call(evaledList.val.slice(1)) | |
35 | } | |
36 | ||
37 | def PRINT(exp MalVal) string { | |
38 | return exp?.print(true) | |
39 | } | |
40 | ||
41 | var repl_env StringMap<MalVal> = { | |
42 | "+": MalNativeFunc.new((args List<MalVal>) MalVal => MalNumber.new((args[0] as MalNumber).val + (args[1] as MalNumber).val)), | |
43 | "-": MalNativeFunc.new((args List<MalVal>) MalVal => MalNumber.new((args[0] as MalNumber).val - (args[1] as MalNumber).val)), | |
44 | "*": MalNativeFunc.new((args List<MalVal>) MalVal => MalNumber.new((args[0] as MalNumber).val * (args[1] as MalNumber).val)), | |
45 | "/": MalNativeFunc.new((args List<MalVal>) MalVal => MalNumber.new((args[0] as MalNumber).val / (args[1] as MalNumber).val)), | |
46 | } | |
47 | ||
48 | def REP(str string) string { | |
49 | return PRINT(EVAL(READ(str), repl_env)) | |
50 | } | |
51 | ||
52 | @entry | |
53 | def main { | |
54 | var line string | |
55 | while (line = readLine("user> ")) != null { | |
56 | if line == "" { continue } | |
57 | try { | |
58 | printLn(REP(line)) | |
59 | } | |
60 | catch e MalError { | |
61 | printLn("Error: \(e.message)") | |
62 | } | |
63 | } | |
64 | } |