Определение переменных и процедур
Переменные. Чтобы определить переменную в PostScript, ее имя и значение нужно занести в текущий словарь. Это делается с помощью оператора def, как в следующем примере:
/ed 47 def
Косая черта перед именем переменной показывает, что интерпретатору следует поместить это имя в стек как литерал и не пытаться сразу же искать его в словаре. Вслед за именем в стек заносится число 47. И наконец def берет оба эти объекта из стека и помещает их в текущий словарь. Второй элемент стека (ed) становится ключом, с которым ассоциировано значение первого элемента (47). На первый взгляд это больше похоже на определение константы, чем переменной. Однако определенное с помощью def значение переменной может быть изменено либо новым оператором def, либо другими операторами, например:
/ed 52 def
Посмотрим на примере, как PostScript работает с новой переменной. Если дальше в программе появится строка:
13 ed add
то интерпретатор сделает следующее:
1) поместит число 13 в стек;
2) найдет в стеке словарей значение для ключа ed и поместит его в стек;
3) сложит два числа из вершины стека, заменив их полученной суммой.
Следующий оператор умножает значение переменной ed на 5:
/ed ed 5 mul def
Задание. Используя приведенные выше правила, определите содержимое стека в каждый момент выполнения этой строки.
Процедуры. Процедура в PostScript - это набор операторов сгруппированных под общим именем. Имя процедуры является ключом в словаре, а набор операторов ассоциируется как его значение. Когда имя процедуры появляется в программе, то выполняется связанный с ним набор операторов. Процедуры в PostScript определяются точно так же, как и переменные, с тем только отличием, что набор операторов процедуры должен быть заключен в фигурные скобки. Следующая строка, например, описывает процедуру inch (дюйм), полезную для перевода дюймов в систему единиц, используемую в PostScript по умолчанию.
/inch {72 mul} def
Любое появление слова inch после этой строки заставит интерпретатор поместить в стек число 72, умножить его на число лежащее в стеке ниже его и поместить в стек вместо двух этих чисел результат их произведения, таким образом следующие две строки эквивалентны:
3 72 mul
3 inch
Как известно, использование процедур сокращает длину программы, улучшает ее читабельность, а главное дает возможность расширить средства языка за счет введения в него новых слов. Таким образом обычный процедурный язык программирования (3GL) можно поднять до сверхвысокого уровня.
При определении процедуры ничего не было сказано о передаче параметров. Для языка ориентированного на работу со стеком естественный способ передачи параметров -- размещение их в стеке. Перепишем программу рисования двух перекрывающихся областей:
/inch {72 mul} def
/box % в стеке: x y
{ newpath moveto
1 inch 0 rlineto
0 1 inch rlineto
-1 inch 0 rlineto
closepath } def
/fillgray % в стеке: уровень серого цвета
{setgray fill} def
% Основная программа
2 inch 3 inch box
.9 fillgray
2.5 inch 3.5 inch box
.7 fillgray
showpage
В такой записи программу уже значительно проще изменять и она более самодокументирована, чем ее первый вариант. За это приходиться платить некоторым увеличением времени выполнения, так как интерпретатору приходится больше работать со словарями, однако быстродействие встроенных микропроцессоров, управляющих внешними устройствами (так в лазерных принтерах обычно используется RISC-процессор Intel 960) настолько велико, что эти микросекунды обычно никого не волнуют.