![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
OK, so I'm sitting here reading the PostScript Language Reference Manual
(3rd edition).
PostScript seems like a simple enough language. But when you sit down to
try to *implement* it rather than just *use* it... you discover that
there are a few simple little statements in the spec that make it really
quite awkward.
For example, PostScript involves "dictionaries". A dictionary stores
key/value pairs. The key will usually be a "name" object. However,
reading the small-print, I discover that a key can *actually* be any
possible PostScript object.
So, for example, you can push the current graphics state onto the
operand stack and use THE ENTIRE GRAPHICS STATE as a key! o_O
In other small-print, I discover that "composite" objects are explicitly
mutable. If you "copy" such an object, it merely copies the reference to
it. If you mutate the copy object, the original object sees the change
too. Fair enough...
...except, wait a sec. So you're telling me I can MUTATE DICTIONARY KEYS??
This is highly interesting, since the keys of a dictionary must, by
definition, be unique. If you insert a key into the dictionary, it
checks to see if such a key already exists. If so, that key's value is
replaced, otherwise the inserted value becomes a new entry.
But wait! I can insert a new key, and then mutate it to match one of the
existing keys. How does *that* work?? Do we now have a dictionary with
two identical keys? Or does one of the keys get deleted? (Which requires
monitoring every single object mutation to check whether it's a key
somewhere.) Or...??
Of course, 99% of all PostScript code actually uses names as keys, so
all of this is a complete non-issue. But theoreticaly 1% of the code out
there might actually try to use a font description as a key, and if the
interpretter is going to work properly, it has to support this. *sigh*
Other amusing edge cases include "/":
- A name is usually executable; by preceeding it with "/", it becomes
literal.
- The toke "/" by itself (i.e., not preceeding a name) is a valid
(executable) name.
Trixy Hobbitses!
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> In other small-print, I discover that "composite" objects are explicitly
> mutable. If you "copy" such an object, it merely copies the reference to
> it. If you mutate the copy object, the original object sees the change
> too. Fair enough...
>
> ...except, wait a sec. So you're telling me I can MUTATE DICTIONARY KEYS??
>
> This is highly interesting, since the keys of a dictionary must, by
> definition, be unique. If you insert a key into the dictionary, it
> checks to see if such a key already exists. If so, that key's value is
> replaced, otherwise the inserted value becomes a new entry.
>
> But wait! I can insert a new key, and then mutate it to match one of the
> existing keys. How does *that* work?? Do we now have a dictionary with
> two identical keys? Or does one of the keys get deleted? (Which requires
> monitoring every single object mutation to check whether it's a key
> somewhere.) Or...??
According to the reference page for he "eq" operator, two composite
objects are "equal" if they point to the same data structure. In other
words, PostScript seems to work on reference equality, not value equality.
Thus, a copy of a composite object is always equal to that copy, and two
seperate composite objects are always unequal, regardless of what you
mutate their values to.
Still a fairly strange design decision, but it doesn't seem *quite* so
insane now... ;-)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible <voi### [at] dev null> wrote:
> For example, PostScript involves "dictionaries". A dictionary stores
> key/value pairs. The key will usually be a "name" object. However,
> reading the small-print, I discover that a key can *actually* be any
> possible PostScript object.
Welcome to object-oriented programming... :P
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible escreveu:
> For example, PostScript involves "dictionaries". A dictionary stores
> key/value pairs. The key will usually be a "name" object. However,
> reading the small-print, I discover that a key can *actually* be any
> possible PostScript object.
>
> So, for example, you can push the current graphics state onto the
> operand stack and use THE ENTIRE GRAPHICS STATE as a key! o_O
Are you sure it's not a hash/id for THE ENTIRE GRAPHICS STATE rather
than it itself?
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> OK, so I'm sitting here reading the PostScript Language Reference Manual
> (3rd edition).
>
I assume you are already aware of this, but I'll provide a link anyways:
http://circle.ch/blog/p558.html
-Aero
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Eero Ahonen wrote:
> I assume you are already aware of this, but I'll provide a link anyways:
>
> http://circle.ch/blog/p558.html
Why...why...WHY...why would they do this? o_O
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
nemesis wrote:
>> So, for example, you can push the current graphics state onto the
>> operand stack and use THE ENTIRE GRAPHICS STATE as a key! o_O
>
> Are you sure it's not a hash/id for THE ENTIRE GRAPHICS STATE rather
> than it itself?
Check my other post. It uses pointer equality, not value equality. (So
pushing the graphics state is just as good as allocating an empty array;
it generates a unique memory address.)
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Invisible <voi### [at] dev null> wrote:
>> For example, PostScript involves "dictionaries". A dictionary stores
>> key/value pairs. The key will usually be a "name" object. However,
>> reading the small-print, I discover that a key can *actually* be any
>> possible PostScript object.
>
> Welcome to object-oriented programming... :P
LOL!
Maybe you'll appreciate this... Did you know that PostScript includes
the tail-recursion optimisation?
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> Other amusing edge cases include "/":
>
> - A name is usually executable; by preceeding it with "/", it becomes
> literal.
>
> - The toke "/" by itself (i.e., not preceeding a name) is a valid
> (executable) name.
>
> Trixy Hobbitses!
Also fun is trying to write a correct number parser:
- ".0" and "0." are both real number objects (equal to 0.0).
- "." by itself is a name object.
- PostScript allows both "-" and "+" as sign prefixes (which is good).
Haskell does not, however (which is bad).
Basically, getting the parser to accept only valid PostScript numbers,
and return the correct value, is proving to be very difficult! :-(
This is what happens when you try to interface your program with
real-world systems; not everything is simple and mathematically elegant,
and it makes stuff much harder to code. I'm not giving up though! >:-D
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> Also fun is trying to write a correct number parser:
>
> - ".0" and "0." are both real number objects (equal to 0.0).
>
> - "." by itself is a name object.
>
> - PostScript allows both "-" and "+" as sign prefixes (which is good).
> Haskell does not, however (which is bad).
Now the joy of parsing strings.
Simple, right? RIGHT??
Ah, but you forget about *escape sequences*! >:-]
PostScript supports these:
- Strings are delimited with brackets, not quotes.
- Matched brackets work automatically. Unmatches ones must be escaped.
- \n, \t, etc.
- \\ is a backslash, \( and \) are brackets.
- \100 is an octal character code. (Oh what fun finding an octal
conversion function!)
- A backslash before a newline discards the newline character.
- Anything else preceeded by a backslash is just itself.
Man my head hurts... Again, 2% of the functionality takes 90% of the
implementation effort! >_<
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |