diff options
| author | Joel Martin <github@martintribe.org> | 2015-03-02 21:33:10 -0600 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-03-02 21:33:10 -0600 |
| commit | 835fb7d8b06e2b44792a97ac89994658bf6d00af (patch) | |
| tree | 578f67726ab9e3ce5fcbc50220e9761a66c5ddf1 /ps | |
| parent | 6b72e6078a7d505ecf9d711eb4a16fc4dfac36b6 (diff) | |
| parent | 8a98ef9a3f3a6b6d05d02dc305a0c886c907e0f3 (diff) | |
| download | mal-835fb7d8b06e2b44792a97ac89994658bf6d00af.tar.gz mal-835fb7d8b06e2b44792a97ac89994658bf6d00af.zip | |
Merge branch 'master' into gh-pages
Conflicts:
.gitignore
Diffstat (limited to 'ps')
| -rw-r--r-- | ps/Makefile | 2 | ||||
| -rw-r--r-- | ps/core.ps | 20 | ||||
| -rw-r--r-- | ps/interop.ps | 21 | ||||
| -rw-r--r-- | ps/printer.ps | 25 | ||||
| -rw-r--r-- | ps/reader.ps | 32 | ||||
| -rw-r--r-- | ps/step1_read_print.ps | 7 | ||||
| -rw-r--r-- | ps/step2_eval.ps | 7 | ||||
| -rw-r--r-- | ps/step3_env.ps | 9 | ||||
| -rw-r--r-- | ps/step4_if_fn_do.ps | 11 | ||||
| -rw-r--r-- | ps/step5_tco.ps | 11 | ||||
| -rw-r--r-- | ps/step6_file.ps | 11 | ||||
| -rw-r--r-- | ps/step7_quote.ps | 11 | ||||
| -rw-r--r-- | ps/step8_macros.ps | 11 | ||||
| -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.mal | 23 | ||||
| -rw-r--r-- | ps/types.ps | 23 |
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) @@ -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 |
