在Common Lisp中实现Lisp eval函数



我正在尝试使用CLISP实现eval函数。

我的动机:假设我有一个像这样的Lisp程序:

(defun call (arg)
(cond
(some-condition (call (other (strange (functions (on arg)))))
(t nil)
)
)
(defun mysterious-function (arg)
(call (strange (functions (on arg))))
)
(mysterious-function 100)       ; only this line can be changed

我想知道(mysterious-function 100)中实际调用的是什么。

目前我的想法如下,但障碍是:

  1. 如何查找符号(当前使用eval(
  2. 如何获取函数的定义(例如,获取类似(defun f (x))的内容(,然后对其进行解析
  3. 如何检测宏并展开它们

我的方向正确吗?

(defun my-eval (body)
(cond
((typep body 'integer) body)
((typep body 'float) body)
((typep body 'rational) body)
((typep body 'complex) body)
((typep body 'boolean) body)
((typep body 'symbol) (eval body))
((typep body 'list) (eval body))
(t (error))
)
)
(my-eval '(mysterious-function 100))

代码中的大多数情况都可以用一个检查来替换:((constantp body) body)

至于其他情况:

  • 您可以使用boundp来检查符号是否具有全局值
  • 要查找全局符号值,可以使用symbol-value
  • fboundp可用于检查符号是否全局绑定到函数
  • 要查找全局函数,可以使用symbol-function访问其函数对象,有时还可以使用function-lambda-expression从函数对象中检索可解析的源代码列表。有时这将不起作用,因为CLISP函数可以在C中定义
  • 要检查符号是否有关联的全局宏,请使用macro-function(如果有,则返回非零(
  • 要展开宏窗体,请使用macroexpand

您可能还需要使用special-operator-p检测特殊运算符,并对其进行相应的处理。

我认为,如果你尽可能地将你解释的代码限制为宏和用户定义的函数,你试图做的事情就会简化。我记得读过一篇关于遗传编程中使用的快速eval函数的文章,该函数跳过了评估代码的宏扩展阶段,它的方法看起来与您所想的类似。

最新更新