|
||||
Меню:
Главная
Форум
Литература: Программирование и ремонт Импульсные блоки питания Неисправности и замена Радиоэлектронная аппаратура Микросхема в ТА Рубрикатор ТА Кабельные линии Обмотки и изоляция Радиоаппаратура Гибкие диски часть 2 часть 3 часть 4 часть 5 Ремонт компьютера часть 2 Аналитика: Монтаж Справочник Электроника Мощные высокочастотные транзисторы 200 микросхем Полупроводники ч.1 Часть 2 Алгоритмические проблемы 500 микросхем 500 микросхем Сортировка и поиск Монады Передача сигнала Электроника Прием сигнала Телевидиние Проектирование Эвм Оптимизация Автомобильная электроника Поляковтрансиверы Форт Тензодатчик Силовые полевые транзисторы Распределение частот Резисторные и термопарные Оберон Открытые системы шифрования Удк |
[128] (vproc (analyze (assignment-value exp)))) (lambda (env succeed fail) (vproc env (lambda (val fail2); *1* (let ((old-value (lookup-variable-value var env))) (set-variable-value! var val env) (succeed ok (lambda (); *2* (set-variable-value! var old-value env) (fail2))))) fail)))) Вызов процедур Исполнительная процедура для вызовов не содержит никаких новшеств, кроме сложных технических деталей работы с продолжениями. Сложность возникает внутри analyze-application и обусловлена необходимостью следить за продолжениями успеха и неудачи при вычислении операндов. Мы вычисляем операнды с помощью процедуры get-args, а не простого map, как в обыкновенном интерпретаторе. (define (analyze-application exp) (let ((fproc (analyze (operator exp))) (aprocs (map analyze (operands exp)))) (lambda (env succeed fail) (fproc env (lambda (proc fail2) (get-args aprocs env (lambda (args fail3) (execute-application proc args succeed fail3)) fail2)) fail)))) Заметьте, как в get-args для движения через cdr по списку исполнительных процедур aproc и сборки через cons получающегося списка аргументов каждая aproc в списке вызывается с продолжением успеха, которое рекурсивно зовет get-args. Каждый из этих рекурсивных вызовов get-args имеет продолжение успеха, значение которого - cons свежеполученного аргумента со списком уже собранных аргументов: (define (get-args aprocs env succeed fail) (if (null? aprocs) (succeed () fail) ((car aprocs) env ;; продолжение успеха для этой aproc (lambda (arg fail2) (get-args (cdr aprocs) env ;; продолжение успеха для ;; рекурсивного вызова get-args (lambda (args fail3) (succeed (cons arg args) fail3)) fail2)) fail))) Собственно вызов процедуры, который выполняет execute-application, осуществляется так же, как и в обыкновенном интерпретаторе, не считая того, что необходимо управлять продолжениями. (define (execute-application proc args succeed fail) (cond ((primitive-procedure? proc) (succeed (apply-primitive-procedure proc args) fail)) ((compound-procedure? proc) ((procedure-body proc) (extend-environment (procedure-parameters proc) args (procedure-environment proc)) succeed fail)) (else (error "Неизвестный тип процедуры - EXECUTE-APPLICATION" proc)))) Выполнение выражений amb Особая форма amb - ключевой элемент недетерминистского языка. Здесь лежит сущность процесса интерпретации и обоснование необходимости отслеживать продолжения. Исполнительная процедура для amb определяет цикл try-next, который перебирает исполнительные процедуры для всех возможных значений выражения amb. Каждая из исполнительных процедур вызывается с продолжением неудачи, которое попробует выполнить следующий вариант. Когда вариантов больше не остается, все выражение amb терпит неудачу. (define (analyze-amb exp) (let ((cprocs (map analyze (amb-choices exp)))) (lambda (env succeed fail) (define (try-next choices) (if (null? choices) (fail) ((car choices) env succeed (lambda () (try-next (cdr choices)))))) (try-next cprocs)))) Управляющий цикл Управляющий цикл amb-интерпретатора сложен из-за наличия механизма, позволяющего пользователю заново попытаться выполнить выражение. Цикл использует процедуру internal-loop, которая в качестве аргумента принимает процедуру try-again. Наш замысел состоит в том, чтобы вызов try-again переходил к следующему нерассмотренному варианту в недетерминистском вычислении. Процедура internal-loop либо зовет try-again, если пользователь набирает try-again в управляющем цикле, либо запускает новое вычисление, вызывая ambeval. Продолжение неудачи в этом вызове ambeval сообщает пользователю, что значений больше нет, и перезапускает управляющий цикл. Продолжение успеха для вызова ambeval устроено тоньше. Мы печатаем вычисленное значение, а потом заново запускаем внутренний цикл с процедурой try-again, которая сможет попробовать следующий вариант. Этот переход к следующему варианту выражается процедурой next-alternative, которая передана вторым аргументом в продолжение успеха. Обычно мы считаем этот второй аргумент продолжением неудачи, которое придется использовать, если текущая ветвь исполнения потерпит неудачу. Однако в данном случае мы завершили успешное вычисление, так что «неудачный» вариант можно позвать для того, чтобы найти дополнительные успешные варианты вычисления. (define input-promptВвод Amb-Eval:") (define output-promptЗначение Amb-Eval:") (define (driver-loop) (define (internal-loop try-again) (prompt-for-input input-prompt) (let ((input (read))) (if (eq? input try-again) (try-again) (begin (newline) (displayНачало новой задачи ") (ambeval input the-global-environment ;; успех ambeval (lambda (val next-alternative) (announce-output output-prompt) (user-print val) (internal-loop next-alternative)) ;; неудача ambeval (lambda () (announce-output Нет больше значений") (user-print input) (driver-loop))))))) (internal-loop (lambda () (newline) (display ";;; Задача не задана") (driver-loop)))) Самый первый вызов internal-loop использует процедуру try-again, которая жалуется, что не было дано никакой задачи, и возобновляет управляющий цикл. Такое поведение требуется, если пользователь набирает try-again, еще не задав выражение для вычисления. |
Среды: 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 | ||