1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-10 12:47:45 +03:00
mal/ps/step3_env.ps

111 lines
2.6 KiB
PostScript
Raw Normal View History

2014-05-11 01:29:07 +04:00
/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
(types.ps) runlibfile
(reader.ps) runlibfile
(printer.ps) runlibfile
(env.ps) runlibfile
2014-03-30 02:26:07 +04:00
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
2014-03-30 02:26:07 +04:00
/READ {
/str exch def
str read_str
} def
% eval
/eval_ast { 2 dict begin
/env exch def
/ast exch def
%(eval_ast: ) print ast ==
2014-03-31 07:39:44 +04:00
ast _symbol? { %if symbol
2014-03-30 02:26:07 +04:00
env ast env_get
}{ ast _sequential? { %elseif list or vector
2014-03-30 02:26:07 +04:00
[
ast /data get { %forall items
2014-03-30 02:26:07 +04:00
env EVAL
} forall
] ast _list? { _list_from_array }{ _vector_from_array } ifelse
}{ ast _hash_map? { %elseif list or vector
<<
ast /data get { %forall entries
env EVAL
} forall
>> _hash_map_from_dict
2014-03-30 02:26:07 +04:00
}{ % else
ast
} ifelse } ifelse } ifelse
2014-03-30 02:26:07 +04:00
end } def
/EVAL { 8 dict begin
2014-03-30 02:26:07 +04:00
/env exch def
/ast exch def
%(EVAL: ) print ast true _pr_str print (\n) print
2014-03-31 07:39:44 +04:00
ast _list? not { %if not a list
2014-03-30 02:26:07 +04:00
ast env eval_ast
}{ %else apply the list
/a0 ast 0 _nth def
2014-03-30 02:26:07 +04:00
/def! a0 eq { %if def!
/a1 ast 1 _nth def
/a2 ast 2 _nth def
2014-03-30 02:26:07 +04:00
env a1 a2 env EVAL 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
2014-03-30 02:26:07 +04:00
/idx exch def
let_env
a1 idx _nth
a1 idx 1 add _nth let_env EVAL
2014-03-30 02:26:07 +04:00
env_set
pop % discard the return value
2014-03-30 02:26:07 +04:00
} for
a2 let_env EVAL
}{
/el ast env eval_ast def
el _rest el _first % stack: ast function
exec % apply function to args
2014-03-30 02:26:07 +04:00
} ifelse } ifelse
} ifelse
end } def
% print
/PRINT {
2014-03-30 03:20:07 +04:00
true _pr_str
2014-03-30 02:26:07 +04:00
} def
% repl
/repl_env null null null env_new def
2014-03-30 02:26:07 +04:00
/REP { READ repl_env EVAL PRINT } def
/_ref { repl_env 3 1 roll env_set pop } def
(+) { dup 0 _nth exch 1 _nth add } _ref
(-) { dup 0 _nth exch 1 _nth sub } _ref
(*) { dup 0 _nth exch 1 _nth mul } _ref
(/) { dup 0 _nth exch 1 _nth idiv } _ref
2014-03-30 02:26:07 +04:00
% repl loop
{ %loop
(user> ) _readline
2014-03-30 02:26:07 +04:00
not { exit } if % exit if EOF
{ %try
REP print (\n) print
} stopped {
(Error: ) print
2014-03-30 03:20:07 +04:00
get_error_data false _pr_str print (\n) print
$error /newerror false put
$error /errorinfo null put
clear
cleardictstack
} if
2014-03-30 02:26:07 +04:00
} bind loop
(\n) print % final newline before exit for cleanliness
quit