Учитывая следующую функцию LISP eval - что требуется для добавления defmacro?

Учитывая следующее определение функции eval LISP - что требуется для добавления функции defmacro? (Или просто оценить макрос)

(defun null. (x)
      (eq x '()))

(defun and. (x y)
  (cond (x (cond (y 't) ('t '())))
        ('t '())))

(defun not. (x)
  (cond (x '())
        ('t 't)))

(defun append. (x y)
  (cond ((null. x) y)
        ('t (cons (car x) (append. (cdr x) y)))))

(defun list. (x y)
  (cons x (cons y '())))

(defun pair. (x y)
  (cond ((and. (null. x) (null. y)) '())
        ((and. (not. (atom x)) (not. (atom y)))
         (cons (list. (car x) (car y))
               (pair. (cdr x) (cdr y))))))

(defun assoc. (x y)
  (cond ((eq (caar y) x) (cadar y))
        ('t (assoc. x (cdr y)))))

(defun eval. (e a)
  (cond
    ((atom e) (assoc. e a))
    ((atom (car e))
     (cond
       ((eq (car e) 'quote) (cadr e))
       ((eq (car e) 'atom)  (atom   (eval. (cadr e) a)))
       ((eq (car e) 'eq)    (eq     (eval. (cadr e) a)
                                    (eval. (caddr e) a)))
       ((eq (car e) 'car)   (car    (eval. (cadr e) a)))
       ((eq (car e) 'cdr)   (cdr    (eval. (cadr e) a)))
       ((eq (car e) 'cons)  (cons   (eval. (cadr e) a)
                                    (eval. (caddr e) a)))
       ((eq (car e) 'cond)  (evcon. (cdr e) a))
       ('t (eval. (cons (assoc. (car e) a)
                        (cdr e))
                  a))))
    ((eq (caar e) 'label)
     (eval. (cons (caddar e) (cdr e))
            (cons (list. (cadar e) (car e)) a)))
    ((eq (caar e) 'lambda)
     (eval. (caddar e)
            (append. (pair. (cadar e) (evlis. (cdr e) a))
                     a)))))

(defun evcon. (c a)
  (cond ((eval. (caar c) a)
         (eval. (cadar c) a))
        ('t (evcon. (cdr c) a))))

(defun evlis. (m a)
  (cond ((null. m) '())
        ('t (cons (eval.  (car m) a)
                  (evlis. (cdr m) a)))))


(eval '(car '(a a)) )

Ответ 1

Представление анонимного макроса является условным списком формы (macro lambda ...). Попробуйте убрать их в своем любимом интерпретаторе Lisp (тестируется в Emacs):

(defmacro triple (x) `(+, x, x, x))

тройной

(символ-функция 'тройка)

(макрос lambda (x) (\ `(+ (\, x) (\, x) (\, x))))

Несмотря на то, что в Emacs это не так, единственное, что осталось сделать - это дать адекватную семантику такой форме. То есть, когда eval. видит ((macro lambda (x) EXPR) FORM), он должен

  • Замените каждое событие x в FORM на EXPR без, сначала оценивая EXPR (в отличие от того, что происходит при вызове функции);
  • eval. результат выше.

Вы можете добиться этого, добавив предложение к внешнему cond в eval., которое относится к случаю ((macro lambda ...) ...). Вот грубый прототип:

((eq (caar e) 'macro)
     (cond
      ((eq (cadar e) 'lambda)
       (eval. (eval. (car (cdddar e))
                     (cons (list. (car (caddar e)) (cadr e)) a))
              a))))

Этот код работает только для макросов с одним аргументом. Фиксация, которая включает в себя запись вспомогательной функции substlis., которая работает как evlis., но без цикла до eval.; который остается в качестве упражнения для читателя: -)

Чтобы проверить, определите cadr. как макрос:

(defmacro cadr. (x)
  (list. 'car (list. 'cdr x)))

После этого у вас будет

(символ-функция 'cadr.)

(макрос lambda (x) (список. (quote car) (список. (quote cdr) x)))

Вы можете создать форму, которая применяет этот (macro lambda ...) к выражению, и eval эта конструкция в контексте, который содержит определение для list. (потому что он не считается примитивным интерпретатором eval.). Например,

(let ((e '((macro lambda (x) (list (quote car) (list (quote cdr) x)))
           (cons (quote x) (cons (quote y) nil))))
      (bindings `((list ,(symbol-function 'list.)))))
  (eval. e bindings))

у

Тада!