aboutsummaryrefslogtreecommitdiff
path: root/ps
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2015-03-02 21:33:10 -0600
committerJoel Martin <github@martintribe.org>2015-03-02 21:33:10 -0600
commit835fb7d8b06e2b44792a97ac89994658bf6d00af (patch)
tree578f67726ab9e3ce5fcbc50220e9761a66c5ddf1 /ps
parent6b72e6078a7d505ecf9d711eb4a16fc4dfac36b6 (diff)
parent8a98ef9a3f3a6b6d05d02dc305a0c886c907e0f3 (diff)
downloadmal-835fb7d8b06e2b44792a97ac89994658bf6d00af.tar.gz
mal-835fb7d8b06e2b44792a97ac89994658bf6d00af.zip
Merge branch 'master' into gh-pages
Conflicts: .gitignore
Diffstat (limited to 'ps')
-rw-r--r--ps/Makefile2
-rw-r--r--ps/core.ps20
-rw-r--r--ps/interop.ps21
-rw-r--r--ps/printer.ps25
-rw-r--r--ps/reader.ps32
-rw-r--r--ps/step1_read_print.ps7
-rw-r--r--ps/step2_eval.ps7
-rw-r--r--ps/step3_env.ps9
-rw-r--r--ps/step4_if_fn_do.ps11
-rw-r--r--ps/step5_tco.ps11
-rw-r--r--ps/step6_file.ps11
-rw-r--r--ps/step7_quote.ps11
-rw-r--r--ps/step8_macros.ps11
-rw-r--r--ps/step9_try.ps (renamed from ps/step9_interop.ps)61
-rw-r--r--ps/stepA_mal.ps (renamed from ps/stepA_more.ps)15
-rw-r--r--ps/tests/stepA_mal.mal23
-rw-r--r--ps/types.ps23
17 files changed, 226 insertions, 74 deletions
diff --git a/ps/Makefile b/ps/Makefile
index 43b5b70..9131674 100644
--- a/ps/Makefile
+++ b/ps/Makefile
@@ -2,7 +2,7 @@
TESTS =
SOURCES_BASE = types.ps reader.ps printer.ps
-SOURCES_LISP = env.ps core.ps stepA_more.ps
+SOURCES_LISP = env.ps core.ps stepA_mal.ps
SOURCES = $(SOURCES_BASE) $(SOURCES_LISP)
.PHONY: stats tests $(TESTS)
diff --git a/ps/core.ps b/ps/core.ps
index 191e5c3..52c9b05 100644
--- a/ps/core.ps
+++ b/ps/core.ps
@@ -87,8 +87,8 @@ end } def
_list_from_array
end } def
-% [listA listB] -> concat -> [listA... listB...]
-/concat { % replaces matric concat
+% [listA listB] -> do_concat -> [listA... listB...]
+/do_concat {
dup _count 0 eq { %if just concat
pop 0 _list
}{ dup _count 1 eq { %elseif concat of single item
@@ -102,6 +102,15 @@ end } def
} ifelse } ifelse
} def
+% [obj] -> do_count -> number
+/do_count {
+ 0 _nth dup _nil? {
+ pop 0
+ }{
+ _count
+ } ifelse
+} def
+
% [obj ...] -> first -> obj
/first {
0 _nth _first
@@ -220,7 +229,10 @@ end } def
(nil?) { 0 _nth _nil? }
(true?) { 0 _nth _true? }
(false?) { 0 _nth _false? }
+ (symbol) { 0 _nth _symbol }
(symbol?) { 0 _nth _symbol? }
+ (keyword) { 0 _nth _keyword }
+ (keyword?) { 0 _nth _keyword? }
(pr-str) { /data get ( ) true _pr_str_args }
(str) { /data get () false _pr_str_args }
@@ -254,12 +266,12 @@ end } def
(sequential?) { 0 _nth _sequential? }
(cons) { cons }
- (concat) { concat }
+ (concat) { do_concat }
(nth) { dup 0 _nth exch 1 _nth _nth }
(first) { first }
(rest) { rest }
(empty?) { 0 _nth _count 0 eq }
- (count) { 0 _nth _count }
+ (count) { do_count }
(conj) { conj }
(apply) { apply }
(map) { map }
diff --git a/ps/interop.ps b/ps/interop.ps
new file mode 100644
index 0000000..8020ab0
--- /dev/null
+++ b/ps/interop.ps
@@ -0,0 +1,21 @@
+% [ ps_val1...] -> ps2mal -> [ mal_val1...]
+/ps2mal {
+ % convert returned values to Mal types
+ [ exch
+ { %forall returned values
+ dup ==
+ dup type /arraytype eq {
+ (here1\n) print
+ _list_from_array
+ }{ dup type /dicttype eq {
+ (here2\n) print
+ _hash_map_from_dict
+ }{
+ (here3\n) print
+ % no-op
+ } ifelse } ifelse
+ } forall
+ ]
+ (here4\n) print
+} def
+
diff --git a/ps/printer.ps b/ps/printer.ps
index 3062e2d..52d6c1e 100644
--- a/ps/printer.ps
+++ b/ps/printer.ps
@@ -45,13 +45,24 @@
/slen obj 10 add log ceiling cvi def
obj 10 slen string cvrs
}{ /stringtype obj type eq { % if string
- print_readably {
- (")
- obj (\\) (\\\\) replace
- (") (\\") replace
- (") concatenate concatenate
- }{
- obj
+ obj length 0 gt { % if string length > 0
+ obj 0 get 127 eq { %if starts with 0x7f (keyword)
+ obj dup length string copy
+ dup 0 58 put % 58 is ':'
+ }{ print_readably {
+ (")
+ obj (\\) (\\\\) replace
+ (") (\\") replace
+ (") concatenate concatenate
+ }{
+ obj
+ } ifelse } ifelse
+ }{ % else empty string
+ print_readably {
+ ("")
+ }{
+ obj
+ } ifelse
} ifelse
}{ null obj eq { % if nil
(nil)
diff --git a/ps/reader.ps b/ps/reader.ps
index f1f63f6..4b268c0 100644
--- a/ps/reader.ps
+++ b/ps/reader.ps
@@ -52,6 +52,32 @@ end } def
end } def
+% read_keyword: read a single keyword from string/idx
+% string idx -> read_keyword -> name string new_idx
+/read_keyword { 5 dict begin
+ %(in read_keyword\n) print
+ /idx exch def
+ /str exch def
+ /start idx def
+ /cnt 0 def
+ { % loop
+ idx str length ge { exit } if % EOF, break loop
+ /ch str idx 1 getinterval def
+ token_delim ch search { % if token delimeter
+ pop pop pop exit
+ }{ % else not a delim
+ pop
+ /cnt cnt 1 add def
+ } ifelse
+ /idx idx 1 add def % increment idx
+ } loop
+
+ str start cnt getinterval % the matched keyword string
+ dup 0 127 put % TODO: something like (\x029e) would be better
+ str idx % return: keyword string new_idx
+end } def
+
+
% read_string: read a single string from string/idx
% string idx -> read_string -> new_string string new_idx
/read_string { 5 dict begin
@@ -94,8 +120,10 @@ end } def
%ch 48 ge ch 57 le and 45 ch eq or { %if number
ch 48 ge ch 57 le and { %if number
str idx read_number
- }{ ch 34 eq { %elseif double-quote
+ }{ ch 34 eq { %elseif double-quote (string)
str idx read_string
+ }{ ch 58 eq { %elseif colon (keyword)
+ str idx read_keyword
}{
str idx read_symbol
/idx exch def pop
@@ -108,7 +136,7 @@ end } def
}{ %else
str idx % return the original symbol/name
} ifelse } ifelse } ifelse
- } ifelse } ifelse
+ } ifelse } ifelse } ifelse
}ifelse
% return: atom string new_idx
diff --git a/ps/step1_read_print.ps b/ps/step1_read_print.ps
index 476c917..858987c 100644
--- a/ps/step1_read_print.ps
+++ b/ps/step1_read_print.ps
@@ -1,6 +1,7 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
diff --git a/ps/step2_eval.ps b/ps/step2_eval.ps
index 551c637..215fc2e 100644
--- a/ps/step2_eval.ps
+++ b/ps/step2_eval.ps
@@ -1,6 +1,7 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
diff --git a/ps/step3_env.ps b/ps/step3_env.ps
index 92dc26e..e662c11 100644
--- a/ps/step3_env.ps
+++ b/ps/step3_env.ps
@@ -1,7 +1,8 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
+/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 99 string readline } def
diff --git a/ps/step4_if_fn_do.ps b/ps/step4_if_fn_do.ps
index 9e628b6..422f6eb 100644
--- a/ps/step4_if_fn_do.ps
+++ b/ps/step4_if_fn_do.ps
@@ -1,8 +1,9 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
-(core.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
+(env.ps) runlibfile
+(core.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
diff --git a/ps/step5_tco.ps b/ps/step5_tco.ps
index 83fd43b..680c359 100644
--- a/ps/step5_tco.ps
+++ b/ps/step5_tco.ps
@@ -1,8 +1,9 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
-(core.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
+(env.ps) runlibfile
+(core.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
diff --git a/ps/step6_file.ps b/ps/step6_file.ps
index 7d1c876..bc30e35 100644
--- a/ps/step6_file.ps
+++ b/ps/step6_file.ps
@@ -1,8 +1,9 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
-(core.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
+(env.ps) runlibfile
+(core.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
diff --git a/ps/step7_quote.ps b/ps/step7_quote.ps
index d7340fd..3dd9c0c 100644
--- a/ps/step7_quote.ps
+++ b/ps/step7_quote.ps
@@ -1,8 +1,9 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
-(core.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
+(env.ps) runlibfile
+(core.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
diff --git a/ps/step8_macros.ps b/ps/step8_macros.ps
index 3bf304c..32ca3af 100644
--- a/ps/step8_macros.ps
+++ b/ps/step8_macros.ps
@@ -1,8 +1,9 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
-(core.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
+(env.ps) runlibfile
+(core.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
diff --git a/ps/step9_interop.ps b/ps/step9_try.ps
index de3d2af..d9beec7 100644
--- a/ps/step9_interop.ps
+++ b/ps/step9_try.ps
@@ -1,8 +1,9 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
-(core.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
+(env.ps) runlibfile
+(core.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
@@ -143,20 +144,6 @@ end } def
env exch a1 exch env_set % def! it
}{ /macroexpand a0 eq { %if defmacro!
ast 1 _nth env macroexpand
- }{ /ps* a0 eq { %if ps*
- count /stackcnt exch def
- ast 1 _nth
- {
- token not { exit } if
- exch
- } loop
- exec
- count stackcnt gt { % if new operands on stack
- % return an list of new operands
- count stackcnt sub array astore
- }{
- null % return nil
- } ifelse
}{ /do a0 eq { %if do
ast _count 2 gt { %if ast has more than 2 elements
ast 1 ast _count 2 sub _slice env eval_ast pop
@@ -164,6 +151,42 @@ end } def
ast ast _count 1 sub _nth % last ast becomes new ast
env
/loop? true def % loop
+ }{ /try* a0 eq { %if try*
+ { %try
+ countdictstack /dictcnt exch def
+ count /stackcnt exch def
+ ast 1 _nth env EVAL
+ } stopped { %catch
+ % clean up the dictionary stack
+ 1 1 countdictstack dictcnt sub { %foreach added dict
+ %(popping dict\n) print
+ pop end % pop idx and pop dict
+ %(new ast: ) print ast true _pr_str print (\n) print
+ } for
+ % clean up the operand stack
+ count 1 exch 1 exch stackcnt sub { %foreach added operand
+ %(op stack: ) print pstack
+ pop pop % pop idx and operand
+ %(popped op stack\n) print pstack
+ } for
+ % get error data and reset $error dict
+ /errdata get_error_data def
+ $error /newerror false put
+ $error /errorinfo null put
+
+ ast _count 3 lt { %if no third (catch*) form
+ errdata throw
+ } if
+ ast 2 _nth 0 _nth (catch*) eq not { %if third form not catch*
+ (No catch* in throw form) _throw
+ } if
+ ast 2 _nth 2 _nth
+ env
+ ast 2 _nth 1 _nth 1 _list
+ errdata 1 _list
+ env_new
+ EVAL
+ } if
}{ /if a0 eq { %if if
/a1 ast 1 _nth def
/cond a1 env EVAL def
diff --git a/ps/stepA_more.ps b/ps/stepA_mal.ps
index 76d0a86..c879294 100644
--- a/ps/stepA_more.ps
+++ b/ps/stepA_mal.ps
@@ -1,8 +1,9 @@
-(types.ps) run
-(reader.ps) run
-(printer.ps) run
-(env.ps) run
-(core.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse %
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
+(env.ps) runlibfile
+(core.ps) runlibfile
% read
/_readline { print flush (%stdin) (r) file 99 string readline } def
@@ -149,8 +150,10 @@ end } def
{
token not { exit } if
exch
+ count stackcnt sub 1 roll % send leftover string to bottom
+ exec
+ count stackcnt sub -1 roll % bring leftover string to top
} loop
- exec
count stackcnt gt { % if new operands on stack
% return an list of new operands
count stackcnt sub array astore
diff --git a/ps/tests/stepA_mal.mal b/ps/tests/stepA_mal.mal
new file mode 100644
index 0000000..fffa178
--- /dev/null
+++ b/ps/tests/stepA_mal.mal
@@ -0,0 +1,23 @@
+;; Testing basic ps interop
+
+(ps* "7")
+;=>(7)
+
+(ps* "(7)")
+;=>("7")
+
+(ps* "7 8 9 3 array astore")
+;=>((7 8 9))
+
+(ps* "1 1 eq")
+;=>(true)
+
+(ps* "/sym")
+;=>sym
+
+(ps* "1 1 eq { (yep) }{ (nope) } ifelse")
+;=>("yep")
+
+(ps* "1 0 eq { (yep) }{ (nope) } ifelse")
+;=>("nope")
+
diff --git a/ps/types.ps b/ps/types.ps
index 82be9c2..1f6903e 100644
--- a/ps/types.ps
+++ b/ps/types.ps
@@ -173,11 +173,34 @@ end } def
% Symbols
+/_symbol {
+ dup length string copy cvn
+} def
+
/_symbol? {
type /nametype eq
} def
+% Keywords
+
+/_keyword { 1 dict begin
+ /str exch def
+ str length 1 add string % str2
+ dup 1 str putinterval
+ dup 0 127 put % TODO: something like (\x029e) would be better
+end } def
+
+/_keyword? {
+ dup type /stringtype eq {
+ 0 get 127 eq
+ }{
+ false
+ } ifelse
+} def
+
+
+
% Functions
% block -> _function -> boxed_function