1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-22 02:58:15 +03:00
mal/ps/step4_if_fn_do.ps

139 lines
3.7 KiB
PostScript
Raw Normal View History

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
/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
{ /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 ==
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
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