4 #include
"readline.rexx"
6 #include
"printer.rexx"
11 read: procedure expose values
. err
/* read(str) */
12 return read_str
(arg(1))
14 eval_ast: procedure expose values
. env
. err
/* eval_ast(ast, env_idx) */
20 when type
== "symb" then return env_get
(env_idx
, val
)
21 when type
== "list" then do
24 element
= eval
(word(val
, i
), env_idx
)
25 if element
== "ERR" then return "ERR"
27 res
= res
|| " " || element
33 when type
== "vect" then do
36 element
= eval
(word(val
, i
), env_idx
)
37 if element
== "ERR" then return "ERR"
39 res
= res
|| " " || element
43 return new_vector
(res
)
45 when type
== "hash" then do
48 element
= eval
(word(val
, i
), env_idx
)
49 if element
== "ERR" then return "ERR"
51 res
= res
|| " " || element
55 return new_hashmap
(res
)
61 eval: procedure expose values
. env
. err
/* eval(ast) */
65 if \list?
(ast
) then return eval_ast
(ast
, env_idx
)
67 if words(astval
) == 0 then return ast
68 a0sym
= obj_val
(word(astval
, 1))
70 when a0sym
== "def!" then do
71 a1sym
= obj_val
(word(astval
, 2))
72 a2
= eval
(word(astval
, 3), env_idx
)
73 if a2
== "ERR" then return "ERR"
74 return env_set
(env_idx
, a1sym
, a2
)
76 when a0sym
== "let*" then do
77 a1lst
= obj_val
(word(astval
, 2))
78 letenv_idx
= new_env
(env_idx
)
79 do i
=1 to words(a1lst
) by 2
80 k
= obj_val
(word(a1lst
, i
))
81 v
= eval
(word(a1lst
, i
+ 1), letenv_idx
)
82 if v
== "ERR" then return "ERR"
83 unused
= env_set
(letenv_idx
, k
, v
)
89 when a0sym
== "do" then do
90 do i
=2 to (words(astval
) - 1)
91 res
= eval
(word(astval
, i
), env_idx
)
92 if res
== "ERR" then return "ERR"
94 ast
= word(astval
, words(astval
))
97 when a0sym
== "if" then do
98 condval
= eval
(word(astval
, 2), env_idx
)
99 if false?
(condval
) | nil?
(condval
) then
100 if words(astval
) >= 4 then
101 ast
= word(astval
, 4)
105 ast
= word(astval
, 3)
108 when a0sym
== "fn*" then return new_func
(word(astval
, 3), env_idx
, word(astval
, 2))
110 lst_obj
= eval_ast
(ast
, env_idx
)
111 if lst_obj
== "ERR" then return "ERR"
112 lst
= obj_val
(lst_obj
)
115 when nativefn?
(f
) then do
116 call_args
= subword(lst
, 2)
118 do i
=1 to words(call_args
)
119 element
= '"' || word(call_args
, i
) || '"'
121 call_list
= call_list
|| ', ' || element
126 interpret "res = " || obj_val
(f
) || "(" || call_list
|| ")"
129 when func?
(f
) then do
130 call_args
= new_list
(subword(lst
, 2))
131 env_idx
= new_env
(func_env_idx
(f
), func_binds
(f
), call_args
)
132 ast
= func_body_ast
(f
)
136 err
= "Unsupported function object type: " || obj_type
(f
)
142 print: procedure expose values
. /* print(ast) */
143 return pr_str
(arg(1), 1)
145 re: procedure expose values
. env
. err repl_env_idx
/* re(str) */
148 if ast
== "ERR" then return "ERR"
149 return eval
(ast
, repl_env_idx
)
151 rep: procedure expose values
. env
. err repl_env_idx
/* rep(str) */
154 if exp
== "ERR" then return "ERR"
162 repl_env_idx
= new_env
(0)
164 /* core.rexx: defined using Rexx */
165 core_ns
= get_core_ns
()
166 do i
=1 to words(core_ns
) by 2
167 x
= env_set
(repl_env_idx
, word(core_ns
, i
), new_nativefn
(word(core_ns
, i
+ 1)))
170 /* core.mal: defined using the language itself */
171 x
= rep
("(def! not (fn* (a) (if a false true)))")
174 do while lines() > 0 /* 1 == 1 */
175 input_line
= readline
('user> ')
176 if length(input_line
) > 0 then do
177 res
= rep
(input_line
)
179 call lineout , "Error: " || err