3 func mal_equal
(a
) { return new_boolean
(equal
(*a
(1), *a
(2))); }
4 func mal_throw
(a
) { return MalError
(obj
=a
(1)); }
6 func mal_nil_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalNil
); }
7 func mal_true_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalTrue
); }
8 func mal_false_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalFalse
); }
9 func mal_string_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalString
); }
10 func mal_symbol
(a
) { return MalSymbol
(val
=a
(1)->val
); }
11 func mal_symbol_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalSymbol
); }
12 func mal_keyword
(a
) { return MalKeyword
(val
=a
(1)->val
); }
13 func mal_keyword_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalKeyword
); }
14 func mal_number_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalNumber
); }
17 if
(structof
(*a
(1)) == MalNativeFunction
) return MAL_TRUE
;
18 return new_boolean
(structof
(*a
(1)) == MalFunction
&& !a(1)->macro);
20 func mal_macro_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalFunction
&& a(1)->macro); }
22 func string_helper
(a
, delimiter
, readable
)
25 for
(i
= 1; i
<= numberof
(a
); ++i
) {
26 if
(i
> 1) res
+= delimiter
27 res
+= pr_str
(*a
(i
), readable
)
32 func mal_pr_str
(a
) { return MalString
(val
=string_helper
(a
, " ", 1)); }
33 func mal_str
(a
) { return MalString
(val
=string_helper
(a
, "", 0)); }
34 func mal_prn
(a
) { write
, format
="%s\n", string_helper
(a
, " ", 1); return MAL_NIL
; }
35 func mal_println
(a
) { write
, format
="%s\n", string_helper
(a
, " ", 0); return MAL_NIL
; }
36 func mal_read_string
(a
) { return read_str
(a
(1)->val
); }
41 stdin_file
= open
("/dev/stdin", "r")
42 write
, format
="%s", a
(1)->val
43 line
= rdline
(stdin_file
, prompt
="")
44 return line ? MalString
(val
=line
) : MAL_NIL
53 for
(i
= 1; i
<= numberof
(lines
); ++i
) {
54 s
+= (lines
(i
) + "\n")
56 return MalString
(val
=s
)
59 func mal_lt
(a
) { return new_boolean
(a
(1)->val
< a
(2)->val
); }
60 func mal_lte
(a
) { return new_boolean
(a
(1)->val
<= a
(2)->val
); }
61 func mal_gt
(a
) { return new_boolean
(a
(1)->val
> a
(2)->val
); }
62 func mal_gte
(a
) { return new_boolean
(a
(1)->val
>= a
(2)->val
); }
64 func mal_add
(a
) { return MalNumber
(val
=(a
(1)->val
+ a
(2)->val
)); }
65 func mal_sub
(a
) { return MalNumber
(val
=(a
(1)->val
- a
(2)->val
)); }
66 func mal_mul
(a
) { return MalNumber
(val
=(a
(1)->val
* a
(2)->val
)); }
67 func mal_div
(a
) { return MalNumber
(val
=(a
(1)->val
/ a
(2)->val
)); }
71 elapsed
= array
(double
, 3)
73 return MalNumber
(val
=floor
(elapsed
(3) * 1000))
76 func mal_list
(a
) { return MalList
(val
=&a); }
77 func mal_list_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalList
); }
78 func mal_vector
(a
) { return MalVector
(val
=&a); }
79 func mal_vector_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalVector
); }
80 func mal_hash_map
(a
) { return array_to_hashmap
(a
); }
81 func mal_map_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalHashmap
); }
87 new_h
= Hash
(keys
=&k1, vals=&v1)
88 for
(i
= 2; i
<= numberof
(a
); i
+= 2) {
89 hash_set
, new_h
, hashmap_obj_to_key
(*a
(i
)), *a
(i
+ 1)
91 return MalHashmap
(val
=&new_h);
98 new_h
= Hash
(keys
=&k1, vals=&v1)
99 for
(i
= 2; i
<= numberof
(a
); ++i
) {
100 hash_delete
, new_h
, hashmap_obj_to_key
(*a
(i
))
102 return MalHashmap
(val
=&new_h);
106 if
(structof
(*a
(1)) == MalNil
) return MAL_NIL
109 val
= hash_get
(h
, hashmap_obj_to_key
(key_obj
))
110 return is_void
(val
) ? MAL_NIL
: val
113 func mal_contains_q
(a
) {
114 if
(structof
(*a
(1)) == MalNil
) return MAL_FALSE
117 return hash_has_key
(h
, hashmap_obj_to_key
(key_obj
)) ? MAL_TRUE
: MAL_FALSE
121 keys_strs
= *(a
(1)->val-
>keys
)
122 if
(numberof
(keys_strs
) == 0) return MalList
(val
=&[])
123 res
= array
(pointer
, numberof
(keys_strs
))
124 for
(i
= 1; i
<= numberof
(keys_strs
); ++i
) {
125 res
(i
) = &hashmap_key_to_obj(keys_strs(i))
127 return MalList
(val
=&res);
130 func mal_vals
(a
) { return MalList
(val
=a
(1)->val-
>vals
); }
132 func mal_sequential_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalList || structof
(*a
(1)) == MalVector
); }
136 a2_len
= count
(*a
(2))
137 seq
= array
(pointer
, a2_len
+ 1)
140 seq
(2:) = *(a
(2)->val
)
142 return MalList
(val
=&seq)
148 for
(i
= 1; i
<= numberof
(a
); ++i
) {
149 grow
, seq
, *(a
(i
)->val
)
151 return MalList
(val
=&seq)
157 if
(index
>= count
(*a
(1))) return MalError
(message
="nth: index out of range")
158 return
*((*(a
(1)->val
))(index
+ 1))
163 if
(structof
(*a
(1)) == MalNil || count
(*a
(1)) == 0) return MAL_NIL
164 return
*((*(a
(1)->val
))(1))
169 if
(structof
(*a
(1)) == MalNil
) return MalList
(val
=&[])
173 func mal_empty_q
(a
) { return new_boolean
((structof
(*a
(1)) == MalNil ?
1 : count
(*a
(1)) == 0)); }
174 func mal_count
(a
) { return MalNumber
(val
=(structof
(*a
(1)) == MalNil ?
0 : count
(*a
(1)))); }
176 func call_func
(fn
, args
)
178 if
(structof
(fn
) == MalNativeFunction
) {
179 return call_core_fn
(fn.val
, args
)
180 } else if
(structof
(fn
) == MalFunction
) {
181 fn_env
= env_new
(fn.env
, binds
=*fn.binds
, exprs
=args
)
182 return EVAL
(*fn.ast
, fn_env
)
184 return MalError
(message
="Unknown function type")
189 mid_args
= numberof
(a
) > 2 ? a
(2:-1) : []
190 return call_func
(*a
(1), grow
(mid_args
, *(a
(0)->val
)))
196 if
(numberof
(seq
) == 0) return MalList
(val
=&[])
197 new_seq
= array
(pointer
, numberof
(seq
))
198 for
(i
= 1; i
<= numberof
(seq
); ++i
) {
199 new_val
= call_func
(fn
, [seq
(i
)])
200 if
(structof
(new_val
) == MalError
) return new_val
201 new_seq
(i
) = &new_val
203 return MalList
(val
=&new_seq)
210 if
(type
== MalList
) {
212 for
(i
= 2; i
<= numberof
(a
); ++i
) {
213 res
= mal_cons
([a
(i
), &res])
216 } else if
(type
== MalVector
) {
219 return MalVector
(val
=&seq)
221 return MalError
(message
="conj requires list or vector")
229 if
(type
== MalString
) {
230 len
= strlen
(obj.val
)
231 if
(len
== 0) return MAL_NIL
232 seq
= array
(pointer
, len
)
233 for
(i
= 1; i
<= len
; ++i
) {
234 seq
(i
) = &MalString(val=strpart(obj.val, i:i))
236 return MalList
(val
=&seq)
237 } else if
(type
== MalList
) {
238 return count
(obj
) == 0 ? MAL_NIL
: obj
239 } else if
(type
== MalVector
) {
240 return count
(obj
) == 0 ? MAL_NIL
: MalList
(val
=obj.val
)
241 } else if
(type
== MalNil
) {
244 return MalError
(message
="seq requires string or list or vector or nil")
250 meta_obj
= *(a
(1)->meta
)
251 return is_void
(meta_obj
) ? MAL_NIL
: meta_obj
254 func mal_with_meta
(a
)
261 func mal_atom
(a
) { return MalAtom
(val
=&MalAtomVal(val=a(1))); }
262 func mal_atom_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalAtom
); }
263 func mal_deref
(a
) { return
*(a
(1)->val-
>val
); }
264 func mal_reset_bang
(a
) { a
(1)->val-
>val
= a
(2); return
*(a
(1)->val-
>val
); }
265 func mal_swap_bang
(a
)
267 old_val
= mal_deref
([a
(1)])
268 args
= array
(pointer
, numberof
(a
) - 1)
270 if
(numberof
(a
) > 2) args
(2:) = a
(3:)
271 new_val
= call_func
(*a
(2), args
)
272 if
(structof
(new_val
) == MalError
) return new_val
273 return mal_reset_bang
([a
(1), &new_val])
276 func mal_eval
(a
) { return EVAL
(*a
(1), repl_env
); }
278 func yorick_to_mal
(e
)
280 if
(is_void
(e
)) return MAL_NIL
282 if
(is_numerical
(e
)) return MalNumber
(val
=e
)
283 else if
(is_string
(e
)) return MalString
(val
=e
)
284 else return MalString
(val
=totxt
(e
))
286 seq
= array
(pointer
, numberof
(e
))
287 for
(i
= 1; i
<= numberof
(e
); ++i
) {
288 seq
(i
) = &yorick_to_mal(e(i))
290 return MalList
(val
=&seq)
294 func mal_yorick_eval
(a
) { return yorick_to_mal
(exec
(a
(1)->val
)); }
298 h_set
, core_ns
, "=", mal_equal
299 h_set
, core_ns
, "throw", mal_throw
301 h_set
, core_ns
, "nil?", mal_nil_q
302 h_set
, core_ns
, "true?", mal_true_q
303 h_set
, core_ns
, "false?", mal_false_q
304 h_set
, core_ns
, "string?", mal_string_q
305 h_set
, core_ns
, "symbol", mal_symbol
306 h_set
, core_ns
, "symbol?", mal_symbol_q
307 h_set
, core_ns
, "keyword", mal_keyword
308 h_set
, core_ns
, "keyword?", mal_keyword_q
309 h_set
, core_ns
, "number?", mal_number_q
310 h_set
, core_ns
, "fn?", mal_fn_q
311 h_set
, core_ns
, "macro?", mal_macro_q
313 h_set
, core_ns
, "pr-str", mal_pr_str
314 h_set
, core_ns
, "str", mal_str
315 h_set
, core_ns
, "prn", mal_prn
316 h_set
, core_ns
, "println", mal_println
317 h_set
, core_ns
, "read-string", mal_read_string
318 h_set
, core_ns
, "readline", mal_readline
319 h_set
, core_ns
, "slurp", mal_slurp
321 h_set
, core_ns
, "<", mal_lt
322 h_set
, core_ns
, "<=", mal_lte
323 h_set
, core_ns
, ">", mal_gt
324 h_set
, core_ns
, ">=", mal_gte
325 h_set
, core_ns
, "+", mal_add
326 h_set
, core_ns
, "-", mal_sub
327 h_set
, core_ns
, "*", mal_mul
328 h_set
, core_ns
, "/", mal_div
329 h_set
, core_ns
, "time-ms", mal_time_ms
331 h_set
, core_ns
, "list", mal_list
332 h_set
, core_ns
, "list?", mal_list_q
333 h_set
, core_ns
, "vector", mal_vector
334 h_set
, core_ns
, "vector?", mal_vector_q
335 h_set
, core_ns
, "hash-map", mal_hash_map
336 h_set
, core_ns
, "map?", mal_map_q
337 h_set
, core_ns
, "assoc", mal_assoc
338 h_set
, core_ns
, "dissoc", mal_dissoc
339 h_set
, core_ns
, "get", mal_get
340 h_set
, core_ns
, "contains?", mal_contains_q
341 h_set
, core_ns
, "keys", mal_keys
342 h_set
, core_ns
, "vals", mal_vals
344 h_set
, core_ns
, "sequential?", mal_sequential_q
345 h_set
, core_ns
, "cons", mal_cons
346 h_set
, core_ns
, "concat", mal_concat
347 h_set
, core_ns
, "nth", mal_nth
348 h_set
, core_ns
, "first", mal_first
349 h_set
, core_ns
, "rest", mal_rest
350 h_set
, core_ns
, "empty?", mal_empty_q
351 h_set
, core_ns
, "count", mal_count
352 h_set
, core_ns
, "apply", mal_apply
353 h_set
, core_ns
, "map", mal_map
355 h_set
, core_ns
, "conj", mal_conj
356 h_set
, core_ns
, "seq", mal_seq
358 h_set
, core_ns
, "meta", mal_meta
359 h_set
, core_ns
, "with-meta", mal_with_meta
360 h_set
, core_ns
, "atom", mal_atom
361 h_set
, core_ns
, "atom?", mal_atom_q
362 h_set
, core_ns
, "deref", mal_deref
363 h_set
, core_ns
, "reset!", mal_reset_bang
364 h_set
, core_ns
, "swap!", mal_swap_bang
366 h_set
, core_ns
, "eval", mal_eval
367 h_set
, core_ns
, "yorick-eval", mal_yorick_eval
369 func call_core_fn
(name
, args_list
)
371 f
= h_get
(core_ns
, name
)