Dear Log,
So, PostScript is hard. It's a stack language, and that made it ideal for what it needed to do decades ago; but in these days when people (understandably) are no more familiar with writing Forth than they are with coding in a hex assembler, it's just too damned hard to write by hand.
It sure would be nice to have an easier language that can do the same thing as PostScript -- i.e., write out pictures/text/etc. in the printer.
There have been some decent hacks at improving this situation:
While these are all admirable, they all seem to me half-hearted, or maybe seven-eighths hearted. And I want to do things just a bit better: to implement a Lisp interpreter (possibly later a Logo interpreter) entirely in PostScript, so that it won't need a separate translator program-- instead, you would just send Lisp code (prefaced by the interpreter) right to the printer, and/or view it with GhostScript.
I'm "almost done" with it (i.e., 90% done, which leaves only 90% left to do), and I've already named it: Skreeth. One part Scheme (altho this isn't a straight Scheme implementation), one part Screech, one part proto-Romance for "writes" (cf Latin scribet and Old French escriţ) and one part, uh, Skreeth.
It has been very interesting working through SICP's discussion of implementing a full-featured Lisp using only a simpler Lisp -- because there are interesting matches between PostScript and an even well-developed Lisp (for example, PostScript has invisible garbage collection, and has distinct types for arrays/vectors, booleans, strings, names/symbols, reals, integers, hashes, and a null/nil/undef object), and yet PostScript has only global variables -- which means sensible recursion is out, which means the recursive eval/apply in SICP has run into trouble. Implementing/faking local variables in PostScript has been an especially fun use of PostScript's wide powers of introspection. It has been a great exercise in implementation.
It has also been a wonderful tour of PostScript's most bizarre
features -- for example, there's no structure corresponding to
if(X) {a} elsif(Y) {b} elsif...
-- instead, you get to
have visibly nested code that corresponds to:
if(X) { a } else { if(Y) { b } else { ... } }...which gets REALLY annoying after about four conditions. And there's no switch/case/cond statement in the language. Making a hacky one is esay -- making one that won't trip you up in weird ways, is not easy.
And the stack... the stack!... it never ceases to amaze and appall. It starts out great with things like "/inch {72 mul} def", but it quickly turns very scary. It's the perfect computational embodiment of the old X lyric "this is the game that moves as you play".
I'll post more here as I get this thing more ready for people to look at, but at the moment I'm just dumping raw stuff in here.
As a peek, I'm expecting that this PostScript code...
297 421 translate 0 .1 400 { dup dup sqrt 4 div 0 360 arc fill 137.50775 rotate } for showpage
...will come out something like this in Skreeth:
(page (translate 297 421) (for (i 0 400 .1) (arc i i (/ (sqrt i) 4) 0 360) (fill) (rotate 137.50775) ) )
I'm not exactly a devotee of Lisp; but at the moment, given PostScript's limited string-manipulation powers and my own feebleness at implementing lexers/parsers, Lisp seems about the only choice. Lisp is not the friendliest language ever, but it's a step up from PostScript.
Re:Fantastic!
TorgoX on 2006-04-21T19:51:36
You just do "gs skreeth.psl" at a shell prompt to run the code. But for the moment that'll just run all the self-tests in the code and dump you at a GS prompt (where you can enter further PostScript commands). Enter "quit" to exit.