Lua 跟踪递归求值器

Lua 跟踪递归求值器,lua,lisp,interpreter,trace,evaluation,Lua,Lisp,Interpreter,Trace,Evaluation,我用moonscriptlua编写了一个简单的Lisp解释器。评估器如下所示: eval = ( env, expr ) -> if is_symbol expr lookup env, expr elseif is_define expr eval_define env, expr elseif is_lambda expr eval_lambda env, expr else call (map (pa

我用moonscriptlua编写了一个简单的Lisp解释器。评估器如下所示:

eval = ( env, expr ) ->
    if is_symbol expr
        lookup env, expr
    elseif is_define expr 
        eval_define env, expr
    elseif is_lambda expr 
        eval_lambda env, expr
    else call (map (partial eval, env), expr)
(+ (+ a b) (+ a c))

(+ (+ 1 2) (+ 1 4))

(+ 3 5)

8
它很好用。 但现在我真的想用一种类似这样的方式来追溯这个过程:

eval = ( env, expr ) ->
    if is_symbol expr
        lookup env, expr
    elseif is_define expr 
        eval_define env, expr
    elseif is_lambda expr 
        eval_lambda env, expr
    else call (map (partial eval, env), expr)
(+ (+ a b) (+ a c))

(+ (+ 1 2) (+ 1 4))

(+ 3 5)

8
问题是,由于求值过程是递归的,所以在任何时候我都不会打印出整个表达式


我必须以命令式的方式重写计算器,还是我遗漏了一些明显的东西?

这个答案使用的是Common Lisp,因为我并不真正了解Lua

实际痕迹 通常,您希望跟踪代码中实际发生的情况。 以下是对函数的重写,以及跟踪工具可以执行的操作示例:

(除正常评估(表格env)
(乙酰基酶形式)
(cons(解构绑定(op.args)表单
(应用op
(地图车(lambda(u)
(正常评估环境)
args)))
(零)
(符号(cdr(助理表格环境)))
(t表格)
>(跟踪正常评估)
>(正常评估’(+(+13A)2’((a.5)))
0:(正常评估(+(+13A)2)((A.5)))
1:(正常评估(+13A)((A.5)))
2:(正常评估1((A.5)))
2:正常-评估返回1
2:(正常评估3((A.5)))
2:正常-评估返回3
2:(正常评估A((A.5)))
2:NORMAL-EVAL返回5
1:NORMAL-EVAL返回9
1:(正常评估2((A.5)))
1:正常-评估返回2
0:NORMAL-EVAL返回11
期望轨迹 据我所知,要用您提供的代码获得您想要的输出是不容易的。 但是,如果您愿意更改代码,只需一步一步地重写术语,就可以以纯粹的函数方式获得所需的跟踪。但是,您必须防止对已评估的术语进行评估,以便使表单逐渐更改

(反爆炸s-eval(x环境)
(乙酰胆碱酯酶x)
(缺点(解构绑定(新列表,一些evalp)
(减少
(λ(元素R)
(解构绑定(rec list.some evalp)R
(多值绑定(值evalp)(s-eval元素环境)
(缺点(列表*值记录列表)
(或一些evalp evalp(())))
(其余十项)
:从t端开始
:初始值(cons nil nil))
(价值观
(如果需要一些评估
至少有一个元素需要一些工作
所以我们返回修改后的术语。
(反对党(前十名)新名单)
所有元素都是文字,我们实际上可以
;;将此表格替换为其评估
(应用(第一个x)新列表)
T) ))
(空(值为零)
(符号(值(cdr(assoc x env))t))
(t(值x零)))
(拆卸步骤评估(表格和可选环境)
(打印表格)
(多值绑定(值evalp)
(s-评估表环境)
(如果是evalp
(步骤评估值环境)
(价值)
>(步骤评估“(+(+13a)2)”((a.5)))
(+(+13A)2)
(+ (+ 1 3 5) 2) 
(+ 9 2) 
11
>(步骤评估“(+(+13A)(*BA))”((a.5)(b.0)))
(+(+13A)(*B A))
(+ (+ 1 3 5) (* 0 5)) 
(+ 9 0) 
9
>(步骤评估“(+(+AB)(+AC))”((a.1)
(b.2)
(c.4)))
(+(+AB)(+AC))
(+ (+ 1 2) (+ 1 4)) 
(+ 3 5) 
8.
S-EVAL
在环境中对表单求值并返回两个值:对表单的求值和一个布尔值,指示是否实际发生了某种求值,或者术语是否为自求值(文字)。此布尔值用于防止转换通过递归计算转换子项的项。
STEP-EVAL
打印表单并调用
S-EVAL
,然后递归调用自身,直到求值终止。

如果希望跟踪看起来与实际发生的情况不同,则可能需要编写一个求值器来执行不同的操作,是的。就我个人而言,我希望跟踪显示评估者的实际操作。非常好!事后看来,我可以看出我所问的是多么没有意义。我将使用您的s-eval,看看是否可以用Lua重写它。我知道s-eval根据表单是否为自评估返回第二个值nil或T,以便停止进程。测试表单在每一步求值前后是否相等,或者是否会碰到一些我没有看到的边缘情况?呵呵,我也没有看到任何边缘情况,我认为它也可以这样工作。