6 mal_equal?
: procedure expose values
. /* mal_equal?(a, b) */
7 return new_boolean
(equal?
(arg(1), arg(2)))
9 mal_throw: procedure expose values
. err
/* mal_throw(a) */
10 err
= "__MAL_EXCEPTION__" arg(1)
13 mal_nil?
: procedure expose values
. /* mal_nil?(a) */
14 return new_boolean
(nil?
(arg(1)))
16 mal_true?
: procedure expose values
. /* mal_true?(a) */
17 return new_boolean
(true?
(arg(1)))
19 mal_false?
: procedure expose values
. /* mal_false?(a) */
20 return new_boolean
(false?
(arg(1)))
22 mal_string?
: procedure expose values
. /* mal_string?(a) */
23 return new_boolean
(string?
(arg(1)))
25 mal_symbol: procedure expose values
. /* mal_symbol(a) */
26 return new_symbol
(obj_val
(arg(1)))
28 mal_symbol?
: procedure expose values
. /* mal_symbol?(a) */
29 return new_boolean
(symbol?
(arg(1)))
31 mal_keyword: procedure expose values
. /* mal_keyword(a) */
32 return new_keyword
(obj_val
(arg(1)))
34 mal_keyword?
: procedure expose values
. /* mal_keyword?(a) */
35 return new_boolean
(keyword?
(arg(1)))
37 mal_number?
: procedure expose values
. /* mal_number?(a) */
38 return new_boolean
(number?
(arg(1)))
40 mal_fn?
: procedure expose values
. /* mal_fn?(a) */
41 return new_boolean
(nativefn?
(arg(1)) | (func?
(arg(1)) & (func_is_macro
(arg(1)) \
= 1)))
43 mal_macro?
: procedure expose values
. /* mal_macro?(a) */
44 return new_boolean
(func_macro?
(arg(1)))
46 mal_pr_str: procedure expose values
. /* mal_pr_str(...) */
49 element
= pr_str
(arg(i
), 1)
53 res
= res
|| " " || element
55 return new_string
(res
)
57 mal_str: procedure expose values
. /* mal_str(...) */
60 element
= pr_str
(arg(i
), 0)
66 return new_string
(res
)
68 mal_prn: procedure expose values
. /* mal_prn(...) */
71 element
= pr_str
(arg(i
), 1)
75 res
= res
|| " " || element
80 mal_println: procedure expose values
. /* mal_println(...) */
83 element
= pr_str
(arg(i
), 0)
87 res
= res
|| " " || element
92 mal_read_string: procedure expose values
. err
/* mal_read_string(str) */
93 return read_str
(obj_val
(arg(1)))
95 mal_readline: procedure expose values
. /* mal_readline(prompt) */
96 line = readline
(obj_val
(arg(1)))
97 if length(line) > 0 then return new_string
(line)
98 if lines() > 0 then return new_string
("")
101 mal_slurp: procedure expose values
. /* mal_read_string(filename) */
102 file_content
= charin(obj_val
(arg(1)), 1, 100000)
103 return new_string
(file_content
)
105 mal_lt: procedure expose values
. /* mal_lt(a, b) */
106 return new_boolean
(obj_val
(arg(1)) < obj_val
(arg(2)))
108 mal_lte: procedure expose values
. /* mal_lte(a, b) */
109 return new_boolean
(obj_val
(arg(1)) <= obj_val
(arg(2)))
111 mal_gt: procedure expose values
. /* mal_gt(a, b) */
112 return new_boolean
(obj_val
(arg(1)) > obj_val
(arg(2)))
114 mal_gte: procedure expose values
. /* mal_gte(a, b) */
115 return new_boolean
(obj_val
(arg(1)) >= obj_val
(arg(2)))
117 mal_add: procedure expose values
. /* mal_add(a, b) */
118 return new_number
(obj_val
(arg(1)) + obj_val
(arg(2)))
120 mal_sub: procedure expose values
. /* mal_sub(a, b) */
121 return new_number
(obj_val
(arg(1)) - obj_val
(arg(2)))
123 mal_mul: procedure expose values
. /* mal_mul(a, b) */
124 return new_number
(obj_val
(arg(1)) * obj_val
(arg(2)))
126 mal_div: procedure expose values
. /* mal_div(a, b) */
127 return new_number
(obj_val
(arg(1)) / obj_val
(arg(2)))
129 mal_time_ms: procedure expose values
. /* mal_time_ms() */
130 return new_number
(trunc(time('E') * 1000))
132 mal_list: procedure expose values
. /* mal_list(...) */
138 res
= res
|| " " || arg(i
)
142 mal_list?
: procedure expose values
. /* mal_list?(a) */
143 return new_boolean
(list?
(arg(1)))
145 mal_vector: procedure expose values
. /* mal_vector(...) */
151 res
= res
|| " " || arg(i
)
153 return new_vector
(res
)
155 mal_vector?
: procedure expose values
. /* mal_vector?(a) */
156 return new_boolean
(vector?
(arg(1)))
158 mal_hash_map: procedure expose values
. /* mal_hash_map(...) */
164 res
= res
|| " " || arg(i
)
166 return new_hashmap
(res
)
168 mal_map?
: procedure expose values
. /* mal_map?(a) */
169 return new_boolean
(hashmap?
(arg(1)))
171 mal_assoc: procedure expose values
. /* mal_assoc(a, ...) */
175 key_val
= arg(i
) || " " || arg(i
+ 1)
179 res
= res
|| " " || key_val
182 do i
=1 to words(hm_val
) by 2
183 if \contains?
(res
, word(hm_val
, i
)) then
184 res
= res
|| " " || word(hm_val
, i
) || " " || word(hm_val
, i
+ 1)
186 return new_hashmap
(res
)
188 mal_dissoc: procedure expose values
. /* mal_dissoc(a, ...) */
192 do i
=1 to words(hm_val
) by 2
193 key
= word(hm_val
, i
)
196 if equal?
(key
, arg(j
)) then do
202 if length(res
) > 0 then res
= res
|| " "
203 res
= res
|| key
|| " " || word(hm_val
, i
+ 1)
206 return new_hashmap
(res
)
208 mal_get: procedure expose values
. /* mal_get(a, b) */
209 res
= hashmap_get
(obj_val
(arg(1)), arg(2))
215 mal_contains?
: procedure expose values
. /* mal_contains?(a, b) */
216 return new_boolean
(contains?
(obj_val
(arg(1)), arg(2)))
218 mal_keys: procedure expose values
. /* mal_keys(a) */
219 hm_val
= obj_val
(arg(1))
221 do i
=1 to words(hm_val
) by 2
223 seq
= word(hm_val
, i
)
225 seq
= seq
|| " " || word(hm_val
, i
)
229 mal_vals: procedure expose values
. /* mal_vals(a) */
230 hm_val
= obj_val
(arg(1))
232 do i
=2 to words(hm_val
) by 2
234 seq
= word(hm_val
, i
)
236 seq
= seq
|| " " || word(hm_val
, i
)
240 mal_sequential?
: procedure expose values
. /* mal_sequential?(a) */
241 return new_boolean
(sequential?
(arg(1)))
243 mal_cons: procedure expose values
. /* mal_cons(a, b) */
244 return new_list
(arg(1) || " " || obj_val
(arg(2)))
246 mal_concat: procedure expose values
. /* mal_concat(...) */
250 seq
= obj_val
(arg(i
))
252 seq
= seq
|| " " || obj_val
(arg(i
))
256 mal_nth: procedure expose values
. err
/* mal_nth(list, index) */
257 list_val
= obj_val
(arg(1))
259 if i
>= words(list_val
) then do
260 err
= "nth: index out of range"
263 return word(list_val
, i
+ 1)
265 mal_first: procedure expose values
. /* mal_first(a) */
266 if nil?
(arg(1)) then return new_nil
()
267 list_val
= obj_val
(arg(1))
268 if words(list_val
) == 0 then return new_nil
()
269 return word(list_val
, 1)
271 mal_rest: procedure expose values
. /* mal_rest(a) */
272 return new_list
(subword(obj_val
(arg(1)), 2))
274 mal_empty?
: procedure expose values
. /* mal_empty?(a) */
275 if nil?
(arg(1)) then return new_true
()
276 return new_boolean
(count_elements
(arg(1)) == 0)
278 mal_count: procedure expose values
. /* mal_count(a) */
279 if nil?
(arg(1)) then return new_number
(0)
280 return new_number
(count_elements
(arg(1)))
282 apply_function: procedure expose values
. env
. err
/* apply_function(fn, lst) */
286 when nativefn?
(f
) then do
287 call_args_val
= obj_val
(call_args
)
289 do i
=1 to words(call_args_val
)
290 element
= '"' || word(call_args_val
, i
) || '"'
292 call_list
= call_list
|| ', ' || element
297 interpret "res = " || obj_val
(f
) || "(" || call_list
|| ")"
300 when func?
(f
) then do
301 apply_env_idx
= new_env
(func_env_idx
(f
), func_binds
(f
), call_args
)
302 return eval
(func_body_ast
(f
), apply_env_idx
)
305 err
= "Unsupported function object type: " || obj_type
(f
)
309 mal_apply: procedure expose values
. env
. err
/* mal_apply(fn, ..., lst) */
312 do i
=2 to (arg() - 1)
316 seq
= seq
|| " " || arg(i
)
319 seq
= seq
|| " " || obj_val
(arg(arg()))
321 return apply_function
(fn
, new_list
(seq
))
323 mal_map: procedure expose values
. env
. err
/* mal_map(f, lst) */
325 lst_val
= obj_val
(arg(2))
327 do i
=1 to words(lst_val
)
328 element
= word(lst_val
, i
)
329 mapped_element
= apply_function
(fn
, new_list
(element
))
330 if mapped_element
== "ERR" then return "ERR"
334 res
= res
|| " " || mapped_element
338 mal_conj: procedure expose values
. env
. err
/* mal_conj(a, ...) */
341 when list?
(a
) then do
343 a
= mal_cons
(arg(i
), a
)
347 when vector?
(a
) then do
350 if length(seq
) > 0 then seq
= seq
|| " "
353 return new_vector
(seq
)
356 err
= "conj requires list or vector"
360 mal_seq: procedure expose values
. env
. err
/* mal_conj(a) */
363 when string?
(a
) then do
365 if length(str
) == 0 then return new_nil
()
367 do i
=1 to length(str
)
368 element
= new_string
(substr(str
, i
, 1))
372 seq
= seq
|| " " || element
376 when list?
(a
) then do
377 if count_elements
(a
) == 0 then return new_nil
()
380 when vector?
(a
) then do
381 if count_elements
(a
) == 0 then return new_nil
()
382 return new_list
(obj_val
(a
))
384 when nil?
(a
) then return new_nil
()
386 err
= "seq requires string or list or vector or nil"
390 mal_with_meta: procedure expose values
. /* mal_with_meta(a, b) */
391 new_obj
= obj_clone_and_set_meta
(arg(1), arg(2))
392 if new_obj
== "" then return arg(1)
395 mal_meta: procedure expose values
. /* mal_meta(a) */
396 meta
= obj_meta
(arg(1))
397 if meta
== "" then return new_nil
()
400 mal_atom: procedure expose values
. /* mal_atom(a) */
401 return new_atom
(arg(1))
403 mal_atom?
: procedure expose values
. /* mal_atom?(a) */
404 return new_boolean
(atom?
(arg(1)))
406 mal_deref: procedure expose values
. /* mal_deref(a) */
407 return obj_val
(arg(1))
409 mal_reset
!: procedure expose values
. /* mal_reset!(a, new_val) */
410 return atom_set
(arg(1), arg(2))
412 mal_swap
!: procedure expose values
. env
. err
/* mal_swap!(a, fn, ...) */
415 atom_val
= obj_val
(atom
)
418 seq
= seq
|| " " || arg(i
)
420 new_val
= apply_function
(fn
, new_list
(seq
))
421 if new_val
== "ERR" then return "ERR"
422 return atom_set
(atom
, new_val
)
424 mal_rexx_eval: procedure expose values
. /* mal_rexx_eval(..., a) */
425 do i
=1 to (arg() - 1)
426 interpret obj_val
(arg(i
))
428 last_arg
= arg(arg())
429 if nil?
(last_arg
) then return new_nil
()
430 last_arg_str
= obj_val
(last_arg
)
431 if length(last_arg_str
) == 0 then return new_nil
()
433 interpret "rexx_eval_res = " || last_arg_str
434 if datatype(rexx_eval_res
) == "NUM" then
435 return new_number
(rexx_eval_res
)
437 return new_string
(rexx_eval_res
)
439 get_core_ns: procedure /* get_core_ns() */
440 return "= mal_equal?" ,
445 "false? mal_false?" ,
446 "string? mal_string?" ,
447 "symbol mal_symbol" ,
448 "symbol? mal_symbol?" ,
449 "keyword mal_keyword" ,
450 "keyword? mal_keyword?" ,
451 "number? mal_number?" ,
453 "macro? mal_macro?" ,
455 "pr-str mal_pr_str" ,
458 "println mal_println" ,
459 "read-string mal_read_string" ,
460 "readline mal_readline" ,
471 "time-ms mal_time_ms" ,
475 "vector mal_vector" ,
476 "vector? mal_vector?" ,
477 "hash-map mal_hash_map" ,
480 "dissoc mal_dissoc" ,
482 "contains? mal_contains?" ,
486 "sequential? mal_sequential?" ,
488 "concat mal_concat" ,
492 "empty? mal_empty?" ,
501 "with-meta mal_with_meta" ,
505 "reset! mal_reset!" ,
508 "rexx-eval mal_rexx_eval"