5 /_readline
{ print flush
(%stdin) (r) file 99 string readline } def
14 /eval_ast
{ 2 dict begin
17 %(eval_ast: ) print ast ==
18 ast _symbol?
{ %if symbol
20 }{ ast _list?
{ %elseif list
35 %(EVAL: ) print ast true _pr_str print (\n) print
36 ast _list? not
{ %if not a list
38 }{ %else apply the list
40 /def
! a0 eq
{ %if def!
43 env a1 a2 env EVAL env_set
44 }{ /let
* a0 eq
{ %if let*
47 /let_env env
[ ] [ ] env_new def
48 0 2 a1 length
1 sub { %for each pair
52 a1 idx
1 add get let_env EVAL
54 pop % discard the return value
58 /el ast _rest env eval_ast def
59 el el length
1 sub get
% return last value
63 cond null eq cond
false eq or
{ % if cond is nil or false
64 ast length
3 gt
{ %if false branch with a3
67 }{ % else false branch with no a3
74 }{ /fn
* a0 eq
{ %if fn*
78 /type
/_maltype_function
% user defined function
79 /params null
% close over parameters
80 /ast null
% close over ast
81 /env null
% close over environment
82 /data
{ __self__ fload EVAL
}
84 dup length dict
copy % make an actual copy/new instance
85 dup /params a1 put
% insert closed over a1 into position 2
86 dup /ast a2 put
% insert closed over a2 into position 3
87 dup /env env put
% insert closed over env into position 4
88 dup dup /data get
exch 0 exch put
% insert self reference
90 /el ast env eval_ast def
91 el _rest el _first
% stack: ast function
92 dup _mal_function?
{ % if user defined function
93 fload
% stack: ast new_env
95 }{ %else (regular procedure/function)
96 exec % apply function to args
98 } ifelse } ifelse } ifelse } ifelse } ifelse
110 /repl_env null
[ ] [ ] env_new def
112 /RE
{ READ repl_env EVAL
} def
113 /REP
{ READ repl_env EVAL PRINT
} def
114 /_ref
{ repl_env
3 1 roll env_set
pop } def
116 types_ns
{ _ref
} forall
118 (\
(def
! not \
(fn
* \
(a\
) \
(if a
false true\
)\
)\
)) RE
pop
122 not
{ exit } if % exit if EOF
128 get_error_data
false _pr_str print
(\n) print
129 $error
/newerror
false put
130 $error
/errorinfo null put
136 (\n) print
% final newline before exit for cleanliness