Category:Initlib: Difference between revisions
Content added Content deleted
(Improved display of source code, enabled syntax highlighting, and fixed sloppy formatting and typos.) |
|||
(10 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 |
|||
% 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?}. |
|||
% 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 |
/# {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 60: | ||
/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 ] }. |
||
% 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 |
% [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.. |
||
/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}. |
||
% ifs with stack invariant predicates. |
|||
/ |
/transpose { |
||
[ 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}. |
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 { |
/ifte { |
||
[/.if /.then /.else] let |
|||
4 dict begin |
|||
/.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. |
|||
% 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 { |
|||
exch aload pop |
|||
rup exch rdown {} for |
|||
}. |
|||
% [0 10] 2 range |
|||
% combinators |
|||
/linrec { |
/linrec { |
||
[/.if /.then /.rec1 /.rec2] let |
|||
/.if ' /.then ' |
|||
.if {.then} {.rec /.if ' /.then ' /.rec ' /.join ' linrec . join } ifelse |
|||
{.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}. |
|||
/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) |
/, {(=============\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> |
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.