don@brillig.umd.edu (Don Hopkins) (04/19/89)
What if there was another bit in every PostScript array reference (like the executable bit), that when set, makes it an "inline executable array", i.e. when the interpreter hits an inline executable array, it would execute it (push it directly onto the execution stack) instead of pushing it onto the operand stack. Then autobind could replace names that were bound to inline executable arrays, as well as built-in operators like it does now... So you could define your own autobound inline PostScript functions, which didn't have to be looked up on the dict stack at run time! (You could accomplish the same thing manually by pushing the array and then doing an exec, ala {//myfunc exec}, but that's twice as many runs through the interpreter loop.) Inline executable arrays could save a lot of dictionary searches, especially when used for the non-primative functions in systemdict (the last dict in the search list, and quite a whopper), and commonly called functions in userdict. That's the funny thing about PostScript ... The interpreter treats arrays differently than everything else: When it comes across an executable array in a function, it pushes the array onto the operand stack, same as with literal arrays. I think it could speed things up a bit if you could have a kind of super-executable array that was automatically executed, that the scanner automatically autobinds into your functions. Something Forth has that PostScript doesn't is the notion of "immediacy". (This is something different than "inline executable arrays" described above.) Each Forth word has a bit that tells if it's immediate or not (most aren't). The compiler (i.e. scanner, in the case of a hypothetically extended PostScript) *executes* an immediate word (function) instead of compiling it (i.e. putting it into an executable array). It would be like an extended mode of autobind. Immediate functions take care of compiling (or scanning) themselves. They can even read things off the input stream following the token that invoked them. This mechanism is used in Forth for implementing control structures, macros, inline string literals, and other types of magic compiler constructs. The way the NeWS scanner works would have to be changed to accomodate immediate PostScript function, because the scanner uses its own special stack for building executable arrays. You'd want the PostScript scanner to put a mark on the operand stack, and push each array element as it's scanned. When it scans an executable token that's bound to an immediate function on the dict stack, it would execute that function, then go on scanning the rest of the array. Immediate PostScript functions would be able to look at the operand stack to see what of the array has been scanned so far, and anything they left on the stack would end up in the array. User definable magic variables and tuple-space operations (ala PIX) could be a great deal of fun, too! [Check out Wm Leler's "PIX, the latest NeWS" in the Proceedings of COMPCON Spring '89, IEEE, and N. Carriero and D. Gelernter's "Linda In Context", in the April 1989 CACM.] But then it wouldn't be PostScript TM, would it? (Ah, yes, the eternal tension between featurization and standardization. Phooey. Onward!) -Don
fons@cs.vu.nl (Fons Botman) (04/20/89)
In article <16993@mimsy.UUCP> don@brillig.umd.edu.UUCP (Don Hopkins) writes: >What if there was another bit in every PostScript array reference >(like the executable bit), that when set, makes it an "inline >executable array", i.e. [example, description and advantages deleted] I think something like that could be useful, but could not that be done by redefining "def"? Something like: /olddef /def load def /def { superbind olddef } olddef /superbind { % proc -> newproc integrate-operators % What autobind usually does integrate-executables % What you like to do } def Both the intergrate functions recursively walk down the executable arrays and perform the substitutions. intergrate-executable does something like: /double { 2 mul } def { xcoord ycoord double moveto } intergrate-executable ==> { xcoord ycoord 2 mul moveto } Is this the kind of thing you had in mind? With some extra work you can also do constant folding etc. >That's the funny thing about PostScript ... The interpreter treats >arrays differently than everything else: When it comes across an >executable array in a function, it pushes the array onto the operand >stack, same as with literal arrays. It does so also with executable number and strings. The only exception is an executable name which is looked up and executed. >Something Forth has that PostScript doesn't is the notion of >"immediacy". (This is something different than "inline executable >arrays" described above.) Each Forth word has a bit that tells if it's >immediate or not (most aren't). The compiler (i.e. scanner, in the >case of a hypothetically extended PostScript) *executes* an immediate >word (function) instead of compiling it (i.e. putting it into an >executable array). It would be like an extended mode of autobind. >Immediate functions take care of compiling (or scanning) themselves. >They can even read things off the input stream following the token >that invoked them. This mechanism is used in Forth for implementing >control structures, macros, inline string literals, and other types of >magic compiler constructs. The way the NeWS scanner works would have >to be changed to accomodate immediate PostScript function, because the >scanner uses its own special stack for building executable arrays. >You'd want the PostScript scanner to put a mark on the operand stack, >and push each array element as it's scanned. When it scans an >executable token that's bound to an immediate function on the dict >stack, it would execute that function, then go on scanning the rest >of the array. Immediate PostScript functions would be able to look at >the operand stack to see what of the array has been scanned so far, >and anything they left on the stack would end up in the array. I must admit that this is one of the the things in Forth i didn't like completely, but you can easily define your own control structures in postscript, "case" is one of the standard examples. something { 1 { (one) show } 2 { (two) show } { (many) show } } case > From: chris@goedel.uucp (Chris White) > Subject: Re: Beyond PostScript > Keywords: PostScript, Forth, Scheme > > This seems like a useful feature. It makes it easier > to construct executable arrays that must have "live" > information stuck in them during creation time. (The > old way is to use "[....] cvx" where everything inside > the square brackets often becomes unreadable due to > the fighting you have to do to keep the evaluator from > executing things too soon) > ... > I think scheme (lisp dialect) has a variation on this. > > Anyway, you still have to come up with a reasonable > syntax for the special array. > > How about: < {1 2 add} iexec 3 add > > > When scanned, this would push {3 3 add} onto the operand > stack. Does either PostScript or NeWS use the <> combination for > some kind of system construct? Alas, <A8B9> is a hexadecimal notation for a string. Scheme has indeed such a construct: `(a ,(+ 3 4) c) yields (a 7 c) Defining an operator "parse-it" which does: { a {, 3 4 add } c } parse-it ==> { a 7 c } should be no problem. Then you can write for instance. /movethere { {, 10 3.14 mul} {, 5 3.14 mul} moveto } parse-it def Or you could make superbind do this also. I am off to an appointment now, so i can't generate the source, but mail me if you have problems. The Fons