if-statement - 从 AST 为条件表达式生成分支指令
问题描述
我正在尝试为特定于域的语言编写编译器,目标是基于堆栈机器的 VM,而不是 JVM。
我已经为我的语言生成了一个解析器,并且可以很容易地生成一个我可以轻松行走的 AST。我也没有问题将我的语言的许多语句转换为该 VM 的适当指令,但是在遇到复杂条件时处理生成适当分支指令的问题时遇到了障碍,尤其是当它们与(可能是嵌套的)类似“and”或“or”的操作结合使用,这些操作应该在适用的情况下使用短路分支。
我不是要求任何人为我写这个。我知道我还没有开始足够详细地描述我的问题。我要的是指向有用的材料的指针,这些材料可以让我克服我面临的这个障碍。正如我所说,我已经超过了将我的语言中大约 90% 的语句转换为适用指令的地步,但让我难过的是条件的处理和生成适当的流控制指令。到目前为止,我能够找到的关于从 AST 生成代码的大部分信息似乎只处理与简单的命令式语句相对应的代码生成,但条件和流程控制的处理似乎更加稀缺.
除了我描述的“and”和“or”之类的构造的短路/惰性评估机制之外,我不关心处理任何其他优化。
解决方案
每个条件控制流都可以建模为流程图(或流程图),其中条件的两个分支具有不同的目标。鉴于布尔运算符短路,它们是控制流元素而不是简单的表达式,它们需要这样建模。
考虑这一点的一种方法是将布尔运算符重新表述为三元条件运算符的实例。因此,例如,A and B
成为A ? B : false
并A or B
成为A ? true : B
[注 1]。请注意,每个控制流程图都恰好有两个输出点。
要组合布尔表达式,只需替换到图中即可。例如,这里是A AND (B OR C)
您NOT
只需交换两个流出的含义即可实现。
如果布尔表达式的最终使用是某种条件,例如if
语句或条件循环,您可以按原样使用控制流。如果要将布尔表达式保存到变量中或以其他方式用作值,则需要用代码填充两个流出,以创建相关常量,通常是true或false布尔常量,或者(在类 C 语言中)一个 1 或 0。
笔记:
- 写这个等价的另一种方法是
A and B ⇒ A ? B : A
;A or B ⇒ A ? A : B
,但这对于控制流视图来说用处不大,而且还掩盖了意图只对每个表达式求值一次的事实。这种形式(修改为重用 的初始计算A
)通常用于具有多个“假”值的语言(如 Python)。
推荐阅读
- php - Lumen 中的路由绑定
- java - 如何在java中将0和1字符串转换为字节[]?
- javascript - 多个 \t 转义序列看起来与单个 \t 有何不同?
- reactjs - (WIN) 错误:querySrv ENOTFOUND _mongodb._tcp.cluster0.yq9c1.mongodb.net
- mysql - 如何在mysql中为用户授予创建会话权限
- k3s - k3sup 加入成功但节点未加入,tls 问题?
- javascript - 需要帮助存储 blob 并在浏览器中显示它
- c - 函数“退出”的参数太少。代码有什么问题?
- html - 在 ngIf 中获取 mat-panel 的值?
- r - Newey West 关于多元线性回归