Category:Initlib: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
(Improved display of source code, enabled syntax highlighting, and fixed sloppy formatting and typos.)
 
(2 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
%!PS
% conventions: parameter names with let begins with .
% conventions: parameter names with let begins with .
Line 23: Line 23:
/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
% stack invariant, execute any predicate and
% except for answer.
% leave stack untouched except for answer.
/? {
/? {
4 dict begin
4 dict begin
[/.pred] let*
[/.pred] let*
count array astore /.stack exch def
count array astore /.stack exch def
/_restore {clear .stack aload pop}.
/_restore {clear .stack aload pop}.
.stack aload pop .pred /.top exch def
.stack aload pop .pred /.top exch def
_restore .top
_restore .top
end}.
end}.



% stacky functions
% stacky functions
Line 64: 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 81: Line 82:
/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}.


/transpose {
/transpose {
[ exch {
[ exch {
{ {empty? exch pop} map all?} {pop exit} ift
{ {empty? exch pop} map all?} {pop exit} ift
[ exch {} {uncons {exch cons} dip exch} fold counttomark 1 roll] uncons
[ exch {} {uncons {exch cons} dip exch} fold counttomark 1 roll] uncons
} loop ] {reverse} map
} loop ] {reverse} map
}.
}.
/zip {transpose}.
/zip {[rup] transpose}.


% [[1 2 3 4 ] [5 6 7 8] [9 10 11 12]] transpose
% [[1 2 3 4 ] [5 6 7 8] [9 10 11 12]] transpose
/all? {
/all? {
{
{
{empty?} ? {pop true exit} if
{empty?} ? {pop true exit} if
uncons {?} dip exch not {pop false exit} if
uncons {?} dip exch not {pop false exit} if
} loop
} loop
}.
}.
% 1 {{10 gt} {5 gt} {0 gt}} any?
% 1 {{10 gt} {5 gt} {0 gt}} any?
/any? {
/any? {
{
{
{empty?} ? {pop false exit} if
{empty?} ? {pop false exit} if
uncons {?} dip exch {pop true exit} if
uncons {?} dip exch {pop true exit} if
} loop
} loop
}.
}.
/pipe {
/pipe {
{
{
{empty?} ? {pop exit} if
{empty?} ? {pop exit} if
uncons {i} dip
uncons {i} dip
} loop
} loop
}.
}.
% 1 {{2 *} {3 *} {5 *}} pipe
% 1 {{2 *} {3 *} {5 *}} pipe
/collect {
/collect {
{
{
{empty?} ? {pop exit} if
{empty?} ? {pop exit} if
uncons {?} dip
uncons {?} dip
} loop
} loop
}.
}.
% 1 {{2 *} {3 *} {5 *}} collect
% 1 {{2 *} {3 *} {5 *}} collect
Line 126: Line 127:
/treemap {
/treemap {
[/.tree /.rec] let
[/.tree /.rec] let
/.tree '
/.tree '
{leaf?} /.rec '
{leaf?} /.rec '
{{empty?} {}
{{empty?} {}
{dup
{dup
{first /.rec ' treemap} dip
{first /.rec ' treemap} dip
{rest /.rec ' treemap} i cons}
{rest /.rec ' treemap} i cons}
ifte}
ifte}
ifte
ifte
end}.
end}.


Line 140: Line 141:
/ift {
/ift {
[/.if /.then] let
[/.if /.then] let
/.if ' ? /.then ' if
/.if ' ? /.then ' if
end}.
end}.
% ift - allow stack invariant ifelse condition
% ift - allow stack invariant ifelse condition
/ifte {
/ifte {
[/.if /.then /.else] let
[/.if /.then /.else] let
/.if ' ? /.then ' /.else ' ifelse
/.if ' ? /.then ' /.else ' ifelse
end}.
end}.
% switch statement.
% switch statement.
Line 154: Line 155:
/dip {
/dip {
[/.v /.q] let
[/.v /.q] let
.q /.v '
.q /.v '
end}.
end}.
/apply {exec}.
/apply {exec}.
Line 161: Line 162:
/linrec {
/linrec {
[/.if /.then /.rec1 /.rec2] let
[/.if /.then /.rec1 /.rec2] let
/.if ' /.then '
/.if ' /.then '
{.rec1
{.rec1
{/.if ' /.then ' /.rec1 ' /.rec2 ' linrec} i
{/.if ' /.then ' /.rec1 ' /.rec2 ' linrec} i
.rec2}
.rec2}
ifte
ifte
end}.
end}.


/binrec {
/binrec {
[/.if /.then /.rec1 /.rec2] let
[/.if /.then /.rec1 /.rec2] let
/.if ' /.then '
/.if ' /.then '
{ .rec1
{ .rec1
{/.if ' /.then ' /.rec1 ' /.rec2 ' binrec} dip
{/.if ' /.then ' /.rec1 ' /.rec2 ' binrec} dip
{/.if ' /.then ' /.rec1 ' /.rec2 ' binrec} i
{/.if ' /.then ' /.rec1 ' /.rec2 ' binrec} i
.rec2 }
.rec2 }
ifte
ifte
end}.
end}.


/genrec {
/genrec {
[/.if /.then /.rec1 /.rec2] let
[/.if /.then /.rec1 /.rec2] let
/.if ' /.then '
/.if ' /.then '
{.rec1
{.rec1
{/.if ' /.then ' /.rec1 ' /.rec2 ' genrec}
{/.if ' /.then ' /.rec1 ' /.rec2 ' genrec}
.rec2}
.rec2}
ifte
ifte
end}.
end}.


Line 191: Line 192:
/primrec {
/primrec {
5 dict begin
5 dict begin
/lzero? {
/lzero? {
{list?} {empty?}
{list?} {empty?}
{zero?}
{zero?}
ifte}.
ifte}.
/lnext {
/lnext {
{list?} {rest}
{list?} {rest}
{pred}
{pred}
ifte}.
ifte}.
[/.param /.then /.rec] let*
[/.param /.then /.rec] let*
{/.param ' lzero?} /.then '
{/.param ' lzero?} /.then '
{.param
{.param
{/.param ' lnext /.then ' /.rec ' primrec} i
{/.param ' lnext /.then ' /.rec ' primrec} i
.rec}
.rec}
ifte
ifte
end}.
end}.


/cvstr {
/cvstr {
4 dict begin
4 dict begin
/elements exch def
/elements exch def
/len elements length def
/len elements length def
/str len string def
/str len string def
/i 0 def
/i 0 def
{
{
i len ge { exit } if
i len ge { exit } if
str i
str i
%The element of the array, as a hexadecimal string.
% The element of the array, as a hexadecimal string.
%If it exceeds 16#FF, this will fail with a rangecheck.
% If it exceeds 16#FF, this will fail with a rangecheck.
elements i get cvi
elements i get cvi
put
put
/i i 1 add def
/i i 1 add def
} loop
} loop
str
str
end
end
} def
} def
Line 230: Line 231:
/puts {= (\n) print flush}.
/puts {= (\n) print flush}.
/, {(=============\n)
/, {(=============\n)
print pstack
print pstack
(=============\n) print}.
(=============\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.

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