Search code examples
postscript

What does the index method do in PostScript?


I don't understand what the index method does in postscript?

Let's take this code for example:


GS<2>stack
--nostringval-- <-- is an array [3 2 4]
3

GS<2> {
    dup             
    2 index <-- What is the index doing?        
    gt              
    {exch} if       
    pop             
  } forall

Solution

  • Do you have a copy of the PostScript Language Reference Manual ? If you want to program in PostScript you're going to need it.

    The index operator is defined on page 610 of the 3rd Edition PLRM:

    index anyn … any0 n index anyn … any0 anyn

    removes the nonnegative integer n from the operand stack, counts down to the nth element from the top of the stack, and pushes a copy of that element on the stack.

    Examples

    (a) (b) (c) (d) 0 index Þ (a) (b) (c) (d) (d)
    (a) (b) (c) (d) 3 index Þ (a) (b) (c) (d) (a)
    

    Errors: rangecheck, stackunderflow, typecheck

    See Also: copy, dup, roll

    So in your case, the index removes the '2' from the stack, it then counts along the stack 3 more places (index=2, index=1, index=0), and copies the object it finds there to the top of the stack.

    Now, your code fragment is operating in a 'forall', so when that runs it looks at the type of the operand on the top of the stack. In your case that's an array [3 2 4]. The forall operator pushes each element of the array in turn onto the stack, and then calls the executable array provided to the forall operator (that's your code).

    The first thing your code does is call 'dup' which duplicates the operand on the stack. So the first time through the loop, the forall operator will push the first element of the array, a '3', and then your code will duplicate it. So the stack will be:

    3
    3
    ?
    

    The ? here indicates that there's something unknown on the stack, we know it's there because the GS interactive prompt has a '2' in it, but you haven't told us what it is.

    We then push a 2 :

    2
    3
    3
    ?
    

    and do an index. Index removes the 2, and then counts back 3 places which brings us to the ?. That gets copied to the top of the stack, so the stack now looks like this:

    ?
    3
    3
    ?
    

    It then tests the '?' (without checking to see if it's a numeric data type) against the numeric value 3. If 3 is greater than ? then it pushes a true, otherwise it pushes a false.

    So now our stack is :

    true|false
    3
    ?
    

    We then push an executable array, leading to this stack:

    {exch}
    true|false
    3
    ?
    

    and execute the 'if' operator. If the boolean value is 'true' we execute the executable array, if it's false we don't and throw it away. So if ? > 3 we have :

    ?  % Numeric value > 3
    3
    

    Otherwise we have:

    3
    ?
    

    We then execute 'pop' which removes the top operand from the stack leaving either '?' or 3.

    Then we go round the loop again, using the value 2 and finally once more using the value 4.

    It looks like this is a 'max' function which is returning the largest value from an array of numeric data. Presumably the initial value is something like 0.