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)
156 if
(numberof
(a
) == 1) {
157 type
= structof
(*a
(1))
158 if
(type
== MalVector
) return
*(a
(1))
159 if
(type
== MalList
) return MalVector
(val
=a
(1)->val
)
161 return MalError
(message
="vec: requires a sequence")
167 if
(index
>= count
(*a
(1))) return MalError
(message
="nth: index out of range")
168 return
*((*(a
(1)->val
))(index
+ 1))
173 if
(structof
(*a
(1)) == MalNil || count
(*a
(1)) == 0) return MAL_NIL
174 return
*((*(a
(1)->val
))(1))
179 if
(structof
(*a
(1)) == MalNil
) return MalList
(val
=&[])
183 func mal_empty_q
(a
) { return new_boolean
((structof
(*a
(1)) == MalNil ?
1 : count
(*a
(1)) == 0)); }
184 func mal_count
(a
) { return MalNumber
(val
=(structof
(*a
(1)) == MalNil ?
0 : count
(*a
(1)))); }
186 func call_func
(fn
, args
)
188 if
(structof
(fn
) == MalNativeFunction
) {
189 return call_core_fn
(fn.val
, args
)
190 } else if
(structof
(fn
) == MalFunction
) {
191 fn_env
= env_new
(fn.env
, binds
=*fn.binds
, exprs
=args
)
192 return EVAL
(*fn.ast
, fn_env
)
194 return MalError
(message
="Unknown function type")
199 mid_args
= numberof
(a
) > 2 ? a
(2:-1) : []
200 return call_func
(*a
(1), grow
(mid_args
, *(a
(0)->val
)))
206 if
(numberof
(seq
) == 0) return MalList
(val
=&[])
207 new_seq
= array
(pointer
, numberof
(seq
))
208 for
(i
= 1; i
<= numberof
(seq
); ++i
) {
209 new_val
= call_func
(fn
, [seq
(i
)])
210 if
(structof
(new_val
) == MalError
) return new_val
211 new_seq
(i
) = &new_val
213 return MalList
(val
=&new_seq)
220 if
(type
== MalList
) {
222 for
(i
= 2; i
<= numberof
(a
); ++i
) {
223 res
= mal_cons
([a
(i
), &res])
226 } else if
(type
== MalVector
) {
229 return MalVector
(val
=&seq)
231 return MalError
(message
="conj requires list or vector")
239 if
(type
== MalString
) {
240 len
= strlen
(obj.val
)
241 if
(len
== 0) return MAL_NIL
242 seq
= array
(pointer
, len
)
243 for
(i
= 1; i
<= len
; ++i
) {
244 seq
(i
) = &MalString(val=strpart(obj.val, i:i))
246 return MalList
(val
=&seq)
247 } else if
(type
== MalList
) {
248 return count
(obj
) == 0 ? MAL_NIL
: obj
249 } else if
(type
== MalVector
) {
250 return count
(obj
) == 0 ? MAL_NIL
: MalList
(val
=obj.val
)
251 } else if
(type
== MalNil
) {
254 return MalError
(message
="seq requires string or list or vector or nil")
260 meta_obj
= *(a
(1)->meta
)
261 return is_void
(meta_obj
) ? MAL_NIL
: meta_obj
264 func mal_with_meta
(a
)
271 func mal_atom
(a
) { return MalAtom
(val
=&MalAtomVal(val=a(1))); }
272 func mal_atom_q
(a
) { return new_boolean
(structof
(*a
(1)) == MalAtom
); }
273 func mal_deref
(a
) { return
*(a
(1)->val-
>val
); }
274 func mal_reset_bang
(a
) { a
(1)->val-
>val
= a
(2); return
*(a
(1)->val-
>val
); }
275 func mal_swap_bang
(a
)
277 old_val
= mal_deref
([a
(1)])
278 args
= array
(pointer
, numberof
(a
) - 1)
280 if
(numberof
(a
) > 2) args
(2:) = a
(3:)
281 new_val
= call_func
(*a
(2), args
)
282 if
(structof
(new_val
) == MalError
) return new_val
283 return mal_reset_bang
([a
(1), &new_val])
286 func mal_eval
(a
) { return EVAL
(*a
(1), repl_env
); }
288 func yorick_to_mal
(e
)
290 if
(is_void
(e
)) return MAL_NIL
292 if
(is_numerical
(e
)) return MalNumber
(val
=e
)
293 else if
(is_string
(e
)) return MalString
(val
=e
)
294 else return MalString
(val
=totxt
(e
))
296 seq
= array
(pointer
, numberof
(e
))
297 for
(i
= 1; i
<= numberof
(e
); ++i
) {
298 seq
(i
) = &yorick_to_mal(e(i))
300 return MalList
(val
=&seq)
304 func mal_yorick_eval
(a
) { return yorick_to_mal
(exec
(a
(1)->val
)); }
308 h_set
, core_ns
, "=", mal_equal
309 h_set
, core_ns
, "throw", mal_throw
311 h_set
, core_ns
, "nil?", mal_nil_q
312 h_set
, core_ns
, "true?", mal_true_q
313 h_set
, core_ns
, "false?", mal_false_q
314 h_set
, core_ns
, "string?", mal_string_q
315 h_set
, core_ns
, "symbol", mal_symbol
316 h_set
, core_ns
, "symbol?", mal_symbol_q
317 h_set
, core_ns
, "keyword", mal_keyword
318 h_set
, core_ns
, "keyword?", mal_keyword_q
319 h_set
, core_ns
, "number?", mal_number_q
320 h_set
, core_ns
, "fn?", mal_fn_q
321 h_set
, core_ns
, "macro?", mal_macro_q
323 h_set
, core_ns
, "pr-str", mal_pr_str
324 h_set
, core_ns
, "str", mal_str
325 h_set
, core_ns
, "prn", mal_prn
326 h_set
, core_ns
, "println", mal_println
327 h_set
, core_ns
, "read-string", mal_read_string
328 h_set
, core_ns
, "readline", mal_readline
329 h_set
, core_ns
, "slurp", mal_slurp
331 h_set
, core_ns
, "<", mal_lt
332 h_set
, core_ns
, "<=", mal_lte
333 h_set
, core_ns
, ">", mal_gt
334 h_set
, core_ns
, ">=", mal_gte
335 h_set
, core_ns
, "+", mal_add
336 h_set
, core_ns
, "-", mal_sub
337 h_set
, core_ns
, "*", mal_mul
338 h_set
, core_ns
, "/", mal_div
339 h_set
, core_ns
, "time-ms", mal_time_ms
341 h_set
, core_ns
, "list", mal_list
342 h_set
, core_ns
, "list?", mal_list_q
343 h_set
, core_ns
, "vector", mal_vector
344 h_set
, core_ns
, "vector?", mal_vector_q
345 h_set
, core_ns
, "hash-map", mal_hash_map
346 h_set
, core_ns
, "map?", mal_map_q
347 h_set
, core_ns
, "assoc", mal_assoc
348 h_set
, core_ns
, "dissoc", mal_dissoc
349 h_set
, core_ns
, "get", mal_get
350 h_set
, core_ns
, "contains?", mal_contains_q
351 h_set
, core_ns
, "keys", mal_keys
352 h_set
, core_ns
, "vals", mal_vals
354 h_set
, core_ns
, "sequential?", mal_sequential_q
355 h_set
, core_ns
, "cons", mal_cons
356 h_set
, core_ns
, "concat", mal_concat
357 h_set
, core_ns
, "vec", mal_vec
358 h_set
, core_ns
, "nth", mal_nth
359 h_set
, core_ns
, "first", mal_first
360 h_set
, core_ns
, "rest", mal_rest
361 h_set
, core_ns
, "empty?", mal_empty_q
362 h_set
, core_ns
, "count", mal_count
363 h_set
, core_ns
, "apply", mal_apply
364 h_set
, core_ns
, "map", mal_map
366 h_set
, core_ns
, "conj", mal_conj
367 h_set
, core_ns
, "seq", mal_seq
369 h_set
, core_ns
, "meta", mal_meta
370 h_set
, core_ns
, "with-meta", mal_with_meta
371 h_set
, core_ns
, "atom", mal_atom
372 h_set
, core_ns
, "atom?", mal_atom_q
373 h_set
, core_ns
, "deref", mal_deref
374 h_set
, core_ns
, "reset!", mal_reset_bang
375 h_set
, core_ns
, "swap!", mal_swap_bang
377 h_set
, core_ns
, "eval", mal_eval
378 h_set
, core_ns
, "yorick-eval", mal_yorick_eval
380 func call_core_fn
(name
, args_list
)
382 f
= h_get
(core_ns
, name
)