aboutsummaryrefslogtreecommitdiff
path: root/ps
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-12-18 20:33:49 -0600
committerJoel Martin <github@martintribe.org>2015-01-09 16:16:50 -0600
commitb8ee29b22fbaa7a01f2754b4d6dd9af52e02017c (patch)
treef4d977ed220e9a3f665cfbf4f68770a81e4c2095 /ps
parentaaba249304b184e12e2445ab22d66df1f39a51a5 (diff)
downloadmal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.tar.gz
mal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.zip
All: add keywords.
Also, fix nth and count to match cloure.
Diffstat (limited to 'ps')
-rw-r--r--ps/core.ps20
-rw-r--r--ps/printer.ps25
-rw-r--r--ps/reader.ps32
-rw-r--r--ps/types.ps23
4 files changed, 87 insertions, 13 deletions
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/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/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