2 load "../logo/reader.lg
3 load "../logo/printer.lg
5 make "global_exception []
8 output ifelse :bool [true_new] [false_new]
12 output bool_to_mal equal_q :a :b
16 make "global_exception :a
17 (throw "error "_mal_exception_)
21 output bool_to_mal ((obj_type :a) = "nil)
25 output bool_to_mal ((obj_type :a) = "true)
29 output bool_to_mal ((obj_type :a) = "false)
33 output bool_to_mal ((obj_type :a) = "string)
37 output symbol_new obj_val :a
41 output bool_to_mal ((obj_type :a) = "symbol)
45 output obj_new "keyword obj_val :a
49 output bool_to_mal ((obj_type :a) = "keyword)
53 output bool_to_mal ((obj_type :a) = "number)
58 [[nativefn] output true_new ]
59 [[fn] output bool_to_mal not fn_is_macro :a]
60 [else output false_new ]
65 if ((obj_type :a) = "fn) [ output bool_to_mal fn_is_macro :a ]
70 output obj_new "string pr_seq :args "true " " :space_char
74 output obj_new "string pr_seq :args "false " " "
78 print pr_seq :args "true " " :space_char
82 to mal_println [:args]
83 print pr_seq :args "false " " :space_char
87 to mal_read_string :str
88 output read_str obj_val :str
91 to mal_readline :prompt
92 localmake "line readline obj_val :prompt
93 if :line=[] [output nil_new]
94 output obj_new "string :line
102 make "content word :content readchar
105 output obj_new "string :content
109 output bool_to_mal ((obj_val :a) < (obj_val :b))
113 output bool_to_mal ((obj_val :a) <= (obj_val :b))
117 output bool_to_mal ((obj_val :a) > (obj_val :b))
121 output bool_to_mal ((obj_val :a) >= (obj_val :b))
125 output obj_new "number ((obj_val :a) + (obj_val :b))
129 output obj_new "number ((obj_val :a) - (obj_val :b))
133 output obj_new "number ((obj_val :a) * (obj_val :b))
137 output obj_new "number ((obj_val :a) / (obj_val :b))
141 ; Native function timems is added to coms.c (see Dockerfile)
142 output obj_new "number timems
146 output obj_new "list :args
150 output bool_to_mal ((obj_type :a) = "list)
153 to mal_vector [:args]
154 output obj_new "vector :args
158 output bool_to_mal ((obj_type :a) = "vector)
161 to mal_hash_map [:args]
164 while [:i < count :args] [
165 make "h hashmap_put :h item :i :args item (:i + 1) :args
168 output obj_new "hashmap :h
172 output bool_to_mal ((obj_type :a) = "hashmap)
175 to mal_assoc :map [:args]
176 localmake "h obj_val :map
178 while [:i < count :args] [
179 make "h hashmap_put :h item :i :args item (:i + 1) :args
182 output obj_new "hashmap :h
185 to mal_dissoc :map [:args]
186 localmake "h obj_val :map
187 foreach :args [make "h hashmap_delete :h ?]
188 output obj_new "hashmap :h
192 localmake "val hashmap_get obj_val :map :key
193 if emptyp :val [output nil_new]
197 to mal_contains_q :map :key
198 localmake "val hashmap_get obj_val :map :key
199 output bool_to_mal not emptyp :val
203 localmake "h obj_val :map
206 while [:i <= count :h] [
207 make "keys lput item :i :h :keys
210 output obj_new "list :keys
214 localmake "h obj_val :map
217 while [:i <= count :h] [
218 make "values lput item :i :h :values
221 output obj_new "list :values
224 to mal_sequential_q :a
225 output bool_to_mal sequentialp :a
229 output obj_new "list fput :a obj_val :b
232 to mal_concat [:args]
233 output obj_new "list apply "sentence map [obj_val ?] :args
237 if (obj_val :i) >= _count :a [(throw "error [nth: index out of range])]
238 output nth :a obj_val :i
243 [[(obj_type :a) = "nil] nil_new]
244 [[(_count :a) = 0] nil_new]
245 [else first obj_val :a]
250 output obj_new "list cond [
251 [[(obj_type :a) = "nil] []]
252 [[(_count :a) = 0] []]
253 [else butfirst obj_val :a]
258 output bool_to_mal (emptyp obj_val :a)
262 output obj_new "number _count :a
265 to mal_apply :f [:args]
266 localmake "callargs obj_new "list sentence butlast :args obj_val last :args
267 output invoke_fn :f :callargs
271 output obj_new "list map [invoke_fn :f obj_new "list (list ?)] obj_val :seq
274 to mal_conj :a0 [:rest]
276 [[list] localmake "newlist :a0
277 foreach :rest [make "newlist mal_cons ? :newlist]
279 [[vector] output obj_new "vector sentence obj_val :a0 :rest ]
280 [else (throw "error [conj requires list or vector]) ]
287 if (_count :a) = 0 [output nil_new]
289 foreach obj_val :a [ make "chars lput obj_new "string ? :chars ]
290 output obj_new "list :chars ]
292 if (_count :a) = 0 [output nil_new]
295 if (_count :a) = 0 [output nil_new]
296 output obj_new "list obj_val :a ]
297 [[nil] output nil_new ]
298 [else (throw "error [seq requires string or list or vector or nil]) ]
303 localmake "m obj_meta :a
304 if emptyp :m [output nil_new]
308 to mal_with_meta :a :new_meta
309 localmake "m ifelse (obj_type :new_meta) = "nil [[]] [:new_meta]
310 output obj_new_with_meta obj_type :a obj_val :a :m
314 output obj_new "atom :a
318 output bool_to_mal ((obj_type :a) = "atom)
325 to mal_reset_bang :a :val
326 .setfirst butfirst :a :val
330 to invoke_fn :f :callargs
331 output case obj_type :f [
333 apply obj_val :f obj_val :callargs ]
335 _eval fn_body :f env_new fn_env :f fn_args :f :callargs ]
337 (throw "error [Wrong type for apply])]
341 to mal_swap_bang :atom :f [:args]
342 localmake "callargs obj_new "list fput mal_deref :atom :args
343 output mal_reset_bang :atom invoke_fn :f :callargs
348 [[:a = "true] true_new]
349 [[:a = "false] false_new]
350 [[numberp :a] obj_new "number :a]
351 [[wordp :a] obj_new "string :a]
352 [[listp :a] obj_new "list map [logo_to_mal ?] :a]
357 to mal_logo_eval :str
358 make "res runresult obj_val :str
359 if emptyp :res [output nil_new]
360 output logo_to_mal first :res
364 [[symbol =] [nativefn mal_equal_q]]
365 [[symbol throw] [nativefn mal_throw]]
367 [[symbol nil?] [nativefn mal_nil_q]]
368 [[symbol true?] [nativefn mal_true_q]]
369 [[symbol false?] [nativefn mal_false_q]]
370 [[symbol string?] [nativefn mal_string_q]]
371 [[symbol symbol] [nativefn mal_symbol]]
372 [[symbol symbol?] [nativefn mal_symbol_q]]
373 [[symbol keyword] [nativefn mal_keyword]]
374 [[symbol keyword?] [nativefn mal_keyword_q]]
375 [[symbol number?] [nativefn mal_number_q]]
376 [[symbol fn?] [nativefn mal_fn_q]]
377 [[symbol macro?] [nativefn mal_macro_q]]
379 [[symbol pr-str] [nativefn mal_pr_str]]
380 [[symbol str] [nativefn mal_str]]
381 [[symbol prn] [nativefn mal_prn]]
382 [[symbol println] [nativefn mal_println]]
383 [[symbol read-string] [nativefn mal_read_string]]
384 [[symbol readline] [nativefn mal_readline]]
385 [[symbol slurp] [nativefn mal_slurp]]
387 [[symbol <] [nativefn mal_lt]]
388 [[symbol <=] [nativefn mal_lte]]
389 [[symbol >] [nativefn mal_gt]]
390 [[symbol >=] [nativefn mal_gte]]
391 [[symbol +] [nativefn mal_add]]
392 [[symbol -] [nativefn mal_sub]]
393 [[symbol *] [nativefn mal_mul]]
394 [[symbol /] [nativefn mal_div]]
395 [[symbol time-ms] [nativefn mal_time_ms]]
397 [[symbol list] [nativefn mal_list]]
398 [[symbol list?] [nativefn mal_list_q]]
399 [[symbol vector] [nativefn mal_vector]]
400 [[symbol vector?] [nativefn mal_vector_q]]
401 [[symbol hash-map] [nativefn mal_hash_map]]
402 [[symbol map?] [nativefn mal_map_q]]
403 [[symbol assoc] [nativefn mal_assoc]]
404 [[symbol dissoc] [nativefn mal_dissoc]]
405 [[symbol get] [nativefn mal_get]]
406 [[symbol contains?] [nativefn mal_contains_q]]
407 [[symbol keys] [nativefn mal_keys]]
408 [[symbol vals] [nativefn mal_vals]]
410 [[symbol sequential?] [nativefn mal_sequential_q]]
411 [[symbol cons] [nativefn mal_cons]]
412 [[symbol concat] [nativefn mal_concat]]
413 [[symbol nth] [nativefn mal_nth]]
414 [[symbol first] [nativefn mal_first]]
415 [[symbol rest] [nativefn mal_rest]]
416 [[symbol empty?] [nativefn mal_empty_q]]
417 [[symbol count] [nativefn mal_count]]
418 [[symbol apply] [nativefn mal_apply]]
419 [[symbol map] [nativefn mal_map]]
421 [[symbol conj] [nativefn mal_conj]]
422 [[symbol seq] [nativefn mal_seq]]
424 [[symbol meta] [nativefn mal_meta]]
425 [[symbol with-meta] [nativefn mal_with_meta]]
426 [[symbol atom] [nativefn mal_atom]]
427 [[symbol atom?] [nativefn mal_atom_q]]
428 [[symbol deref] [nativefn mal_deref]]
429 [[symbol reset!] [nativefn mal_reset_bang]]
430 [[symbol swap!] [nativefn mal_swap_bang]]
432 [[symbol logo-eval] [nativefn mal_logo_eval]]