mirror of
https://github.com/kanaka/mal.git
synced 2024-11-11 00:52:44 +03:00
eeca7d7034
Issue #178
116 lines
3.4 KiB
PostScript
116 lines
3.4 KiB
PostScript
% requires types.ps to be included first
|
|
|
|
% ast print_readably -> _pr_str -> string
|
|
/_pr_str { 4 dict begin
|
|
/print_readably exch def
|
|
dup xcheck { (Cannot print proc: ) print dup == quit } if % assert
|
|
/obj exch def
|
|
obj _sequential? {
|
|
obj _list? { (\() (\)) }{ ([) (]) } ifelse
|
|
obj /data get ( ) print_readably _pr_str_args
|
|
exch concatenate concatenate
|
|
}{ obj _hash_map? {
|
|
({)
|
|
% get array of contents with keys stringified
|
|
[ obj /data get { exch dup length string cvs exch } forall ]
|
|
( ) print_readably _pr_str_args
|
|
concatenate
|
|
(}) concatenate
|
|
}{ obj _function? { % if builtin function
|
|
(<\(builtin_fn* {)
|
|
obj /data get dup length array copy cvlit
|
|
( ) print_readably _pr_str_args
|
|
(}>)
|
|
concatenate concatenate
|
|
}{ obj _mal_function? { % if user defined mal_function
|
|
(<\(fn* )
|
|
obj /params get print_readably _pr_str
|
|
( )
|
|
obj /ast get print_readably _pr_str
|
|
(\)>)
|
|
concatenate concatenate concatenate concatenate
|
|
}{ obj _atom? { % if atom
|
|
(\(atom )
|
|
obj /data get print_readably _pr_str
|
|
(\))
|
|
concatenate concatenate
|
|
}{ /arraytype obj type eq { % if list or code block
|
|
% accumulate an array of strings
|
|
(\()
|
|
obj ( ) print_readably _pr_str_args
|
|
concatenate
|
|
(\))
|
|
concatenate
|
|
}{ /integertype obj type eq { % if number
|
|
/slen
|
|
obj abs 1 max log floor cvi 1 add % positive size
|
|
obj 0 lt { 1 add } if % account for sign
|
|
def
|
|
obj 10 slen string cvrs
|
|
}{ /stringtype obj type eq { % if string
|
|
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
|
|
(\n) (\\n) replace
|
|
(") concatenate concatenate
|
|
}{
|
|
obj
|
|
} ifelse } ifelse
|
|
}{ % else empty string
|
|
print_readably {
|
|
("")
|
|
}{
|
|
obj
|
|
} ifelse
|
|
} ifelse
|
|
}{ null obj eq { % if nil
|
|
(nil)
|
|
}{ true obj eq { % if true
|
|
(true)
|
|
}{ false obj eq { % if false
|
|
(false)
|
|
}{ /nametype obj type eq { % if symbol
|
|
obj dup length string cvs
|
|
}{
|
|
(<unknown>)
|
|
} ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse
|
|
end } def
|
|
|
|
% array delim print_readably -> _pr_str_args -> new_string
|
|
/_pr_str_args { 3 dict begin
|
|
/print_readably exch def
|
|
/delim exch def
|
|
/args exch def
|
|
()
|
|
args length 0 gt { %if any elements
|
|
[
|
|
args { %foreach argument in array
|
|
dup xcheck { %if executable
|
|
255 string cvs
|
|
}{
|
|
print_readably _pr_str
|
|
} ifelse
|
|
} forall
|
|
]
|
|
{ concatenate delim concatenate } forall
|
|
dup length delim length sub 0 exch getinterval % strip off final delim
|
|
} if
|
|
end } def
|
|
|
|
% utility function
|
|
/print_dict {
|
|
(DICT contents:\n) print
|
|
{
|
|
( - ) print
|
|
exch dup length string cvs print % key
|
|
(: ) print
|
|
==
|
|
} forall
|
|
} def
|
|
|