aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-03-29 17:26:07 -0500
committerJoel Martin <github@martintribe.org>2014-03-29 17:26:07 -0500
commit04517bc8265b6930e96735dd5d12b7aac7d86217 (patch)
tree844ab6fc6efee9e86b7df80a7f9012b3378a0405
parent55e2bfa8a3a9fb98a405321d1183a3fbc872d118 (diff)
downloadmal-04517bc8265b6930e96735dd5d12b7aac7d86217.tar.gz
mal-04517bc8265b6930e96735dd5d12b7aac7d86217.zip
PS: add step3_env
-rw-r--r--docs/TODO2
-rw-r--r--ps/step0_repl.ps4
-rw-r--r--ps/step1_read_print.ps4
-rw-r--r--ps/step2_eval.ps12
-rw-r--r--ps/step3_env.ps98
-rw-r--r--ps/types.ps50
6 files changed, 157 insertions, 13 deletions
diff --git a/docs/TODO b/docs/TODO
index f530ef0..3c3df97 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -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