3 using System
.Collections
;
4 using System
.Collections
.Generic
;
6 using MalVal
= Mal
.types
.MalVal
;
7 using MalString
= Mal
.types
.MalString
;
8 using MalSymbol
= Mal
.types
.MalSymbol
;
9 using MalInteger
= Mal
.types
.MalInteger
;
10 using MalList
= Mal
.types
.MalList
;
11 using MalVector
= Mal
.types
.MalVector
;
12 using MalHashMap
= Mal
.types
.MalHashMap
;
13 using MalFunction
= Mal
.types
.MalFunction
;
14 using Env
= Mal
.env
.Env
;
19 static MalVal
READ(string str
) {
20 return reader
.read_str(str
);
24 static MalVal
eval_ast(MalVal ast
, Env env
) {
25 if (ast
is MalSymbol
) {
26 MalSymbol sym
= (MalSymbol
)ast
;
27 return env
.get(sym
.getName());
28 } else if (ast
is MalList
) {
29 MalList old_lst
= (MalList
)ast
;
30 MalList new_lst
= ast
.list_Q() ? new MalList()
31 : (MalList
)new MalVector();
32 foreach (MalVal mv
in old_lst
.getValue()) {
33 new_lst
.conj_BANG(EVAL(mv
, env
));
36 } else if (ast
is MalHashMap
) {
37 var new_dict
= new Dictionary
<string, MalVal
>();
38 foreach (var entry
in ((MalHashMap
)ast
).getValue()) {
39 new_dict
.Add(entry
.Key
, EVAL((MalVal
)entry
.Value
, env
));
41 return new MalHashMap(new_dict
);
48 static MalVal
EVAL(MalVal orig_ast
, Env env
) {
49 MalVal a0
, a1
, a2
, res
;
54 //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
55 if (!orig_ast
.list_Q()) {
56 return eval_ast(orig_ast
, env
);
60 MalList ast
= (MalList
)orig_ast
;
61 if (ast
.size() == 0) { return ast; }
64 String a0sym
= a0
is MalSymbol
? ((MalSymbol
)a0
).getName()
72 env
.set(((MalSymbol
)a1
).getName(), res
);
79 Env let_env
= new Env(env
);
80 for(int i
=0; i
<((MalList
)a1
).size(); i
+=2) {
81 key
= (MalSymbol
)((MalList
)a1
)[i
];
82 val
= ((MalList
)a1
)[i
+1];
83 let_env
.set(key
.getName(), EVAL(val
, let_env
));
89 eval_ast(ast
.slice(1, ast
.size()-1), env
);
90 orig_ast
= ast
[ast
.size()-1];
94 MalVal cond
= EVAL(a1
, env
);
95 if (cond
== Mal
.types
.Nil
|| cond
== Mal
.types
.False
) {
96 // eval false slot form
100 return Mal
.types
.Nil
;
103 // eval true slot form
108 MalList a1f
= (MalList
)ast
[1];
111 return new MalFunction(a2f
, env
, a1f
,
112 args
=> EVAL(a2f
, new Env(cur_env
, a1f
, args
)) );
114 el
= (MalList
)eval_ast(ast
, env
);
115 var f
= (MalFunction
)el
[0];
116 MalVal fnast
= f
.getAst();
119 env
= f
.genEnv(el
.rest());
121 return f
.apply(el
.rest());
130 static string PRINT(MalVal exp
) {
131 return printer
._pr_str(exp
, true);
135 static MalVal
RE(Env env
, string str
) {
136 return EVAL(READ(str
), env
);
139 static void Main(string[] args
) {
140 string prompt
= "user> ";
142 // core.cs: defined using C#
143 var repl_env
= new env
.Env(null);
144 foreach (var entry
in core
.ns
) {
145 repl_env
.set(entry
.Key
, entry
.Value
);
147 repl_env
.set("eval", new MalFunction(a
=> EVAL(a
[0], repl_env
)));
148 MalList _argv
= new MalList();
149 for (int i
=1; i
< args
.Length
; i
++) {
150 _argv
.conj_BANG(new MalString(args
[i
]));
152 repl_env
.set("*ARGV*", _argv
);
154 // core.mal: defined using the language itself
155 RE(repl_env
, "(def! not (fn* (a) (if a false true)))");
156 RE(repl_env
, "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))");
159 if (args
.Length
> 0 && args
[0] == "--raw") {
160 Mal
.readline
.mode
= Mal
.readline
.Mode
.Raw
;
163 if (args
.Length
> fileIdx
) {
164 RE(repl_env
, "(load-file \"" + args
[fileIdx
] + "\")");
172 line
= Mal
.readline
.Readline(prompt
);
173 if (line
== null) { break; }
174 } catch (IOException e
) {
175 Console
.WriteLine("IOException: " + e
.Message
);
179 Console
.WriteLine(PRINT(RE(repl_env
, line
)));
180 } catch (Mal
.types
.MalContinue
) {
182 } catch (Exception e
) {
183 Console
.WriteLine("Error: " + e
.Message
);
184 Console
.WriteLine(e
.StackTrace
);