2 import types
.Types
.MalType
;
4 import types
.MalException
;
12 static function READ(str
:String
):MalType
{
13 return Reader
.read_str(str
);
17 static function eval_ast(ast
:MalType
, env
:Env
) {
19 case MalSymbol(s
): env
.get(ast
);
21 MalList(l
.map(function(x
) { return EVAL(x
, env
); }));
23 MalVector(l
.map(function(x
) { return EVAL(x
, env
); }));
25 var new_map
= new Map
<String
,MalType
>();
27 new_map
[k
] = EVAL(m
[k
], env
);
34 static function EVAL(ast
:MalType
, env
:Env
):MalType
{
36 if (!list_Q(ast
)) { return eval_ast(ast
, env
); }
39 var alst
= _list(ast
);
40 if (alst
.length
== 0) { return ast
; }
43 case MalSymbol("def!"):
44 return env
.set(alst
[1], EVAL(alst
[2], env
));
45 case MalSymbol("let*"):
46 var let_env
= new Env(env
);
48 case MalList(l
) |
MalVector(l
):
49 for (i
in 0...l
.length
) {
50 if ((i
%2) > 0) { continue; }
51 let_env
.set(l
[i
], EVAL(l
[i
+1], let_env
));
53 case _
: throw "Invalid let*";
59 var el
= eval_ast(MalList(alst
.slice(1, alst
.length
-1)), env
);
63 var cond
= EVAL(alst
[1], env
);
64 if (cond
!= MalFalse
&& cond
!= MalNil
) {
66 } else if (alst
.length
> 3) {
72 case MalSymbol("fn*"):
73 return MalFunc(function (args
) {
74 return EVAL(alst
[2], new Env(env
, _list(alst
[1]), args
));
75 },alst
[2],env
,alst
[1],false,nil
);
77 var el
= eval_ast(ast
, env
);
80 case MalFunc(f
,a
,e
,params
,_
,_
):
81 var args
= _list(el
).slice(1);
84 env
= new Env(e
, _list(params
), args
);
89 case _
: throw "Call of non-function";
96 static function PRINT(exp
:MalType
):String
{
97 return Printer
.pr_str(exp
, true);
101 static var repl_env
= new Env(null);
103 static function rep(line
:String
):String
{
104 return PRINT(EVAL(READ(line
), repl_env
));
107 public static function main() {
108 // core.EXT: defined using Haxe
109 for (k
in Core
.ns
.keys()) {
110 repl_env
.set(MalSymbol(k
), MalFunc(Core
.ns
[k
],null,null,null,false,nil
));
113 var evalfn
= MalFunc(function(args
) {
114 return EVAL(args
[0], repl_env
);
115 },null,null,null,false,nil
);
116 repl_env
.set(MalSymbol("eval"), evalfn
);
118 var cmdargs
= Compat
.cmdline_args();
119 var argarray
= cmdargs
.map(function(a
) { return MalString(a
); });
120 repl_env
.set(MalSymbol("*ARGV*"), MalList(argarray
.slice(1)));
122 // core.mal: defined using the language itself
123 rep("(def! not (fn* (a) (if a false true)))");
124 rep("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))");
126 if (cmdargs
.length
> 0) {
127 rep('(load-file "${cmdargs[0]}")');
133 var line
= Compat
.readline("user> ");
134 if (line
== "") { continue; }
135 Compat
.println(rep(line
));
136 } catch (exc
:BlankLine
) {
138 } catch (exc
:haxe
.io
.Eof
) {
140 } catch (exc
:Dynamic) {
141 if (Type
.getClass(exc
) == MalException
) {
142 Compat
.println("Error: " + Printer
.pr_str(exc
.obj
, true));
144 Compat
.println("Error: " + exc
);