Category:Initlib: Difference between revisions

→‎Library: restructuring
No edit summary
(→‎Library: restructuring)
Line 7:
initlib.ps
<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
/' {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
 
% 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}.
/car {first}.
Line 28 ⟶ 49:
/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.
% 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
/fold {rup exch rdown forall}.
%/reverse [1 2 3 4 5] 1{{} {addexch 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
% name - filter is taken so we are left with..
Line 52 ⟶ 75:
end}.
/zip {
[ rup [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 ]
}.
 
% [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 {
4 dict begin
Line 70 ⟶ 107:
} ifelse
end}.
% ift - allow stack invariant ifelse condition
% 2 {1 gt} {=} ift
 
/ifte {
4 dict begin
Line 83 ⟶ 119:
} ifelse
end}.
% switch statement.
% 1 {2 gt} {3 * =} {2 * =} ifte
 
/is? {{exit} concat cvx ift}.
/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}.
/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 {
[/.if /.then /.recrec1 /.joinrec2] let
.if {.then} {.rec /.if ' /.then ' /.rec ' /.join ' linrec . join } ifelse
{.rec1
{/.if ' /.then ' /.rec1 ' /.rec2 ' linrec} i
.rec2}
ifte
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)
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
 
</lang>
418

edits