4 import types
.Types
.MalType
;
6 import types
.MalException
;
7 import printer
.Printer
;
11 static function BoolFn(v
) {
12 if (v
) { return MalTrue
; }
13 else { return MalFalse
; }
16 static function BoolOp(op
) {
17 return function(args
:Array
<MalType
>) {
18 return switch (args
) {
19 case [MalInt(a
), MalInt(b
)]: BoolFn(op(a
,b
));
20 case _
: throw "Invalid boolean op call";
26 static function NumOp(op
) {
27 return function(args
:Array
<MalType
>) {
28 return switch (args
) {
29 case [MalInt(a
), MalInt(b
)]: MalInt(op(a
,b
));
30 case _
: throw "Invalid numeric op call";
36 static function equal_Q(args
) {
37 return BoolFn(_equal_Q(args
[0],args
[1]));
40 static function pr_str(args
) {
42 args
.map(function(s
) { return Printer
.pr_str(s
,true); }).join(" ")
45 static function str(args
) {
47 args
.map(function(s
) { return Printer
.pr_str(s
,false); }).join("")
50 static function prn(args
) {
51 Compat
.println(args
.map(function(s
) { return Printer
.pr_str(s
,true); }).join(" "));
54 static function println(args
) {
55 Compat
.println(args
.map(function(s
) { return Printer
.pr_str(s
,false); }).join(" "));
59 static function symbol(args
) {
60 return switch (args
[0]) {
61 case MalString(s
): MalSymbol(s
);
62 case MalSymbol(_
): args
[0];
63 case _
: throw "Invalid symbol call";
67 static function keyword(args
) {
68 return switch (args
[0]) {
70 if (keyword_Q(args
[0])) {
73 MalString("\x7f" + s
);
75 case _
: throw "Invalid keyword call";
79 static function read_string(args
) {
80 return switch (args
[0]) {
81 case MalString(s
): Reader
.read_str(s
);
82 case _
: throw "invalid read_str call";
86 static function readline(args
) {
87 return switch (args
[0]) {
88 case MalString(prompt
):
90 MalString(Compat
.readline(prompt
));
91 } catch (exc
:haxe
.io
.Eof
) {
94 case _
: throw "invalid readline call";
98 static function slurp(args
) {
99 return switch (args
[0]) {
101 MalString(Compat
.slurp(s
));
102 case _
: throw "invalid slurp call";
106 // sequential functions
107 static function sequential_Q(args
) {
108 return BoolFn(list_Q(args
[0]) ||
vector_Q(args
[0]));
111 static function cons(args
) {
112 return switch [args
[0], args
[1]] {
113 case [a
, MalList(l
)] |
115 MalList([a
].concat(l
));
118 case _
: throw "Invalid cons call";
122 static function do_concat(args
:Array
<MalType
>) {
123 var res
:Array
<MalType
> = [];
126 case MalList(l
) |
MalVector(l
):
131 throw "concat called with non-sequence";
137 static function nth(args
) {
138 return switch [args
[0], args
[1]] {
139 case [seq
, MalInt(idx
)]:
141 case _
: throw "Invalid nth call";
145 static function empty_Q(args
) {
146 return switch (args
[0]) {
147 case MalList(l
) |
MalVector(l
):
148 if (l
.length
== 0) { MalTrue
; }
150 case MalNil
: MalTrue
;
155 static function count(args
) {
156 return switch (args
[0]) {
157 case MalList(l
) |
MalVector(l
): MalInt(l
.length
);
158 case MalNil
: MalInt(0);
159 case _
: throw "count called on non-sequence";
163 static function apply(args
) {
164 return switch [args
[0], args
[args
.length
-1]] {
165 case [MalFunc(f
,_
,_
,_
,_
), MalList(l
)] |
166 [MalFunc(f
,_
,_
,_
,_
), MalVector(l
)]:
167 var fargs
= args
.slice(1,args
.length
-1).concat(l
);
169 case _
: throw "Invalid apply call";
173 static function do_map(args
) {
174 return switch [args
[0], args
[1]] {
175 case [MalFunc(f
,_
,_
,_
,_
), MalList(l
)] |
176 [MalFunc(f
,_
,_
,_
,_
), MalVector(l
)]:
177 return MalList(l
.map(function(x
) { return f([x
]); }));
178 case _
: throw "Invalid map call";
182 // hash-map functions
184 public static function get(hm
:MalType
, key
:MalType
) {
185 return switch [hm
, key
] {
186 case [MalHashMap(m
), MalString(k
)]:
192 case [nil
, MalString(k
)]:
194 case _
: throw "invalid get call";
198 public static function assoc(args
) {
199 return switch (args
[0]) {
201 var new_m
= _clone(args
[0]);
202 MalHashMap(assoc_BANG(new_m
, args
.slice(1)));
203 case _
: throw "invalid assoc call";
207 public static function dissoc(args
) {
208 return switch (args
[0]) {
210 var new_m
= _clone(args
[0]);
211 MalHashMap(dissoc_BANG(new_m
, args
.slice(1)));
212 case _
: throw "invalid dissoc call";
216 public static function contains_Q(hm
:MalType
, key
:MalType
) {
217 return switch [hm
, key
] {
218 case [MalHashMap(m
), MalString(k
)]:
220 case _
: throw "invalid contains? call";
224 public static function keys(hm
:MalType
) {
227 MalList([for (k
in m
.keys()) MalString(k
)]);
228 case _
: throw "invalid keys call";
232 public static function vals(hm
:MalType
) {
235 MalList([for (k
in m
.keys()) m
[k
]]);
236 case _
: throw "invalid vals call";
240 // metadata functions
241 static function meta(args
) {
242 return switch (args
[0]) {
243 case MalFunc(f
,_
,_
,_
,_
,meta
): meta
;
244 case _
: throw "meta called on non-function";
248 static function with_meta(args
) {
249 return switch (args
[0]) {
250 case MalFunc(f
,a
,e
,p
,mac
,_
):
251 MalFunc(f
,a
,e
,p
,mac
,args
[1]);
252 case _
: throw "with_meta called on non-function";
260 static function deref(args
) {
261 return switch (args
[0]) {
262 case MalAtom(v
): v
.val
;
263 case _
: throw "deref called on non-atom";
267 static function reset_BANG(args
) {
268 return switch (args
[0]) {
269 case MalAtom(v
): v
.val
= args
[1];
270 case _
: throw "reset! called on non-atom";
274 static function swap_BANG(args
) {
275 return switch [args
[0], args
[1]] {
276 case [MalAtom(v
), MalFunc(f
,_
,_
,_
,_
)]:
277 var fargs
= [v
.val
].concat(args
.slice(2));
280 case _
: throw "swap! called on non-atom";
285 public static var ns
:Map
<String
,Array
<MalType
> -> MalType
> = [
286 "=" => function(a
) { return BoolFn(_equal_Q(a
[0],a
[1])); },
287 "throw" => function(a
) { throw new MalException(a
[0]); },
289 "nil?" => function(a
) { return BoolFn(nil_Q(a
[0])); },
290 "true?" => function(a
) { return BoolFn(true_Q(a
[0])); },
291 "false?" => function(a
) { return BoolFn(false_Q(a
[0])); },
293 "symbol?" => function(a
) { return BoolFn(symbol_Q(a
[0])); },
294 "keyword" => keyword
,
295 "keyword?" => function(a
) { return BoolFn(keyword_Q(a
[0])); },
300 "println" => println
,
301 "read-string" => read_string
,
302 "readline" => readline
,
305 "<" => BoolOp(function(a
,b
) {return a
<b
;}),
306 "<=" => BoolOp(function(a
,b
) {return a
<=b
;}),
307 ">" => BoolOp(function(a
,b
) {return a
>b
;}),
308 ">=" => BoolOp(function(a
,b
) {return a
>=b
;}),
309 "+" => NumOp(function(a
,b
) {return a
+b
;}),
310 "-" => NumOp(function(a
,b
) {return a
-b
;}),
311 "*" => NumOp(function(a
,b
) {return a
*b
;}),
312 "/" => NumOp(function(a
,b
) {return Std
.int(a
/b
);}),
314 "list" => function(a
) { return MalList(a
); },
315 "list?" => function(a
) { return BoolFn(list_Q(a
[0])); },
316 "vector" => function(a
) { return MalVector(a
); },
317 "vector?" => function(a
) { return BoolFn(vector_Q(a
[0])); },
318 "hash-map" => hash_map
,
319 "map?" => function(a
) { return BoolFn(hash_map_Q(a
[0])); },
322 "get" => function(a
) { return get(a
[0],a
[1]); },
323 "contains?" => function(a
) { return BoolFn(contains_Q(a
[0], a
[1])); },
324 "keys" => function(a
) { return keys(a
[0]); } ,
325 "vals" => function(a
) { return vals(a
[0]); } ,
327 "sequential?" => sequential_Q
,
329 "concat" => do_concat
,
331 "first" => function(a
) { return first(a
[0]); },
332 "rest" => function(a
) { return MalList(_list(a
[0]).slice(1)); },
338 "conj" => function(a
) { return nil
; },
341 "with-meta" => with_meta
,
342 "atom" => function(a
) { return MalAtom({val
:a
[0]}); },
343 "atom?" => function(a
) { return BoolFn(atom_Q(a
[0])); },
345 "reset!" => reset_BANG
,