Commit | Line | Data |
---|---|---|
b56c49a1 JM |
1 | using System; |
2 | using System.IO; | |
3 | using System.Collections; | |
4 | using System.Collections.Generic; | |
5 | using Mal; | |
6 | using MalVal = Mal.types.MalVal; | |
7 | using MalSymbol = Mal.types.MalSymbol; | |
c3b508af | 8 | using MalInt = Mal.types.MalInt; |
b56c49a1 JM |
9 | using MalList = Mal.types.MalList; |
10 | using MalVector = Mal.types.MalVector; | |
11 | using MalHashMap = Mal.types.MalHashMap; | |
c3b508af | 12 | using MalFunc = Mal.types.MalFunc; |
b56c49a1 JM |
13 | |
14 | namespace Mal { | |
aaba2493 | 15 | class step2_eval { |
b56c49a1 JM |
16 | // read |
17 | static MalVal READ(string str) { | |
18 | return reader.read_str(str); | |
19 | } | |
20 | ||
21 | // eval | |
22 | static MalVal eval_ast(MalVal ast, Dictionary<string, MalVal> env) { | |
23 | if (ast is MalSymbol) { | |
24 | MalSymbol sym = (MalSymbol)ast; | |
25 | return (MalVal)env[sym.getName()]; | |
26 | } else if (ast is MalList) { | |
27 | MalList old_lst = (MalList)ast; | |
28 | MalList new_lst = ast.list_Q() ? new MalList() | |
29 | : (MalList)new MalVector(); | |
30 | foreach (MalVal mv in old_lst.getValue()) { | |
31 | new_lst.conj_BANG(EVAL(mv, env)); | |
32 | } | |
33 | return new_lst; | |
34 | } else if (ast is MalHashMap) { | |
35 | var new_dict = new Dictionary<string, MalVal>(); | |
36 | foreach (var entry in ((MalHashMap)ast).getValue()) { | |
37 | new_dict.Add(entry.Key, EVAL((MalVal)entry.Value, env)); | |
38 | } | |
39 | return new MalHashMap(new_dict); | |
40 | } else { | |
41 | return ast; | |
42 | } | |
43 | } | |
44 | ||
45 | ||
46 | static MalVal EVAL(MalVal orig_ast, Dictionary<string, MalVal> env) { | |
47 | MalVal a0; | |
b8ee29b2 | 48 | //Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true)); |
b56c49a1 JM |
49 | if (!orig_ast.list_Q()) { |
50 | return eval_ast(orig_ast, env); | |
51 | } | |
52 | ||
53 | // apply list | |
54 | MalList ast = (MalList)orig_ast; | |
55 | if (ast.size() == 0) { return ast; } | |
8cb5cda4 | 56 | a0 = ast[0]; |
b56c49a1 JM |
57 | if (!(a0 is MalSymbol)) { |
58 | throw new Mal.types.MalError("attempt to apply on non-symbol '" | |
59 | + Mal.printer._pr_str(a0,true) + "'"); | |
60 | } | |
b18969c0 | 61 | var el = (MalList)eval_ast(ast, env); |
c3b508af | 62 | var f = (MalFunc)el[0]; |
b18969c0 | 63 | return f.apply(el.rest()); |
b56c49a1 JM |
64 | |
65 | } | |
66 | ||
67 | ||
68 | static string PRINT(MalVal exp) { | |
69 | return printer._pr_str(exp, true); | |
70 | } | |
71 | ||
86b689f3 | 72 | // repl |
b56c49a1 | 73 | static void Main(string[] args) { |
b56c49a1 | 74 | var repl_env = new Dictionary<string, MalVal> { |
c3b508af JM |
75 | {"+", new MalFunc(a => (MalInt)a[0] + (MalInt)a[1]) }, |
76 | {"-", new MalFunc(a => (MalInt)a[0] - (MalInt)a[1]) }, | |
77 | {"*", new MalFunc(a => (MalInt)a[0] * (MalInt)a[1]) }, | |
78 | {"/", new MalFunc(a => (MalInt)a[0] / (MalInt)a[1]) }, | |
b56c49a1 | 79 | }; |
c3b508af | 80 | Func<string, MalVal> RE = (string str) => EVAL(READ(str), repl_env); |
8cb5cda4 | 81 | |
b56c49a1 JM |
82 | if (args.Length > 0 && args[0] == "--raw") { |
83 | Mal.readline.mode = Mal.readline.Mode.Raw; | |
84 | } | |
c3b508af JM |
85 | |
86 | // repl loop | |
b56c49a1 JM |
87 | while (true) { |
88 | string line; | |
89 | try { | |
c3b508af | 90 | line = Mal.readline.Readline("user> "); |
b56c49a1 | 91 | if (line == null) { break; } |
c3b508af | 92 | if (line == "") { continue; } |
b56c49a1 JM |
93 | } catch (IOException e) { |
94 | Console.WriteLine("IOException: " + e.Message); | |
95 | break; | |
96 | } | |
97 | try { | |
c3b508af | 98 | Console.WriteLine(PRINT(RE(line))); |
b56c49a1 JM |
99 | } catch (Mal.types.MalContinue) { |
100 | continue; | |
b56c49a1 JM |
101 | } catch (Exception e) { |
102 | Console.WriteLine("Error: " + e.Message); | |
8cb5cda4 | 103 | Console.WriteLine(e.StackTrace); |
b56c49a1 JM |
104 | continue; |
105 | } | |
106 | } | |
107 | } | |
108 | } | |
109 | } |