sicp.io
5.5.3 · Компиляция комбинаций

Порядок компиляции комбинации и граница apply

Точный порядок инструкций вложенной комбинации, видимое через состояние вычисление операндов и единое соглашение о применении для всех процедур.

Вопрос для размышления

Какие контракты порядка и представления должен сохранять скомпилированный код применения?

  • Компиляция оператора перед выражениями его операндов
  • Компиляция операндов слева направо с сохранением порядка аргументов
  • Генерация одной инструкции call после того, как готово полное состояние комбинации
  • Наблюдение эффектов порядка исходного кода без опоры на неопределенное расписание
  • Использование общего лексического окружения и соглашения об аргументах между представлениями процедур
  • Сохранение явного различия между диспетчеризацией примитивных, интерпретируемых и скомпилированных процедур

Учебный компилятор генерирует load для оператора вычитания, затем весь код для вызова левой процедуры record, затем весь код для вызова правой процедуры record и в конце одну внешнюю инструкцию call. Процедура с состоянием record добавляет метки в observations, поэтому возвращаемый список (left right) подтверждает, что выполнение следует сгенерированному порядку исходного кода. Результат вычитания также подтверждает порядок аргументов.

Вторая программа расширяет границы вызовов. Код вычислителя вызывает скомпилированное замыкание add-three, а скомпилированный код вызывает интерпретируемую процедуру double. Оба пути передают упорядоченный список аргументов через apply-any, а dispatch-log сохраняет фактические теги primitive, interpreted и compiled. Это фиксирует соглашение о вызовах, используемое в уроке.

Код SICP11,199 из 1,048,576 байт UTF-8
Примеры
Результат
Вывод
Значение
Диагностика
Трасса выполнения0 / 0 событий
    Запуски происходят внутри браузера с отображением результата программы и трассы выполнения.
    Ожидаемый результат

    Программа упорядочения возвращает ((17 (left right)) (load load literal literal call load literal literal call call)). Программа интерфейса возвращает ((evaluator-to-compiled 8 (compiled primitive)) (compiled-to-evaluator 14 (interpreted primitive) #t) (representations #t #t)).

    На что обратить внимание в трассе

    В первом запуске проследите внешний load оператора, каждую инструкцию левого вызова record, каждую инструкцию правого вызова record и только затем вызов вычитания. В запуске интерфейса отделите подготовку аргументов от диспетчеризации представлений в apply-any и убедитесь, что каждое тело получает аргументы в объявленном порядке параметров.

    Попробуйте сами

    Измените программу и сравните результат.

    Скомпилируйте вызов list с тремя операндами, каждый из которых записывает отдельную метку, затем оберните один операнд в вызов скомпилированного замыкания. Спрогнозируйте как теги инструкций, так и хронологический журнал dispatch-log.

    Показать подсказку

    Сначала завершите код оператора. Каждый операнд добавляет свой полный код в порядке исходного кода, а финальный call принимает полученный упорядоченный список аргументов.

    Завершить этот урок

    В этой главе пройдено 0 из 23 урока0%