首页 > 解决方案 > 从 AST 为条件表达式生成分支指令

问题描述

我正在尝试为特定于域的语言编写编译器,目标是基于堆栈机器的 VM,而不是 JVM。

我已经为我的语言生成了一个解析器,并且可以很容易地生成一个我可以轻松行走的 AST。我也没有问题将我的语言的许多语句转换为该 VM 的适当指令,但是在遇到复杂条件时处理生成适当分支指令的问题时遇到了障碍,尤其是当它们与(可能是嵌套的)类似“and”或“or”的操作结合使用,这些操作应该在适用的情况下使用短路分支。

我不是要求任何人为我写这个。我知道我还没有开始足够详细地描述我的问题。我要的是指向有用的材料的指针,这些材料可以让我克服我面临的这个障碍。正如我所说,我已经超过了将我的语言中大约 90% 的语句转换为适用指令的地步,但让我难过的是条件的处理和生成适当的流控制指令。到目前为止,我能够找到的关于从 AST 生成代码的大部分信息似乎只处理与简单的命令式语句相对应的代码生成,但条件和流程控制的处理似乎更加稀缺.

除了我描述的“and”和“or”之类的构造的短路/惰性评估机制之外,我不关心处理任何其他优化。

标签: if-statementcompiler-constructioncode-generationabstract-syntax-treelazy-evaluation

解决方案


每个条件控制流都可以建模为流程图(或流程图),其中条件的两个分支具有不同的目标。鉴于布尔运算符短路,它们是控制流元素而不是简单的表达式,它们需要这样建模。

考虑这一点的一种方法是将布尔运算符重新表述为三元条件运算符的实例。因此,例如,A and B成为A ? B : falseA or B成为A ? true : B[注 1]。请注意,每个控制流程图都恰好有两个输出点。 在此处输入图像描述

要组合布尔表达式,只需替换到图中即可。例如,这里是A AND (B OR C)

在此处输入图像描述

NOT只需交换两个流出的含义即可实现。

如果布尔表达式的最终使用是某种条件,例如if语句或条件循环,您可以按原样使用控制流。如果要将布尔表达式保存到变量中或以其他方式用作值,则需要用代码填充两个流出,以创建相关常量,通常是truefalse布尔常量,或者(在类 C 语言中)一个 1 或 0。


笔记:

  1. 写这个等价的另一种方法是A and B ⇒ A ? B : AA or B ⇒ A ? A : B,但这对于控制流视图来说用处不大,而且还掩盖了意图只对每个表达式求值一次的事实。这种形式(修改为重用 的初始计算A)通常用于具有多个“假”值的语言(如 Python)。

推荐阅读