Lisp 编程语言用来评估AST的算法是什么?
编程语言用来评估其AST的算法是什么 也就是说,假设我们有4个基本函数,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的基本算法是什么,例如:
(+ (- (* 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)
(*24)
这是一个包含3个元素的列表:*、2和4。如上所述,*是乘法函数。2和4是文本,所以它们自己计算。我们用参数2和4调用乘法函数,它返回8
复杂的第二个参数也经历了同样的过程,只是有几个层次的递归。它最终返回4。然后我们用参数4和8调用乘法函数,它返回32
第二个示例的处理方式类似。在顶部,有两个元素的列表:
(lambda(a)(+a2))
3