Category:Initlib: Difference between revisions
Content added Content deleted
(→Library: restructuring) |
(Improved display of source code, enabled syntax highlighting, and fixed sloppy formatting and typos.) |
||
(7 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{Library}} |
|||
Here is a library of functions tested in |
Here is a library of functions tested in GhostScript. 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' |
ghostscript -q -dNODISPLAY -c '(initlib.ps) run' |
||
</syntaxhighlight> |
|||
</lang> |
|||
initlib.ps |
== <code>initlib.ps</code> == |
||
< |
<syntaxhighlight lang="postscript" lines> |
||
%!PS |
%!PS |
||
% conventions: parameter names with let begins with . |
% conventions: parameter names with let begins with . |
||
Line 18: | Line 18: | ||
% some predicates. |
% some predicates. |
||
/eq? {eq |
/eq? {eq}. |
||
/list? {dup type /arraytype eq?}. |
/list? {dup type /arraytype eq?}. |
||
/leaf? {list? not}. |
/leaf? {list? not}. |
||
/empty? {dup length 0 eq?}. |
/empty? {dup length 0 eq?}. |
||
/zero? {dup 0 eq?}. |
/zero? {dup 0 eq?}. |
||
% stack invariant, execute any predicate and |
|||
% leave stack untouched except for answer. |
|||
⚫ | |||
⚫ | |||
[/.pred] let* |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
end}. |
|||
% stacky functions |
% stacky functions |
||
Line 53: | Line 64: | ||
/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. |
% make a unit list. |
||
/unit {1 array astore cvx}. |
/unit {1 array astore cvx}. |
||
Line 70: | Line 82: | ||
/find { |
/find { |
||
4 dict begin |
4 dict begin |
||
/aif {0 /get /if}. |
|||
/atox { [ exch cvx {cvx} forall ] cvx}. |
|||
[ rup [ /dup rdown /exec /not [{pop}] aif ] atox forall ] |
|||
end}. |
end}. |
||
⚫ | |||
/transpose { |
|||
[rup{ |
|||
[ exch { |
|||
dup length 0 eq rdown dup length 0 eq rdown or {exit} if |
|||
{ {empty? exch pop} map all?} {pop exit} ift |
|||
uncons rdown uncons rdown 4 2 roll unit cons rup exch |
|||
[ exch {} {uncons {exch cons} dip exch} fold counttomark 1 roll] uncons |
|||
} loop pop pop] |
|||
} loop ] {reverse} map |
|||
}. |
}. |
||
/zip {[rup] transpose}. |
|||
% [[1 2 3 4 ] [5 6 7 8] [9 10 11 12]] transpose |
|||
/all? { |
|||
{ |
|||
{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. |
% do on all elements of a tree. |
||
/treemap { |
/treemap { |
||
[/.tree /.rec] let |
[/.tree /.rec] let |
||
/.tree ' |
|||
{leaf?} /.rec ' |
|||
{{empty?} {} |
|||
{dup |
|||
{first /.rec ' treemap} dip |
|||
{rest /.rec ' treemap} i cons} |
|||
ifte} |
|||
ifte |
|||
end}. |
end}. |
||
Line 97: | Line 140: | ||
% ift - allow stack invariant if condition |
% ift - allow stack invariant if condition |
||
/ift { |
/ift { |
||
[/.if /.then] let |
|||
⚫ | |||
/.if ' ? /.then ' if |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} { |
|||
_restore |
|||
} ifelse |
|||
end}. |
end}. |
||
% ift - allow stack invariant ifelse condition |
% ift - allow stack invariant ifelse condition |
||
/ifte { |
/ifte { |
||
[/.if /.then /.else] let |
|||
⚫ | |||
/.if ' ? /.then ' /.else ' 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}. |
end}. |
||
% switch statement. |
% switch statement. |
||
Line 126: | Line 155: | ||
/dip { |
/dip { |
||
[/.v /.q] let |
[/.v /.q] let |
||
.q /.v ' |
|||
end}. |
end}. |
||
/apply {exec}. |
/apply {exec}. |
||
Line 133: | Line 162: | ||
/linrec { |
/linrec { |
||
[/.if /.then /.rec1 /.rec2] let |
[/.if /.then /.rec1 /.rec2] let |
||
/.if ' /.then ' |
|||
{.rec1 |
|||
{/.if ' /.then ' /.rec1 ' /.rec2 ' linrec} i |
|||
.rec2} |
|||
ifte |
|||
end}. |
end}. |
||
/binrec { |
/binrec { |
||
[/.if /.then /.rec1 /.rec2] let |
[/.if /.then /.rec1 /.rec2] let |
||
/.if ' /.then ' |
|||
{ .rec1 |
|||
{/.if ' /.then ' /.rec1 ' /.rec2 ' binrec} dip |
|||
{/.if ' /.then ' /.rec1 ' /.rec2 ' binrec} i |
|||
.rec2 } |
|||
ifte |
|||
end}. |
end}. |
||
/genrec { |
/genrec { |
||
[/.if /.then /.rec1 /.rec2] let |
[/.if /.then /.rec1 /.rec2] let |
||
/.if ' /.then ' |
|||
{.rec1 |
|||
{/.if ' /.then ' /.rec1 ' /.rec2 ' genrec} |
|||
.rec2} |
|||
ifte |
|||
end}. |
end}. |
||
Line 163: | Line 192: | ||
/primrec { |
/primrec { |
||
5 dict begin |
5 dict begin |
||
/lzero? { |
|||
{list?} {empty?} |
|||
{zero?} |
|||
ifte}. |
|||
/lnext { |
|||
{list?} {rest} |
|||
{pred} |
|||
ifte}. |
|||
[/.param /.then /.rec] let* |
[/.param /.then /.rec] let* |
||
{/.param ' lzero?} /.then ' |
|||
{.param |
|||
{/.param ' lnext /.then ' /.rec ' primrec} i |
|||
.rec} |
|||
ifte |
|||
end}. |
end}. |
||
/cvstr { |
|||
⚫ | |||
/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 |
|||
Line 183: | Line 231: | ||
/puts {= (\n) print flush}. |
/puts {= (\n) print flush}. |
||
/, {(=============\n) |
/, {(=============\n) |
||
print pstack |
|||
(=============\n) print}. |
|||
% set the prompt to something else so that we know initlib is loaded. |
% 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> |
Latest revision as of 19:55, 29 November 2023
Library
This is an example of a library. You may see a list of other libraries used on Rosetta Code at Category:Solutions by Library.
This is an example of a library. You may see a list of other libraries used on Rosetta Code at Category:Solutions by Library.
Here is a library of functions tested in GhostScript. It is assumed to be loaded before startup with a command-line such as
ghostscript -q -dNODISPLAY -c '(initlib.ps) run'
initlib.ps
%!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?}.
% 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
/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}.
/transpose {
[ exch {
{ {empty? exch pop} map all?} {pop exit} ift
[ exch {} {uncons {exch cons} dip exch} fold counttomark 1 roll] uncons
} loop ] {reverse} map
}.
/zip {[rup] transpose}.
% [[1 2 3 4 ] [5 6 7 8] [9 10 11 12]] transpose
/all? {
{
{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}.
% 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
/.if ' ? /.then ' /.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}.
/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 to something else so that we know initlib is loaded.
/prompt {(>| ) print flush} bind def
Pages in category "Initlib"
The following 27 pages are in this category, out of 27 total.