Macros Franz LISP到Common LISP转换2-生成宏的宏

Macros Franz LISP到Common LISP转换2-生成宏的宏,macros,lisp,common-lisp,franz-lisp,Macros,Lisp,Common Lisp,Franz Lisp,我正在恢复上世纪80年代早期的一个旧LISP程序。(这是Nelson Oppen simplifier,一个早期验证系统。该版本是福特Pascal-F验证器的一部分,1982年在Franz LISP中运行。)以下是整个程序: 我正在将代码转换为在Linux上的clisp下运行,需要一些建议。大多数问题都与宏有关。这是今天的问题 DEFSMAC和DEFMAC 更古老的斯坦福人工智能实验室宏,在defmacro成为语言的一部分之前使宏定义更容易。宏及其文档如下所示: 这些是生成更多宏的宏 ;;;

我正在恢复上世纪80年代早期的一个旧LISP程序。(这是Nelson Oppen simplifier,一个早期验证系统。该版本是福特Pascal-F验证器的一部分,1982年在Franz LISP中运行。)以下是整个程序:

我正在将代码转换为在Linux上的clisp下运行,需要一些建议。大多数问题都与宏有关。这是今天的问题

DEFSMAC和DEFMAC

更古老的斯坦福人工智能实验室宏,在defmacro成为语言的一部分之前使宏定义更容易。宏及其文档如下所示:

这些是生成更多宏的宏

;;; defmac (define macro) and defsmac (define simple macro) are like defun,
;;; but they define the function as a macro instead of as an expr.  They are
;;; less powerful then defining a macro directly (for example, they cannot be
;;; used to define macros with arbitrarily many arguments) but are easier to
;;; use.   For example,
;;; 
;;; (defsmac f (x y) (foo (bar x) (bar y)))
;;; 
;;; causes f to be defined as a macro in such a way that every call (f e1 e2)
;;; will expand to (foo (bar e1) (bar e2)) before it is evaluated.

(defun defsmac macro (args)
       (defsmac1 (cadr args) (caddr args) (cdddr args)))


(defun defsmac1 (name formals body)
       `(defun ,name macro (app) 
                     ,(defsmac2 formals
                                  (cond ((cdr body) (cons 'progn body)) 
                                        (t (car body))))))

(defun defsmac2 (formals body)
       `(sublis  ,(defsmac3 formals 1) (quote ,body)))

(defun defsmac3 (formals n)
       (cond ((null formals) nil)
             (`(cons (cons (quote ,(car formals)) (car ,(defsmac4 n)))
                           ,(defsmac3 (cdr formals) (1+ n))))))

(defun defsmac4 (n) (cond ((= n 0) 'app) ((list 'cdr (defsmac4 (1- n))))))
直接转换为“defmacro”不起作用。我不清楚“用宏定义”是如何工作的。记录在第46页,共页

但这并没有太大帮助。不清楚参数列表是如何处理的。从字面上看,旧文档似乎说传入的是参数的“数量”,而不是参数本身。这不可能是正确的解释

上面的代码似乎假设在宏处理期间可以使用常规的defun定义函数。但Common LISP不允许这样做,是吗


我正在寻找一种将旧式Franz LISP/MacLISP宏转换为现代通用LISP的通用方法。建议?

在编译器环境中定义函数时使用
eval,以便在宏扩展期间使用

(eval-when (:compile-toplevel :load-toplevel :execute)
    (defun defsmac1 (name formals body)
           `(defmacro ,name (app) 
                         ,(defsmac2 formals
                                      (cond ((cdr body) (cons 'progn body)) 
                                            (t (car body))))))

    (defun defsmac2 (formals body)
           `(sublis  ,(defsmac3 formals 1) (quote ,body)))

    (defun defsmac3 (formals n)
           (cond ((null formals) nil)
                 (`(cons (cons (quote ,(car formals)) (car ,(defsmac4 n)))
                               ,(defsmac3 (cdr formals) (1+ n))))))

    (defun defsmac4 (n) (cond ((= n 0) 'app) ((list 'cdr (defsmac4 (1- n))))))
)

我从黑客新闻的“pwd”那里得到了一个有用的答案:

(defmacro defsmac (name params &rest expr)
      `(defmacro ,name ,params
         `,(cons 'progn (sublis (mapcar 'cons ',params 
              (list ,@params))  ', expr))))

这似乎很有效。

您可以使用
(eval when(:compile top level)
在编译时环境中执行代码。这些函数可以在宏处理中使用。不过,我不确定你还能找到它。这很有帮助。我还在研究Franz LISP的“defun…macro”和Common LISP的“defmacro”之间的所有区别。这很有帮助,但不起作用。我还在研究Franz LISP的“defun…macro”和Common LISP的“defmacro”之间的所有区别。到目前为止,1)在Franz LISP宏中,一个参数是所有参数的列表,并且在开头有一个额外的元素。2) 引用则不同。看看上面的“defsmac”。原件中没有反引号或逗号。3) 我仍在试图找出宏参数的作用域。查看“defsmac1”中内部宏定义中的“app”。在“defsmac4”中,它仅作为引用符号引用。这是如何工作的?我只是演示如何将定义放入编译时环境中,我没有尝试进行完整的Franz->CL转换。您可以使用
&rest-app
在CL中获得整个参数列表。在
defsmac
中没有反引号,因为反引号是在它调用的帮助函数中完成的。完成所有helper函数后,它们返回一个包含
app
的主体,该主体引用生成宏的参数。使用
macroexpand
查看结果。