Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lisp 编程语言用来评估AST的算法是什么?_Lisp_Scheme_Eval_Abstract Syntax Tree - Fatal编程技术网

Lisp 编程语言用来评估AST的算法是什么?

Lisp 编程语言用来评估AST的算法是什么?,lisp,scheme,eval,abstract-syntax-tree,Lisp,Scheme,Eval,Abstract Syntax Tree,编程语言用来评估其AST的算法是什么 也就是说,假设我们有4个基本函数,/*+-。正确评估任何AST的基本算法是什么,例如: (+ (- (* 3 2) (+ (/ 5 2))) (* 2 4)) 我的疑问是,如果节点的求值返回仍然需要求值的内容,那么实际会发生什么。例如,在方案中,((lambda(a)(+a2))3)的评估将是(+32)。但这可以再次评估为5。那么,语言如何确定何时停止对表单求值呢?在您给出的例子中,执行将在5处停止,因为它是一个文本值,并且表示它自己。这并不难测试。您还

编程语言用来评估其AST的算法是什么

也就是说,假设我们有4个基本函数,
/*+-
。正确评估任何AST的基本算法是什么,例如:

(+ (- (* 3 2) (+ (/ 5 2))) (* 2 4)) 

我的疑问是,如果节点的求值返回仍然需要求值的内容,那么实际会发生什么。例如,在方案中,
((lambda(a)(+a2))3)
的评估将是
(+32)
。但这可以再次评估为5。那么,语言如何确定何时停止对表单求值呢?

在您给出的例子中,执行将在5处停止,因为它是一个文本值,并且表示它自己。这并不难测试。您还可以询问深入遍历列表的函数如何知道如何停止(事实上,您应该这样做,因为在Scheme中这是相同的)


在Scheme中,任何复合表达式最终都应该解析为7种基本数据类型之一或空列表,除非它被困在无限循环中。如果您想提前知道表达式是否能解决问题,那么这是一个有趣的问题:

我想您可能问错了问题,但我会尝试:

直到它得到一个可以处理的结果。在您的示例中,您将询问interpeter何时停止计算表达式。。。它100%依赖于语言,如果你问一个编译器,这将是一个完全不同的答案。对于Scheme示例,您需要阅读Scheme规范()


所以它是由解释器的编写者定义的。如果在我的语言中,表达式的预期结果是单个文本(甚至是变量),那么它就到此为止。

有许多不同的算法

备选方案1:您可以将AST编译为更线性的中间表示形式。您的代码可以编译为如下内容:

a <- 3 * 2
b <- 5 / 2
c <- a - b
d <- 2 * 4
e <- c + d
return e
备选方案3:您可以将备选方案#1编译为一种称为SSA的特殊形式,或“单一静态赋值”,类似于#1,但每个赋值的LHS是唯一的,特殊的“phi”节点用于组合来自不同分支的值。然后可以将SSA编译为机器码或字节码

li      r3, 3
muli    r3, 2
li      r4, 5
divi    r4, r5, 2
subf    r3, r3, r4
li      r4, 2
muli    r4, r4, 4
add     r3, r3, r4
blr
备选方案4:您可以通过递归下降法评估AST。这在大多数关于Scheme/Lisp的书籍中都有详细介绍

备选方案5:您可以使用递归下降法将代码转换为堆栈机器代码,然后对其求值。比如:

push 3
push 2
mul
push 5
push 2
div
sub
push 2
push 4
mul
add
ret

备选方案∞:还有很多其他技巧。关于这个主题的书太多了。

你完全误解了Scheme/Lisp评估的工作原理。我将使用您给出的示例:

(+ (- (* 3 2) (+ (/ 5 2))) (* 2 4))
为了计算列表,我们计算每个元素。第一个应该返回一个过程(我忽略语法运算符的特殊情况),其余的可以返回任意值。我们调用该过程,其余部分作为参数

在顶层,这是一个包含3个元素的列表:

  • +
  • ((*32)(+(/52)))
  • (*24)
  • 每一个都进行了评估。第一个是一个变量,其值是一个过程(Scheme的内置加法函数)。其他列表需要递归到求值算法中。由于其复杂性,我将跳过对第二个的描述,转到第三个:
    (*24)

    这是一个包含3个元素的列表:*、2和4。如上所述,*是乘法函数。2和4是文本,所以它们自己计算。我们用参数2和4调用乘法函数,它返回8

    复杂的第二个参数也经历了同样的过程,只是有几个层次的递归。它最终返回4。然后我们用参数4和8调用乘法函数,它返回32

    第二个示例的处理方式类似。在顶部,有两个元素的列表:

  • (lambda(a)(+a2))
  • 3
  • 每一个都进行了评估。Lambda是一种特殊的语法,它解析其内容并返回一个过程,该过程在参数变量绑定到参数的上下文中对其主体进行求值,因此第一个过程返回一个过程,该过程向其参数添加2并返回该值。3是一个文本,所以它只返回数字3。然后我们用参数3调用这个过程,它向其中添加2并返回5