【发布时间】:2012-10-11 07:58:30
【问题描述】:
我正在尝试弄清楚如何实现 Lisp 评估 非递归。我的基于 C 的评估器是 Minimal Lisp 文件 l1.c。然而 那里的几个函数再次递归到 eval 中:eval、apply、 evargs、evlist 以及 Lisp Ops defineFunc、whileFunc、setqFunc、ifFunc...
我正在尝试找出一个平坦的评估。 我可以想出一些可能的方法:
- 转换为字节码并在VM中执行
- 实现一个扁平的 Forth 求值器并在 Forth 中实现 Lisp 求值,这就是 lf.f 所做的。
- 另一种可能是将 l1.c 中的所有递归函数加入到一个大的 switch 循环中。局部变量将连接到基于堆的结构中,对递归子函数的调用将由基于堆的返回堆栈实现。
我的问题是:是否有算法/论文/实现 以不同方式进行平面评估。我正在寻找 一个不转换为字节码的实现 类似于使用 a 的无递归“深度优先遍历” 下推堆栈。我想对原来的 s 表达式进行操作。
答案:在 c 中实现评估器时,您需要实现整个 在一个平面循环中,手动实现返回堆栈和堆栈帧,使用 goto 和 switch() 对控制流进行建模。这是一个示例:flat。
【问题讨论】:
-
一般来说,你已经回答了你的问题:有一个下推堆栈(在堆上)并运行一个while循环,以正确的顺序将要评估的东西推到该堆栈上,连同他们的相关信息,可能定义您自己的操作码来指导您如何处理弹出的实体。您是否阅读过 SICP 或“Lisp in Small Pieces”或“EOPL”或“Lisp 1.5 手册”或 McCarthy 的原始论文或“Lambda 论文”或“FUNARG 问题”论文?你决定 Lisp-1 还是 Lisp-2 了吗?环境堆栈树与浅绑定?动态作用域还是词法作用域?
-
感谢您的评论。我不知道这种问题有一个名字:“FUNARG 问题”。感谢您的许多参考,现在我有一些指导方针。理性是好的:基于 c 的评估器中的堆栈是由 c 编译器创建的。要摆脱堆栈,您需要将 c 编译器重写为基于堆的(这不是我能做的)或手动编写控制流。也许没有人想到过,一个不使用堆栈的 c 编译器。完成后,我将发布我的基于堆的 c-evaluator 实现。评估器基于 Ian Piumarta 的 lysp.c。 Lisp-1,树,词法。
-
太棒了!顺便说一句,Scheme 是 Lisp-1,环境树,词法。 :)
-
这是用 c 编写的 Lisp 求值器,重写为平面循环:flat evaluator。 (整个事情是一个实验,我不打算写像Scheme这样完整的东西,它在MinimalLisp中有解释)。 “如果你不理解 Unix,你注定要重新实现它” 可以重写为:“如果你自己不(重新)实现 Unix,你就注定不理解它” ...也许这就是我写这篇文章的主要原因。
-
顺便说一句,如果没有其他答案令人满意,您可以发布自己的答案并接受它。 :)
标签: c lisp eval s-expression