1 load "../logo/readline.lg
2 load "../logo/reader.lg
3 load "../logo/printer.lg
13 output case (obj_type :ast) [
14 [[symbol] env_get :env :ast]
15 [[list] obj_new "list map [_eval ? :env] obj_val :ast]
16 [[vector] obj_new "vector map [_eval ? :env] obj_val :ast]
17 [[hashmap] obj_new "hashmap map [_eval ? :env] obj_val :ast]
22 to _eval :a_ast :a_env
26 if (obj_type :ast) <> "list [output eval_ast :ast :env]
27 if emptyp obj_val :ast [output :ast]
28 localmake "a0 nth :ast 0
29 case list obj_type :a0 obj_val :a0 [
31 localmake "a1 nth :ast 1
32 localmake "a2 nth :ast 2
33 output env_set :env :a1 _eval :a2 :env ]
36 localmake "a1 nth :ast 1
37 localmake "letenv env_new :env [] []
39 while [:i < _count :a1] [
40 ignore env_set :letenv nth :a1 :i _eval nth :a1 (:i + 1) :letenv
44 make "ast nth :ast 2 ] ; TCO
48 while [:i < ((_count :ast) - 1)] [
49 ignore _eval nth :ast :i :env
52 make "ast last obj_val :ast ] ; TCO
55 localmake "a1 nth :ast 1
56 localmake "cond _eval :a1 :env
58 [[nil false] ifelse (_count :ast) > 3 [
59 make "ast nth :ast 3 ; TCO
63 [else make "ast nth :ast 2] ; TCO
67 output fn_new nth :ast 1 :env nth :ast 2 ]
70 localmake "el eval_ast :ast :env
71 localmake "f nth :el 0
74 output apply obj_val :f butfirst obj_val :el ]
76 make "env env_new fn_env :f fn_args :f rest :el
77 make "ast fn_body :f ] ; TCO
79 (throw "error [Wrong type for apply])]
86 output pr_str :exp "true
90 output _eval _read :str :repl_env
97 to print_exception :exception
98 if not emptyp :exception [
99 localmake "e first butfirst :exception
100 ifelse :e = "_mal_exception_ [
101 (print "Error: pr_str :global_exception "false)
109 localmake "running "true
111 localmake "line readline word "user> :space_char
116 if not emptyp :line [
117 catch "error [print rep :line]
118 print_exception error
125 output _eval :a :repl_env
129 localmake "argv ifelse emptyp :command.line [[]] [butfirst :command.line]
130 output obj_new "list map [obj_new "string ?] :argv
133 make "repl_env env_new [] [] []
135 ignore env_set :repl_env first ? first butfirst ?
137 ignore env_set :repl_env [symbol eval] [nativefn mal_eval]
138 ignore env_set :repl_env [symbol *ARGV*] argv_list
140 ; core.mal: defined using the language itself
141 ignore re "|(def! not (fn* (a) (if a false true)))|
142 ignore re "|(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\\nnil)\")))))|
144 if not emptyp :command.line [
145 catch "error [ignore re (word "\(load-file :space_char "\" first :command.line "\"\) )]
146 print_exception error