Category:Initlib: Difference between revisions
No edit summary |
(→Library: restructuring) |
||
Line 7: | Line 7: | ||
initlib.ps |
initlib.ps |
||
<lang postscript> |
<lang postscript> |
||
%!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 |
/. {bind def} bind def |
||
/' {load} 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?}. |
|||
% stacky functions |
|||
/rup {3 1 roll}. |
|||
/rdown {3 -1 roll}. |
|||
/# {exch dup rdown .makeoperator bind def} bind def |
/# {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}. |
/first {0 get}. |
||
/car {first}. |
/car {first}. |
||
Line 28: | Line 49: | ||
/tail {dup length 1 sub get}. |
/tail {dup length 1 sub get}. |
||
/!tail {dup tail}. |
/!tail {dup tail}. |
||
/cons {[rup aload pop] |
/cons {[rup aload pop]}. |
||
/tadd {[rup aload length 1 add -1 roll] }. |
/tadd {[rup aload length 1 add -1 roll] }. |
||
/uncons {getname getbody}. |
/uncons {getname getbody}. |
||
/concat {exch [ rup aload pop counttomark -1 roll aload pop ] }. |
/concat {exch [ rup aload pop counttomark -1 roll aload pop ] }. |
||
% make a unit list. |
|||
% higher order |
|||
/unit {1 array astore cvx}. |
|||
/map { |
|||
/succ {1 add}. |
|||
[ rup forall ] |
|||
/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 |
% [1 2 3 4] {1 add} map |
||
/fold {rup exch rdown forall}. |
/fold {rup exch rdown forall}. |
||
% |
%/reverse {{} {exch 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 |
% [1 2 3 4] 0 {+} fold |
||
% name - filter is taken so we are left with.. |
% name - filter is taken so we are left with.. |
||
Line 52: | Line 75: | ||
end}. |
end}. |
||
/zip { |
/zip { |
||
[rup{ |
|||
dup length 0 eq rdown dup length 0 eq rdown or {exit} if |
dup length 0 eq rdown dup length 0 eq rdown or {exit} if |
||
uncons rdown uncons rdown 4 2 roll unit cons rup exch |
uncons rdown uncons rdown 4 2 roll unit cons rup exch |
||
} loop pop pop |
} loop pop pop] |
||
}. |
}. |
||
% [1 3 5 7] [2 4 6 8] zip |
|||
% do on all elements of a tree. |
|||
% ifs with stack invariant predicates. |
|||
/treemap { |
|||
[/.tree /.rec] let |
|||
/.tree ' |
|||
{leaf?} /.rec ' |
|||
{{empty?} {} |
|||
{dup |
|||
{first /.rec ' treemap} dip |
|||
{rest /.rec ' treemap} i cons} |
|||
ifte} |
|||
ifte |
|||
end}. |
|||
% control structures |
|||
% ift - allow stack invariant if condition |
|||
/ift { |
/ift { |
||
4 dict begin |
4 dict begin |
||
Line 70: | Line 107: | ||
} ifelse |
} ifelse |
||
end}. |
end}. |
||
% ift - allow stack invariant ifelse condition |
|||
% 2 {1 gt} {=} ift |
|||
/ifte { |
/ifte { |
||
4 dict begin |
4 dict begin |
||
Line 83: | Line 119: | ||
} ifelse |
} ifelse |
||
end}. |
end}. |
||
% switch statement. |
|||
% 1 {2 gt} {3 * =} {2 * =} ifte |
|||
/is? {{exit} concat cvx ift}. |
/is? {{exit} concat cvx ift}. |
||
/cond {{exit} concat cvx loop}. |
/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}. |
/apply {exec}. |
||
/i {cvx 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 { |
/linrec { |
||
[/.if /.then /.rec1 /.rec2] let |
|||
/.if ' /.then ' |
|||
{.rec1 |
|||
{/.if ' /.then ' /.rec1 ' /.rec2 ' linrec} i |
|||
.rec2} |
|||
ifte |
|||
end}. |
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}. |
|||
% debug |
|||
/puts {= (\n) print flush}. |
|||
/, {(=============\n) |
/, {(=============\n) |
||
print pstack |
print pstack |
||
(=============\n) print}. |
(=============\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 |
||
</lang> |
</lang> |
Revision as of 06:54, 27 March 2011
Library
Here is a library of functions tested in ghostscript. It is assumed to be loaded before startup with a command line such as <lang> ghostscript -q -dNODISPLAY -c '(initlib.ps) run' </lang>
initlib.ps <lang postscript> %!PS % conventions: parameter names with let begins with .
% basic definition, makes the definitions less verbose. /. {bind def} bind def /' {load} bind def /reverse {{} exch {exch [3 1 roll aload pop]} forall}. /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?}.
% stacky functions /rup {3 1 roll}. /rdown {3 -1 roll}. /# {exch dup rdown .makeoperator bind def} bind def
/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}. /!first {dup first}. /rest {dup length 1 sub 1 exch getinterval}. /cdr {rest}. /!rest {dup rest}. /head {dup length 1 sub 0 exch getinterval}. /!head {dup head}. /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 ] }. % make a unit list. /unit {1 array astore cvx}. /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 {{} {exch cons} fold}. % {} [1 2 3 4 5] {exch cons} 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}. /zip {
[rup{ dup length 0 eq rdown dup length 0 eq rdown or {exit} if uncons rdown uncons rdown 4 2 roll unit cons rup exch } loop pop pop]
}.
% 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}.
% control structures % ift - allow stack invariant if condition /ift {
4 dict begin [/.if /.then] let* count array astore /.stack exch def /_restore {clear .stack aload pop}. .stack aload pop .if { _restore .then } { _restore } ifelse
end}. % ift - allow stack invariant ifelse condition /ifte {
4 dict begin [/.if /.then /.else] let* 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. /is? {{exit} concat cvx ift}. /cond {{exit} concat cvx loop}.
% combinators /dip { [/.v /.q] let
.q /.v '
end}. /apply {exec}. /i {cvx exec}.
/linrec { [/.if /.then /.rec1 /.rec2] let
/.if ' /.then ' {.rec1 {/.if ' /.then ' /.rec1 ' /.rec2 ' linrec} i .rec2} ifte
end}.
/binrec { [/.if /.then /.rec1 /.rec2] let
/.if ' /.then ' { .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}.
% debug
/puts {= (\n) print flush}.
/, {(=============\n)
print pstack (=============\n) print}.
% set the prompt to something else so that we know initlib is loaded. /prompt {(>| ) print flush} bind def
</lang>
Pages in category "Initlib"
The following 27 pages are in this category, out of 27 total.