(types.ps) run (reader.ps) run (printer.ps) run (env.ps) run % read /_readline { print flush (%stdin) (r) file 99 string readline } def /READ { /str exch def str read_str } def % eval /eval_ast { 2 dict begin /env exch def /ast exch def %(eval_ast: ) print ast == ast _symbol? { %if symbol env ast env_get }{ ast _list? { %elseif list [ ast { env EVAL } forall ] }{ % else ast } ifelse } ifelse end } def /EVAL { 8 dict begin /env exch def /ast exch def %(EVAL: ) print ast true _pr_str print (\n) print ast _list? not { %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 pop % discard the return value } for a2 let_env EVAL }{ /el ast env eval_ast def el _rest el _first % stack: ast function exec % apply function to args } ifelse } ifelse } ifelse end } def % print /PRINT { true _pr_str } def % repl /repl_env null [ ] [ ] env_new def /REP { READ repl_env EVAL PRINT } def /_ref { repl_env 3 1 roll env_set pop } def (+) { dup 0 get exch 1 get add } _ref (-) { dup 0 get exch 1 get sub } _ref (*) { dup 0 get exch 1 get mul } _ref (/) { dup 0 get exch 1 get idiv } _ref { % loop (user> ) _readline not { exit } if % exit if EOF { %try REP print (\n) print } stopped { (Error: ) print get_error_data false _pr_str print (\n) print $error /newerror false put $error /errorinfo null put clear cleardictstack } if } bind loop (\n) print % final newline before exit for cleanliness quit