我试图设计一个非递归的 Scheme 解释器,使用堆栈和指针在 AST 上行走和评估。
如果我只需要处理纯过程调用,一切都很好。然而,一旦出现宏,不规则的语法使得编写非递归例程变得困难。(因为混合了不同的语义)更糟糕的是,当考虑到内置宏(如 if、conf let 等)时,非递归方法似乎变得异常复杂。
关于实现非递归解释器有什么好的建议吗?或者有什么相关资料?我用谷歌搜索,但什么也没找到。
而且,我想知道主流的 Scheme 解释器是否使用这种方法。也许我可以只写递归,它不会受到指责。
我试图设计一个非递归的 Scheme 解释器,使用堆栈和指针在 AST 上行走和评估。
如果我只需要处理纯过程调用,一切都很好。然而,一旦出现宏,不规则的语法使得编写非递归例程变得困难。(因为混合了不同的语义)更糟糕的是,当考虑到内置宏(如 if、conf let 等)时,非递归方法似乎变得异常复杂。
关于实现非递归解释器有什么好的建议吗?或者有什么相关资料?我用谷歌搜索,但什么也没找到。
而且,我想知道主流的 Scheme 解释器是否使用这种方法。也许我可以只写递归,它不会受到指责。
在 vanilla r5rs 方案中,宏只是用于重新排列 AST 的 DSL。它们在纯句法级别上运行,应该与解释器分开。
在 R6RS 或 CL 或其他中,宏实际上可以进行计算,这意味着它们需要运行 2 次解释器,一次用于扩展宏,一次用于评估生成的 AST。
例如给出这个代码
(let ((x 5))
(if (= x 5)
(display "Woohoo")
(error)))
您应该在离开 AST 的第一阶段对其运行宏扩展器
((lambda (x)
(cond
((= x 5) (display "Woohoo"))
(else (error)))) 5)
这样做应该不会评估任何代码。只需重新排列 AST。然后,当您的解释器运行它时,它甚至不必知道宏的存在。
所以你的最终方案解释器应该是这样的
Parse File
|
|
|
Expand All Macros
|
|
|
Optimize/Black Magic
|
|
|
Optional ByteCode compilation or similar IL
|
|
Evaluate
|
|
Profit
Whle researching for my Scheme compiler I have read lots of papers about all sorts of old problems related to compilation. Related to macros and @jozefg's nice illustration of separating actual interpreting and macro espansions that I found was Alexpander, written by Al Petrofsky. He has also written Eval in one define, which is a nice interpreter with syntax-rules.
I have previously written a Lisp1 interpreter that runs on Brainf*ck. It had a stack with alternating cell addresses to set-car! the result and the expression to be evaluated.
Eval is something like this:
(pop_stack register1) ; expression
(while-not-zero register1
... do computation
(pop_stack register2) ; return address
(open-cons register2) ; opens location
(set-car register1) ; sets value
(pop_stack register1)) ; next job
It supports standard McCharty LISP1 stuff, including macros (flambda).
A simple expression like (cons 'a 'b) used 6 rounds in the while loop, like this:
Because of this i could rename every keyword. Eg. this works:
(let ((mylambda lambda))
(mylambda (x) (cons '1 x)))