2014-03-30 03:20:07 +04:00
|
|
|
(types.ps) run
|
|
|
|
(reader.ps) run
|
|
|
|
|
|
|
|
% read
|
|
|
|
/READ {
|
|
|
|
/str exch def
|
|
|
|
str read_str
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% eval
|
|
|
|
/eval_ast { 2 dict begin
|
|
|
|
/env exch def
|
|
|
|
/ast exch def
|
|
|
|
%(eval_ast: ) print ast ==
|
|
|
|
/nametype ast type eq { %if symbol
|
|
|
|
env ast env_get
|
|
|
|
}{ /arraytype ast type eq { %elseif list
|
|
|
|
[
|
|
|
|
ast {
|
|
|
|
env EVAL
|
|
|
|
} forall
|
|
|
|
]
|
|
|
|
}{ % else
|
|
|
|
ast
|
|
|
|
} ifelse } ifelse
|
|
|
|
end } def
|
|
|
|
|
2014-03-30 03:35:22 +04:00
|
|
|
/EVAL { 9 dict begin
|
2014-03-30 03:20:07 +04:00
|
|
|
/env exch def
|
|
|
|
/ast exch def
|
|
|
|
%(EVAL: ) print ast ==
|
|
|
|
/arraytype ast type ne { %if not a list
|
|
|
|
ast env eval_ast
|
|
|
|
}{ %else apply the list
|
|
|
|
/a0 ast 0 get def
|
|
|
|
/def! a0 eq { %if def!
|
|
|
|
/a1 ast 1 get def
|
|
|
|
/a2 ast 2 get def
|
|
|
|
env a1 a2 env EVAL env_set
|
|
|
|
}{ /let* a0 eq { %if let*
|
|
|
|
/a1 ast 1 get def
|
|
|
|
/a2 ast 2 get def
|
|
|
|
/let_env env [ ] [ ] env_new def
|
|
|
|
0 2 a1 length 1 sub { %for each pair
|
|
|
|
/idx exch def
|
|
|
|
let_env
|
|
|
|
a1 idx get
|
|
|
|
a1 idx 1 add get let_env EVAL
|
|
|
|
env_set
|
|
|
|
} for
|
|
|
|
a2 let_env EVAL
|
|
|
|
}{ /do a0 eq { %if do
|
|
|
|
/el ast _rest env eval_ast def
|
|
|
|
el el length 1 sub get % return last value
|
|
|
|
}{ /if a0 eq { %if if
|
|
|
|
/a1 ast 1 get def
|
|
|
|
/cond a1 env EVAL def
|
|
|
|
cond null eq cond false eq or { % if cond is nil or false
|
|
|
|
ast length 3 gt { %if false branch (a3) provided
|
|
|
|
ast 3 get env EVAL % EVAL false branch (a3)
|
|
|
|
}{
|
|
|
|
null
|
|
|
|
} ifelse
|
|
|
|
}{
|
|
|
|
ast 2 get env EVAL % EVAL true branch (a2)
|
|
|
|
} ifelse
|
|
|
|
}{ /fn* a0 eq { %if fn*
|
|
|
|
/a1 ast 1 get def
|
|
|
|
/a2 ast 2 get def
|
2014-03-30 03:35:22 +04:00
|
|
|
{ /user_defined % mark this as user defined
|
|
|
|
__PARAMS__ __AST__ __ENV__ % closed over variables
|
|
|
|
4 dict begin
|
|
|
|
/ENV exch def % closed over above, pos 3
|
|
|
|
/AST exch def % closed over above, pos 2
|
|
|
|
/PARAMS exch def % closed over above, pos 1
|
|
|
|
/args exch def
|
2014-03-30 03:20:07 +04:00
|
|
|
%(inside fn*:\n) print
|
|
|
|
%( A1: ) print A1 ==
|
|
|
|
%( A2: ) print A2 ==
|
|
|
|
%( ENV: ) print ENV ==
|
|
|
|
%( args: ) print args ==
|
2014-03-30 03:35:22 +04:00
|
|
|
AST ENV PARAMS args env_new EVAL
|
2014-03-30 03:20:07 +04:00
|
|
|
end }
|
|
|
|
dup length array copy cvx % make an actual copy/new instance
|
2014-03-30 03:35:22 +04:00
|
|
|
dup 1 a1 put % insert closed over a1 into position 1
|
|
|
|
dup 2 a2 put % insert closed over a2 into position 2
|
|
|
|
dup 3 env put % insert closed over env into position 3
|
2014-03-30 03:20:07 +04:00
|
|
|
}{
|
|
|
|
/el ast env eval_ast def
|
|
|
|
el _rest % args array
|
|
|
|
el _first cvx % function
|
|
|
|
%(vvv\n) print pstack (^^^\n) print
|
|
|
|
exec % apply function to args
|
|
|
|
} ifelse } ifelse } ifelse } ifelse } ifelse
|
|
|
|
} ifelse
|
|
|
|
end } def
|
|
|
|
|
|
|
|
|
|
|
|
% print
|
|
|
|
/PRINT {
|
|
|
|
true _pr_str
|
|
|
|
} def
|
|
|
|
|
|
|
|
|
|
|
|
% repl
|
|
|
|
/repl_env null [ ] [ ] env_new def
|
|
|
|
|
|
|
|
/RE { READ repl_env EVAL } def
|
|
|
|
/REP { READ repl_env EVAL PRINT } def
|
|
|
|
/_ref { repl_env 3 1 roll env_set pop } def
|
|
|
|
|
|
|
|
types_ns { _ref } forall
|
|
|
|
|
|
|
|
(\(def! not \(fn* \(a\) \(if a false true\)\)\)) RE pop
|
|
|
|
|
|
|
|
/stdin (%stdin) (r) file def
|
|
|
|
|
|
|
|
{ % loop
|
|
|
|
(user> ) print flush
|
|
|
|
|
|
|
|
stdin 99 string readline
|
|
|
|
|
|
|
|
not { exit } if % exit if EOF
|
|
|
|
|
|
|
|
%(\ngot line: ) print dup print (\n) print flush
|
|
|
|
|
|
|
|
{ %try
|
|
|
|
REP print (\n) print
|
|
|
|
} stopped {
|
|
|
|
(Error: ) print
|
|
|
|
get_error_data false _pr_str print (\n) print
|
|
|
|
clear
|
|
|
|
} if
|
|
|
|
} bind loop
|
|
|
|
|
|
|
|
(\n) print % final newline before exit for cleanliness
|
|
|
|
quit
|