diff options
| author | Joel Martin <github@martintribe.org> | 2014-03-29 17:26:07 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-03-29 17:26:07 -0500 |
| commit | 04517bc8265b6930e96735dd5d12b7aac7d86217 (patch) | |
| tree | 844ab6fc6efee9e86b7df80a7f9012b3378a0405 | |
| parent | 55e2bfa8a3a9fb98a405321d1183a3fbc872d118 (diff) | |
| download | mal-04517bc8265b6930e96735dd5d12b7aac7d86217.tar.gz mal-04517bc8265b6930e96735dd5d12b7aac7d86217.zip | |
PS: add step3_env
| -rw-r--r-- | docs/TODO | 2 | ||||
| -rw-r--r-- | ps/step0_repl.ps | 4 | ||||
| -rw-r--r-- | ps/step1_read_print.ps | 4 | ||||
| -rw-r--r-- | ps/step2_eval.ps | 12 | ||||
| -rw-r--r-- | ps/step3_env.ps | 98 | ||||
| -rw-r--r-- | ps/types.ps | 50 |
6 files changed, 157 insertions, 13 deletions
@@ -49,7 +49,7 @@ Java: Postscript: - negative numbers - - step 3-A + - step 4-A Rust: - http://www.rustforrubyists.com/book/index.html diff --git a/ps/step0_repl.ps b/ps/step0_repl.ps index 325392f..1085525 100644 --- a/ps/step0_repl.ps +++ b/ps/step0_repl.ps @@ -24,9 +24,7 @@ % repl -/REP { - READ (stub env) EVAL PRINT -} def +/REP { READ (stub env) EVAL PRINT } def /stdin (%stdin) (r) file def diff --git a/ps/step1_read_print.ps b/ps/step1_read_print.ps index 8c54012..d08579c 100644 --- a/ps/step1_read_print.ps +++ b/ps/step1_read_print.ps @@ -26,9 +26,7 @@ % repl -/REP { - READ (stub env) EVAL PRINT -} def +/REP { READ (stub env) EVAL PRINT } def /stdin (%stdin) (r) file def diff --git a/ps/step2_eval.ps b/ps/step2_eval.ps index 60d1906..72a91fa 100644 --- a/ps/step2_eval.ps +++ b/ps/step2_eval.ps @@ -12,6 +12,7 @@ /eval_ast { 2 dict begin /env exch def /ast exch def + %(eval_ast: ) print ast == /nametype ast type eq { %if symbol env ast get }{ /arraytype ast type eq { %elseif list @@ -25,15 +26,16 @@ } ifelse } ifelse end } def -/EVAL { 5 dict begin +/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 1 el length 1 sub getinterval % args array - el 0 get cvx % function + el _rest % args array + el _first % function %(vvv\n) print pstack (^^^\n) print exec % apply function to args } ifelse @@ -56,9 +58,7 @@ end } def (/) { dup 0 get exch 1 get idiv } >> def -/REP { - READ repl_env EVAL PRINT -} def +/REP { READ repl_env EVAL PRINT } def /stdin (%stdin) (r) file def diff --git a/ps/step3_env.ps b/ps/step3_env.ps new file mode 100644 index 0000000..c2e65cb --- /dev/null +++ b/ps/step3_env.ps @@ -0,0 +1,98 @@ +(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 { 10 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 + /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 + }{ + /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 +end } def + + +% print +/PRINT { + /exp exch def + %(printing: ) print exp == + exp 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 + +/stdin (%stdin) (r) file def + +{ % loop + (user> ) print flush + + %(%lineedit) (r) file 99 string readline + stdin 99 string readline + + not { exit } if % exit if EOF + + %(\ngot line: ) print dup print (\n) print flush + REP print (\n) print +} bind loop + +(\n) print % final newline before exit for cleanliness +quit diff --git a/ps/types.ps b/ps/types.ps index 2201cd4..5028c58 100644 --- a/ps/types.ps +++ b/ps/types.ps @@ -67,3 +67,53 @@ %pstack %(pr_str2 stack ^^^\n) print } def + + +% list operations +/_first { 0 get } def +/_rest { dup length 1 sub 1 exch getinterval } def +/_nth { get } def + + +% +% Env implementation +% +/env_new { 1 dict begin + /outer exch def + << + /__outer__ outer + >> +end } def + +/env_find { 2 dict begin + /key exch def + /env exch def + env key known { %if key in env + env + }{ env /__outer__ get null ne { %elseif __outer__ not null + env /__outer__ get key env_find + }{ %else + null + } ifelse } ifelse +end } def + +/env_set { 3 dict begin + /func dup xcheck def + /val exch cvlit def + /key exch def + /env exch def + env key val func { cvx } if put + val func { cvx } if +end } def + +/env_get { 2 dict begin + /key exch def + /env exch def + env key env_find + dup null eq { + (Error: ') print key 99 string cvs print (' not found\n) print + error + }{ + key get + } ifelse +end } def |
