/runlibfile where { pop }{ /runlibfile { run } def } ifelse % (types.ps) runlibfile (reader.ps) runlibfile (printer.ps) runlibfile (env.ps) runlibfile % read /_readline { print flush (%stdin) (r) file 1024 string readline } def /READ { /str exch def str read_str } def % eval /EVAL { 7 dict begin /env exch def /ast exch def env (DEBUG-EVAL) env_get { dup null ne exch false ne and { (EVAL: ) print ast true _pr_str print (\n) print } if } if ast _symbol? { %if symbol env ast env_get not { (') ast dup length string cvs (' not found) concatenate concatenate _throw } if }{ ast _vector? { [ ast /data get { %forall items env EVAL } forall ] _vector_from_array }{ ast _hash_map? { << ast /data get { %forall entries env EVAL } forall >> _hash_map_from_dict }{ ast _list? not { ast }{ ast _count 0 eq { ast }{ /a0 ast 0 _nth def /def! a0 eq { %if def! ast 2 _nth env EVAL env ast 1 _nth 2 index env_set }{ /let* a0 eq { %if let* /a1 ast 1 _nth def /a2 ast 2 _nth def /let_env env null null env_new def 0 2 a1 _count 1 sub { %for each pair /idx exch def let_env a1 idx _nth a1 idx 1 add _nth let_env EVAL env_set } for a2 let_env EVAL }{ a0 env EVAL [ ast _rest /data get { env EVAL } forall ] _list_from_array exch exec % apply function to args } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse end } def % print /PRINT { true _pr_str } def % repl /repl_env null null null env_new def /REP { READ repl_env EVAL PRINT } def repl_env (+) { dup 0 _nth exch 1 _nth add } env_set repl_env (-) { dup 0 _nth exch 1 _nth sub } env_set repl_env (*) { dup 0 _nth exch 1 _nth mul } env_set repl_env (/) { dup 0 _nth exch 1 _nth idiv } env_set % repl loop { %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