12 /eval_ast
{ 2 dict begin
15 %(eval_ast: ) print ast ==
16 ast _symbol?
{ %if symbol
18 }{ ast _list?
{ %elseif list
36 %(EVAL: ) print ast ==
37 ast _list? not
{ %if not a list
39 }{ %else apply the list
41 /def
! a0 eq
{ %if def!
44 env a1 a2 env EVAL env_set
45 }{ /let
* a0 eq
{ %if let*
48 /let_env env
[ ] [ ] env_new def
49 0 2 a1 length
1 sub { %for each pair
53 a1 idx
1 add get let_env EVAL
58 ast length
2 ge
{ %if ast has more than 2 elements
59 ast
1 ast length
1 sub getinterval env eval_ast
61 ast ast length
1 sub get
% last ast becomes new ast
63 /loop?
true def
% loop
67 cond null eq cond
false eq or
{ % if cond is nil or false
68 ast length
3 gt
{ %if false branch (a3) provided
69 ast
3 get env
% new ast is false branch (a3)
75 ast
2 get env
% new ast is true branch (a2)
78 }{ /fn
* a0 eq
{ %if fn*
81 { /user_defined
% mark this as user defined
82 __PARAMS__ __AST__ __ENV__
% closed over variables
84 /ENV
exch def
% closed over above, pos 3
85 /AST
exch def
% closed over above, pos 2
86 /PARAMS
exch def
% closed over above, pos 1
89 AST ENV PARAMS args env_new EVAL
91 dup length array
copy cvx
% make an actual copy/new instance
92 dup 1 a1 put
% insert closed over a1 into position 1
93 dup 2 a2 put
% insert closed over a2 into position 2
94 dup 3 env put
% insert closed over env into position 3
96 /el ast env eval_ast def
97 el _first
0 get
/user_defined eq
{ %if userdefined function
98 /PARAMS el _first
1 get def
99 /AST el _first
2 get def
100 /ENV el _first
3 get def
101 AST
% new ast is one stored in function
102 ENV PARAMS el _rest env_new
% new environment
104 }{ %else (regular procedure/function)
105 el _rest
% args array
106 el _first cvx
% function
107 exec % apply function to args
109 } ifelse } ifelse } ifelse } ifelse } ifelse
112 loop? not
{ exit } if
124 /repl_env null
[ ] [ ] env_new def
126 /RE
{ READ repl_env EVAL
} def
127 /REP
{ READ repl_env EVAL PRINT
} def
128 /_ref
{ repl_env
3 1 roll env_set
pop } def
130 types_ns
{ _ref
} forall
132 (read
-string
) { 0 get read_str
} _ref
133 (eval
) { 0 get repl_env EVAL
} _ref
134 /slurp
{ (r
) file
dup bytesavailable string readstring
pop } def
135 (slurp
) { 0 get slurp
} _ref
137 (\
(def
! not \
(fn
* \
(a\
) \
(if a
false true\
)\
)\
)) RE
pop
138 (\
(def
! load
-file \
(fn
* \
(f\
) \
(eval \
(read
-string \
(str
"\(do " \
(slurp f\
) "\)"\
)\
)\
)\
)\
)) RE
pop
140 /stdin
(%stdin) (r) file def
142 userdict
/ARGUMENTS known
{ %if command line arguments
143 ARGUMENTS length
0 gt
{ %if more than 0 arguments
145 (\
(load
-file
") exch ("\
)) concatenate concatenate RE
pop
153 stdin
99 string readline
155 not
{ exit } if % exit if EOF
157 %(\ngot line: ) print dup print (\n) print flush
163 get_error_data
false _pr_str print
(\n) print
164 $error
/newerror
false put
165 $error
/errorinfo null put
170 (\n) print
% final newline before exit for cleanliness