1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-11 00:52:44 +03:00
mal/ps/printer.ps
2016-02-26 21:40:25 -06:00

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