Category:Initlib: Difference between revisions

From Rosetta Code
Content added Content deleted
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}.
% [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..
Line 52: Line 75:
end}.
end}.
/zip {
/zip {
[ rup {
[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 /.rec /.join] let
[/.if /.then /.rec1 /.rec2] let
.if {.then} {.rec /.if ' /.then ' /.rec ' /.join ' linrec . join } ifelse
/.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>