5.5. Компиляция
523
Preserving была бы при этом сложной и неэффективной, поскольку она анализировала
бы каждый из своих аргументов-последовательностей, при том, что сами эти последова-
тельности могли быть созданы вызовами preserving, и в этом случае и х части были
бы уже проанализир ованы. Чтобы избежать такого многократного анализа, мы с каж-
дой последовательностью команд будем связывать некоторую информацию о том, как
она использует регистры. При порождении элементарной последовательности мы будем
указывать эту информацию явно, а процедуры, сочетающие последовательности, будут
выводить информацию об использовании регистров для составной последовательности
из информации, связанной с ее последовательностями-компонентами.
Последовательность команд буде т содержать три вида информации:
• множество регистров, которые должны быть инициализированы, прежде чем вы-
полняются команды из последовательности (говорится, что последовательность нуж-
дается (ne eds) в этих регистрах),
• множество регистров, значения которых последовательность изменяет, и
• сами команды (называемые также предложениями (statements)) в последователь-
ности.
Мы будем представлять последовательность команд в виде списка из трех частей.
Так им образом, конструктор для последовательностей команд таков:
(define (make-instruction-sequence needs modifies statements)
(list needs modifies statements))
Напри мер, последовательно сть из двух команд, которая ищет значение переменной
x в текущем окружении, присваивает его val, а затем возвращается , требует, чтобы
были проинициализированы регистры env и continue, и изменяет регистр val. Сле-
довательно, эту последовател ьность можно построить так:
(make-instruction-sequence ’(env continue) ’(val)
’((assign val
(op lookup-variable-value) (const x) (reg env))
(goto (reg continue))))
Иногда нам нужно будет строить последовательность без команд:
(define (empty-instruction-sequence)
(make-instruction-sequence ’() ’() ’()))
Процедуры для сочетания последовательностей команд приведены в разделе 5.5.4.
Упражнение 5.31.
Во время вычисления вызова процедуры вычислитель с я вным управлением всегда сохраняет и
восстанавливает регистр env при вычислении оператора, сохраняет и восстанавливает env при
вычислении каждого операнда (кроме последнего), сохраняет и восстанавливает argl при вычис-
лении каждого операнда, а также сохраняет и восстанавливает proc при вычислении последова-
тельности операндов. Для каждой из следующих комбинаций скажите, какие из этих операций
save и restore излишни и могут быть исключены с помощью механизма preserving: