Category:Initlib: Difference between revisions

From Rosetta Code
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==
{{Library}}
Here is a library of functions tested in ghostscript. It is assumed to be loaded before startup with a command line such as
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> ==
<lang postscript>
<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}.
% [1 2 3 4 5] 1 {add} fold
%/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}.
/aif {0 /get /if}.
/atox { [ exch cvx {cvx} forall ] cvx}.
/atox { [ exch cvx {cvx} forall ] cvx}.
[ rup [ /dup rdown /exec /not [{pop}] aif ] atox forall ]
[ rup [ /dup rdown /exec /not [{pop}] aif ] atox forall ]
end}.
end}.

% ifs with stack invariant predicates.
/ift {
/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] 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.
% 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 /.rec /.join] let
[/.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
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</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.

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