|
||||
Меню:
Главная
Форум
Литература: Программирование и ремонт Импульсные блоки питания Неисправности и замена Радиоэлектронная аппаратура Микросхема в ТА Рубрикатор ТА Кабельные линии Обмотки и изоляция Радиоаппаратура Гибкие диски часть 2 часть 3 часть 4 часть 5 Ремонт компьютера часть 2 Аналитика: Монтаж Справочник Электроника Мощные высокочастотные транзисторы 200 микросхем Полупроводники ч.1 Часть 2 Алгоритмические проблемы 500 микросхем 500 микросхем Сортировка и поиск Монады Передача сигнала Электроника Прием сигнала Телевидиние Проектирование Эвм Оптимизация Автомобильная электроника Поляковтрансиверы Форт Тензодатчик Силовые полевые транзисторы Распределение частот Резисторные и термопарные Оберон Открытые системы шифрования Удк |
[170] next, то истинная ветвь заканчивается переходом, обходящим код для ложной ветви, на метку, которая стоит в конце условного выражения. (define (compile-if exp target linkage) (let ((t-branch (make-label true-branch)) (f-branch (make-label false-branch)) (after-if (make-label after-if))) (let ((consequent-linkage (if (eq? linkage next) after-if linkage))) (let ((p-code (compile (if-predicate exp) val next)) (c-code (compile (if-consequent exp) target consequent-linkage)) (a-code (compile (if-alternative exp) target linkage))) (preserving (env continue) p-code (append-instruction-sequences (make-instruction-sequence (val) () ((test (op false?) (reg val)) (branch (label ,f-branch)))) (parallel-instruction-sequences (append-instruction-sequences t-branch c-code) (append-instruction-sequences f-branch a-code)) after-if)))))) При вычислении предиката сохраняется env, поскольку он может потребоваться в истинной и ложной ветке, и continue, поскольку он может потребоваться связующему коду в этих ветвях. Код для истинной и ложной ветви (которые не выполняются последовательно) склеивается с помощью особого комбинатора parallel-instruction-sequences, описанного в разделе 5.5.4. Заметим, что поскольку cond является производным выражением, для его обработки компилятор должен только запустить преобразование cond->if, а затем скомпилировать получившееся выражение if. Компиляция последовательностей Компиляция последовательностей (тел процедур и явных выражений begin) происходит так же, как их выполнение. Компилируется каждое из выражений последовательности - последнее с типом связи, который указан для всей последовательности, а остальные с типом связи next (для того, чтобы потом выполнялись остальные выражения последовательности). Последовательности команд для отдельных выражений склеиваются и образуют единую последовательность, при этом сохраняются env (необходимый для остатка последовательности) и continue (возможно, требуемый для связи в конце последовательности). (define (compile-sequence seq target linkage) (if (last-exp? seq) (compile (first-exp seq) target linkage) (preserving (env continue) (compile (first-exp seq) target next) (compile-sequence (rest-exps seq) target linkage)))) Компиляция выражений lambda Выражения lambda строят процедуры. Объектный код для выражения lambda должен иметь вид (построить процедурный объект и присвоить его целевому регистру) ( связь ) Компилируя выражения lambda, мы одновременно генерируем код для тела процедуры. Несмотря на то, что во время построения процедурного объекта тело исполняться не будет, удобно вставить его в код сразу после кода для lambda. Если связь для выражения lambda - метка или return, никаких сложностей при этом не возникает. Если же у нас тип связи next, то нужно обойти код для тела процедуры, использовав связь, которая переходит на метку, вставляемую сразу вслед за телом. Таким образом, объектный код принимает вид (построить процедурный объект и присвоить его целевому регистру) (код для указанной связи) либо (goto (label after-lambda)) (скомпилированное тело процедуры) after-lambda Процедура compile-lambda порождает код, строящий процедурный объект, вслед за которым идет код тела процедуры. Процедурный объект порождается во время выполнения путем сочетания текущего окружения (окружения, в котором исполняется определение) и точки входа для скомпилированного тела процедуры (свежесгенерированной метки).38 (define (compile-lambda exp target linkage) (let ((proc-entry (make-label entry)) (after-lambda (make-label after-lambda))) (let ((lambda-linkage (if (eq? linkage next) after-lambda linkage))) (append-instruction-sequences (tack-on-instruction-sequence (end-with-linkage lambda-linkage (make-instruction-sequence (env) (list target) ((assign ,target (op make-compiled-procedure) (label ,proc-entry) (reg env))))) (compile-lambda-body exp proc-entry)) after-lambda)))) 38 Нам потребуются машинные операции, которые реализуют структуру данных, представляющую скомпилированные процедуры, аналогичную структуре для составных процедур, описанной в разделе 4.1.3: (define (make-compiled-procedure entry env) (list compiled-procedure entry env)) (define (compiled-procedure? proc) (tagged-list? proc compiled-procedure)) (define (compiled-procedure-entry c-proc) (cadr c-proc)) (define (compiled-procedure-env c-proc) (caddr c-proc)) В compile-lambda для того, чтобы добавить тело процедуры к коду lambda-выражения, используется специальный комбинатор tack-on-instruction-sequence (раздел 5.5.4), а не обыкновенный append-instruction-sequences, поскольку тело процедуры не является частью последовательности команд, выполняемой при входе в общую последовательность; оно стоит в последовательности только потому, что его удобно было сюда поместить. Процедура compile-lambda-body строит код для тела процедуры. Этот код начинается с метки для точки входа. Затем идут команды, которые заставят машину во время выполнения войти в правильное окружение для вычисления тела - то есть окружение, где определена процедура, расширенное связываниями формальных параметров с аргументами, с которыми она вызвана. Затем следует код для последовательности выражений, составляющих тело процедуры. Последовательность эта компилируется с типом связи return и целевым регистром val, так что она закончится возвратом из процедуры с результатом в регистре val. (define (compile-lambda-body exp proc-entry) (let ((formals (lambda-parameters exp))) (append-instruction-sequences (make-instruction-sequence (env proc argl) (env) (,proc-entry (assign env (op compiled-procedure-env) (reg proc)) (assign env (op extend-environment) (const ,formals) (reg argl) (reg env)))) (compile-sequence (lambda-body exp) val return)))) 5.5.3 Компиляция комбинаций Соль процесса компиляции заключается в компилировании вызовов процедур. Код для комбинации, скомпилированный с данными целевым регистром и типом связи, имеет вид (скомпилированный код оператора с целевым регистром proc и типом связи next) (вычисление операндов и построение списка аргументов в argl) (скомпилированный код вызова процедуры с указанными целевым регистром и типом связи) Во время вычисления оператора и операндов может потребоваться сохранить и восстановить регистры env, proc и argl. Заметим, что это единственное место в компиляторе, где указывается целевой регистр, отличный от val. Требуемый код порождается процедурой compile-application. Она рекурсивно компилирует оператор, порождая код, который помещает подлежащую вызову процедуру в proc, и операнды, порождая код, который по одному вычисляет операнды процедурного вызова. Последовательности команд для операндов собираются (в процедуре construct-arglist) вместе с кодом, который строит список аргументов в регистре argl, а полученный код для порождения списка аргументов склеивается с кодом вычисления процедуры и кодом, |
Среды: Smalltalk80 MicroCap Local bus Bios Pci 12С ML Микроконтроллеры: Atmel Intel Holtek AVR MSP430 Microchip Книги: Емкостный датчик 500 схем для радиолюбителей часть 2 (4) Структура компьютерных программ Автоматическая коммутация Кондиционирование и вентиляция Ошибки при монтаже Схемы звуковоспроизведения Дроссели для питания Блоки питания Детекторы перемещения Теория электропривода Адаптивное управление Измерение параметров Печатная плата pcad pcb Физика цвета Управлении софтверными проектами Математический аппарат Битовые строки Микроконтроллер nios Команды управления выполнением программы Перехода от ahdl к vhdl Холодный спай Усилители hi-fi Электронные часы Сердечники из распылённого железа Анализ алгоритмов 8-разрядные КМОП Классификация МПК История Устройства автоматики Системы и сети Частотность Справочник микросхем Вторичного электропитания Типы видеомониторов Радиобиблиотека Электронные системы Бесконтекстный язык Управление техническими системами Монтаж печатных плат Работа с коммуникациями Создание библиотечного компонента Нейрокомпьютерная техника Parser Пи-регулятор ч.1 ПИ-регулятор ч.2 Обработка списков Интегральные схемы Шина ISAВ Шина PCI Прикладная криптография Нетематическое: Взрывной автогидролиз Нечеткая логика Бытовые установки (укр) Автоматизация проектирования Сбор и защита Дискретная математика Kb радиостанция Энергетика Ретро: Прием в автомобиле Управление шаговым двигателем Магнитная запись Ремонт микроволновки Дискретные системы часть 2 | ||