Merge pull request #11 from treeform/patch-1
[jackhill/mal.git] / cs / step2_eval.cs
CommitLineData
b56c49a1
JM
1using System;
2using System.IO;
3using System.Collections;
4using System.Collections.Generic;
5using Mal;
6using MalVal = Mal.types.MalVal;
7using MalSymbol = Mal.types.MalSymbol;
c3b508af 8using MalInt = Mal.types.MalInt;
b56c49a1
JM
9using MalList = Mal.types.MalList;
10using MalVector = Mal.types.MalVector;
11using MalHashMap = Mal.types.MalHashMap;
c3b508af 12using MalFunc = Mal.types.MalFunc;
b56c49a1
JM
13
14namespace 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 // print
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}