Category:Initlib: Difference between revisions

Improved display of source code, enabled syntax highlighting, and fixed sloppy formatting and typos.
(Improved display of source code, enabled syntax highlighting, and fixed sloppy formatting and typos.)
 
(9 intermediate revisions by 2 users not shown)
Line 1:
=={{Library==}}
Here is a library of functions tested in ghostscriptGhostScript. It is assumed to be loaded before startup with a command -line such as
<syntaxhighlight lang="shell" inline>
<lang>
ghostscript -q -dNODISPLAY -c '(initlib.ps) run'
</syntaxhighlight>
</lang>
 
== <code>initlib.ps</code> ==
<langsyntaxhighlight lang="postscript" lines>
%!PS
% given [sym x y z] get sym and [x y z] separately
% conventions: parameter names with let begins with .
/getname {dup 0 get exch} bind def
 
/getbody {dup length 1 sub 1 exch getinterval} bind def
% basic definition, makes the definitions less verbose.
/rup {3 1 roll} bind def
/rdown {3 -1 roll} bind def
% convenience for binding.
/. {bind def} bind def
/' {load} bind def
/reverse {{} exch {exch [3 1 roll aload pop]} forall}.
% .makeoperator is ghostscript specific. But this gives us lexical binding.
/let {dup length dict begin reverse {exch def} forall}.
/let* {reverse {exch def} forall}.
 
% some predicates.
/eq? {eq}.
/list? {dup type /arraytype eq?}.
/leaf? {list? not}.
/empty? {dup length 0 eq?}.
/zero? {dup 0 eq?}.
 
% stack invariant, execute any predicate and
% leave stack untouched except for answer.
/? {
4 dict begin
[/.pred] let*
count array astore /.stack exch def
/_restore {clear .stack aload pop}.
.stack aload pop .pred /.top exch def
_restore .top
end}.
 
% stacky functions
/rup {3 1 roll}.
/rdown {3 -1 roll}.
/# {exch dup rdown .makeoperator bind def} bind def
 
% A few lispy words
/getname {dup 0 get exch}.
/getbody {dup length 1 sub 1 exch getinterval}.
 
% convenience arithmetic
/+ {add}.
/- {sub}.
/* {mul}.
/\ {div}.
 
% lispy functions
/first {0 get}.
/car {first}.
Line 28 ⟶ 60:
/tail {dup length 1 sub get}.
/!tail {dup tail}.
/cons {[rup aload pop] }.
/tadd {[rup aload length 1 add -1 roll] }.
/uncons {getname getbody}.
/concat {exch [ rup aload pop counttomark -1 roll aload pop ] }.
 
% higher order
% make a unit list.
/map {
/unit {1 array astore cvx}.
[ rup forall ]
/succ {1 add}.
}.
/pred {1 sub}.
/range {[rup exch aload pop rup exch rdown {} for]}.
 
% higher order thingies.
/map { [ rup forall ] }.
% [1 2 3 4] {1 add} map
/fold {rup exch rdown forall}.
%/reverse [1 2 3 4 5] 1{{} {addexch cons} fold}.
% {} [1 2 3 4 5] {exch cons} forall
% let requires "end" to denote end of scope
 
/let {dup length dict begin reverse {exch def} forall}.
% let* assumes dictionary management is separate.
/let* {reverse {exch def} forall}.
% [1 2 3 4] 0 {+} fold
% name - filter is taken so we are left with..
/find {
4 dict begin
/aif {0 /get /if}.
/atox { [ exch cvx {cvx} forall ] cvx}.
[ rup [ /dup rdown /exec /not [{pop}] aif ] atox forall ]
end}.
 
% ifs with stack invariant predicates.
/ifttranspose {
[ exch {
4 dict begin
{ {empty? exch pop} map all?} {pop exit} ift
[/.if /.then] let*
[ exch {} {uncons {exch cons} dip exch} fold counttomark 1 roll] uncons
count array astore /.stack exch def
} loop ] {reverse} map
/_restore {clear .stack aload pop}.
}.
.stack aload pop .if {
/zip {[rup] transpose}.
_restore .then
 
} {
% [[1 2 3 4 ] [5 6 7 8] [9 10 11 12]] transpose
_restore
/all? {
} ifelse
{
{empty?} ? {pop true exit} if
uncons {?} dip exch not {pop false exit} if
} loop
}.
% 1 {{10 gt} {5 gt} {0 gt}} any?
/any? {
{
{empty?} ? {pop false exit} if
uncons {?} dip exch {pop true exit} if
} loop
}.
/pipe {
{
{empty?} ? {pop exit} if
uncons {i} dip
} loop
}.
% 1 {{2 *} {3 *} {5 *}} pipe
/collect {
{
{empty?} ? {pop exit} if
uncons {?} dip
} loop
}.
% 1 {{2 *} {3 *} {5 *}} collect
 
% do on all elements of a tree.
/treemap {
[/.tree /.rec] let
/.tree '
{leaf?} /.rec '
{{empty?} {}
{dup
{first /.rec ' treemap} dip
{rest /.rec ' treemap} i cons}
ifte}
ifte
end}.
% 2 {1 gt} {=} ift
 
% control structures
% ift - allow stack invariant if condition
/ift {
[/.if /.then] let
/.if ' ? /.then ' if
end}.
% ift - allow stack invariant ifelse condition
/ifte {
[/.if /.then /.else] let
4 dict begin
/.if ' ? [/.if /.then ' /.else] let*' ifelse
count array astore /.stack exch def
/_restore {count array astore pop .stack aload pop}.
.stack aload pop .if {
_restore .then
} {
_restore .else
} ifelse
end}.
% switch statement.
% 1 {2 gt} {3 * =} {2 * =} ifte
 
/is? {{exit} concat cvx ift}.
/cond {{exit} concat cvx loop}.
 
% 100 { {0 eq} {(not-hun) puts} is? {100 eq} {(hundred) puts} is? } cond
% combinators
/dip {
[/.v /.q] let
.q /.v '
end}.
/apply {exec}.
/i {cvx exec}.
 
% make a unit list.
/unit {1 array astore cvx}.
/succ {1 add}.
/pred {1 sub}.
/range {
[ rup exch aload pop rup exch rdown {} for ]
}.
% [0 10] 2 range
% combinators
/linrec {
[/.if /.then /.recrec1 /.joinrec2] let
/.if ' /.then '
.if {.then} {.rec /.if ' /.then ' /.rec ' /.join ' linrec . join } ifelse
{.rec1
{/.if ' /.then ' /.rec1 ' /.rec2 ' linrec} i
.rec2}
ifte
end}.
 
/binrec {
% and convenience
[/.if /.then /.rec1 /.rec2] let
/reverse {{} {exch cons} fold}.
/.if ' /.then '
/puts {print (\n) print flush}.
{ .rec1
{/.if ' /.then ' /.rec1 ' /.rec2 ' binrec} dip
{/.if ' /.then ' /.rec1 ' /.rec2 ' binrec} i
.rec2 }
ifte
end}.
 
/genrec {
[/.if /.then /.rec1 /.rec2] let
/.if ' /.then '
{.rec1
{/.if ' /.then ' /.rec1 ' /.rec2 ' genrec}
.rec2}
ifte
end}.
 
/tailrec {{} linrec}.
 
/primrec {
5 dict begin
/lzero? {
{list?} {empty?}
{zero?}
ifte}.
/lnext {
{list?} {rest}
{pred}
ifte}.
[/.param /.then /.rec] let*
{/.param ' lzero?} /.then '
{.param
{/.param ' lnext /.then ' /.rec ' primrec} i
.rec}
ifte
end}.
 
/cvstr {
4 dict begin
/elements exch def
/len elements length def
/str len string def
/i 0 def
{
i len ge { exit } if
str i
% The element of the array, as a hexadecimal string.
% If it exceeds 16#FF, this will fail with a rangecheck.
elements i get cvi
put
/i i 1 add def
} loop
str
end
} def
 
 
% debug
/puts {= (\n) print flush}.
/, {(=============\n)
print pstack
(=============\n) print}.
 
% set the prompt
% set the prompt to something else so that we know initlib is loaded.
/prompt {(>| ) print flush} bind def
/prompt {(>| ) print flush} bind def</syntaxhighlight>
</lang>
6

edits