8 /_readline
{ print flush
(%stdin) (r) file 99 string readline } def
17 /eval_ast
{ 2 dict begin
20 %(eval_ast: ) print ast ==
21 ast _symbol?
{ %if symbol
23 }{ ast _sequential?
{ %elseif list or vector
25 ast
/data get
{ %forall items
28 ] ast _list?
{ _list_from_array
}{ _vector_from_array
} ifelse
29 }{ ast _hash_map?
{ %elseif list or vector
31 ast
/data get
{ %forall entries
34 >> _hash_map_from_dict
37 } ifelse } ifelse } ifelse
44 %(EVAL: ) print ast true _pr_str print (\n) print
45 ast _list? not
{ %if not a list
47 }{ %else apply the list
49 /def
! a0 eq
{ %if def!
52 env a1 a2 env EVAL env_set
53 }{ /let
* a0 eq
{ %if let*
56 /let_env env null null env_new def
57 0 2 a1 _count
1 sub { %for each pair
61 a1 idx
1 add _nth let_env EVAL
63 pop % discard the return value
67 /el ast _rest env eval_ast def
68 el el _count
1 sub _nth
% return last value
72 cond null eq cond
false eq or
{ % if cond is nil or false
73 ast _count
3 gt
{ %if false branch with a3
76 }{ % else false branch with no a3
83 }{ /fn
* a0 eq
{ %if fn*
87 /_maltype_
/function
% user defined function
88 /params null
% close over parameters
89 /ast null
% close over ast
90 /env null
% close over environment
91 /data
{ __self__ fload EVAL
}
93 dup length dict
copy % make an actual copy/new instance
94 dup /params a1 put
% insert closed over a1 into position 2
95 dup /ast a2 put
% insert closed over a2 into position 3
96 dup /env env put
% insert closed over env into position 4
97 dup dup /data get
exch 0 exch put
% insert self reference
99 /el ast env eval_ast def
100 el _rest el _first
% stack: ast function
101 dup _mal_function?
{ % if user defined function
102 fload
% stack: ast new_env
104 }{ %else (regular procedure/function)
105 exec % apply function to args
107 } ifelse } ifelse } ifelse } ifelse } ifelse
119 /repl_env null null null env_new def
121 /RE
{ READ repl_env EVAL
} def
122 /REP
{ READ repl_env EVAL PRINT
} def
123 /_ref
{ repl_env
3 1 roll env_set
pop } def
125 core_ns
{ _ref
} forall
127 (\
(def
! not \
(fn
* \
(a\
) \
(if a
false true\
)\
)\
)) RE
pop
131 not
{ exit } if % exit if EOF
137 get_error_data
false _pr_str print
(\n) print
138 $error
/newerror
false put
139 $error
/errorinfo null put
145 (\n) print
% final newline before exit for cleanliness