Опубликован: 21.08.2007 | Уровень: для всех | Доступ: платный
Лекция 13:

Оптимизация программ

< Лекция 12 || Лекция 13: 1234 || Лекция 14 >

Все селекторы сводятся к композиции car-cdr, выполняемой после соответствующего распознавателя. Так, в приведенных выше формах поля X, C, A1, S1, P можно выделить селектором, определенным как (lambda (fm) (car(cdr fm))) - выделение второго элемента списка, а поля A2, S2, ST, S, расположенные третьими в списках - как (lambda (fm) (car(cdr(cdr fm)))), поле SF - как (lambda (fm) (car(cdr(cdr(cdr fm))))). Такие определения практически не требуют отладки, работают с первого предъявления.

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

При интерпретации такое соответствие представлялось ассоциативным списком, в котором хранятся связи вида Имя-Смысл, преобразуемые по принципу стека, естественно отражающего динамику вызова функций. При компиляции не принято сохранять имена на время исполнения программы: их роль выполняют сопоставленные именам адреса. Поэтому вместо а-списка вида ((а . 1)(в . 2)(с . 3)...) применяется два списка (а в с ...) и (1 2 3 ...), хранящих имена и их значения на согласованных позициях. Обрабатываются эти два списка синхронно: оба удлиняются или сокращаются на одинаковое число элементов.

Можно переписать Eval-Apply с соответствующей коррекцией и определить функцию подстановки, заменяющую имена их значениями из синхронного списка.

Определение Eval-Apply особенно компактно в стиле p-списка. Иерархию определений можно организовать с помощью блоков Flet со списками определений для шаблонов (перем конст плюс равно) и отдельно для (пусто присвоить шаги если пока).

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

Формально операторы могут рассматриваться как функции, преобразующие полное состояние памяти V. Пусть функция E списочному представлению оператора сопоставляет эквивалентную ему Лисп-функцию, вызываемую в контексте (declare (special N)).

Таблица 13.2. Примеры функциональной реализации операторов и выражений
Оператор Функциональный эквивалент
Абстрактный синтаксис оператора
C (lambda (v)c)
(конст C)
X
(lambda (v) (assoc-i X N v))
N - свободная переменная, задающая список имен, известных в программе
(перем X)
(A1 + A2)
(lambda (v) (+(Е А1)(У А2)))
(плюс А1 А2)
(A1 = A2)
(lambda (v)(=(Е А1)(У А2)))
(равно А1 А2)
(пусто)
(lambda (v)v)
 Состояние памяти неизменно
x := a;
Замена происходит по указанному адресу

(lambda (v)(replace N v X (E A)))
(присвоить X A)
S1; S2;
(lambda (v) (E S2 (E S1 v)))
(шаги S1 S2)
if e then ST else SF;
(lambda (v) (funcall 
     (cond (((E P)v)
                (E S1))
            (T(E S2)) ) v)
(если P ST SF)
while e do S;
Циклу соответствует безымянная 
функция, строящая внутренний
контекст:
(lambda (W) ((lambda (v)
         (cond (((E P)v)(w ((E S)v)))
                   (T v)))
 (lambda (v)
        (cond (((E P)v) (w ((E S)v)))
                  (T v)))  ))
(пока P S)

При определении компилятора на уровне абстрактной машины должно быть выделено описание реализационного минимума языка Лисп, послужившего базой для раскрутки Лиспа и основой для функционального программирования. Необходимо лишь ввести некоторые ограничения, гарантирующие при переходе к низкоуровневому программированию сохранение важнейших свойств функциональных программ. Эти ограничения формулируются как чистый результат правильного выражения:

  • все аргументы убраны из стека;
  • результат выражения записан в стек.
(defun compile-(s)(append (comp- s Nil)"(Ap Stop)))

(defun comp- (S N)(cond

   ((atom S)   (list "LD (adr S N)))

   ((eq (car S)"QUOTE) (list "LDC (cadr S)))
   ((eq (car S)"CONS)   (append (comp-(caddr S)N) (comp-(cadr S)N) "CONS))
   ((eq (car S)"CAR)     (append (comp-(cadr S)N) "CAR))
   ((eq (car S)"+)        (append (comp-(cadr S)N) (comp-(caddr S)N) "ADD))

   ((eq (car S)"IF)    (let  ( (then (list (comp-(caddr S)N) "(JOIN)))
                                     (else (list (comp-(cadddr S)N) "(JOIN))))
                                    (append (comp-(cadr S)N) (list "SEL then else))))

   ((eq (car S)"LAMBDA)  (list "LDF (comp-(caddr S) (append (cadr S) N)) "RTN))

   ((eq (car S)"LET)    (let*   ((args (value (cddr S)))
                                      (mem (cons (var (cddr S)) N))
                                      (body (append (comp-(cadr S)mem) "RTN)))
                                    ((append (map #"(lambda(x)(comp- x N)) args)
                                             (list body 'AP)))))

   ((eq (car S)"LABEL) (let* ((args (value (cddr S)))
                                     (mem (cons (var (cddr S)) N))
                                     (body (append (comp-(cadr S)mem) "RTN)))
                                   ((append "(DUM) (map #"(lambda(x)(comp- x mem)) args)
                                                         (list "LDF body "RAP)))))

   (T (append (map #"(lambda(x)(comp- x N)) (cdr S))
               (list body "AP)) )
))
Листинг 13.3. Определение Лисп-компилятора на Лиспе

Современные методы организации компиляторов и систем программирования претерпевают значительные изменения под давлением изменяющихся условия эксплуатации ИС в сетях, на суперкомпьютерах и в мобильных устройствах. Возрастает роль компиляции "на лету" и организации высокопроизводительных вычислений на многопроцессорных комплексах.

< Лекция 12 || Лекция 13: 1234 || Лекция 14 >
Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?

Илья Ардов
Илья Ардов

Добрый день!

Я записан на программу. Куда высылать договор и диплом?

Данила Некрасов
Данила Некрасов
Россия, Пермь, ПНИПУ
Сергей Федоров
Сергей Федоров
Россия