(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 known { env ast get }{ (') ast pr_str (' not found) concatenate concatenate throw } ifelse }{ /arraytype ast type eq { %elseif list [ ast { env EVAL } forall ] }{ % else ast } ifelse } ifelse end } def /EVAL { 3 dict begin /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 /el ast env eval_ast def el _rest % args array el _first % function %(vvv\n) print pstack (^^^\n) print exec % apply function to args } ifelse end } def % print /PRINT { true _pr_str } def % repl /repl_env << (+) { dup 0 get exch 1 get add } (-) { dup 0 get exch 1 get sub } (*) { dup 0 get exch 1 get mul } (/) { dup 0 get exch 1 get idiv } >> def /REP { READ repl_env EVAL PRINT } def /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