注意:在标题中使用“复杂”时,是指该表达式具有许多运算符和操作数。表达式本身并不复杂。
我最近一直在研究一个简单的x86-64汇编程序。我已经完成了编译器的主要前端-词法分析器和解析器-现在可以生成程序的抽象语法树表示形式。由于我的语言将是静态类型的,因此我现在进入下一阶段:类型检查源代码。但是,我遇到了一个问题,而自己却无法合理解决。
考虑以下示例:
我的编译器的解析器已阅读以下代码行:
int a = 1 + 2 - 3 * 4 - 5
并将其转换为以下AST:
=
/ \
a(int) \
-
/ \
- 5
/ \
+ *
/ \ / \
1 2 3 4
现在,它必须键入检查AST。首先检查=
操作员的类型。首先检查操作员的左侧。可以看到该变量a
被声明为整数。因此,它现在必须验证右侧表达式为整数。
我了解如果表达式只是一个值(例如1
或),该怎么办'a'
?但是,对于具有多个值和操作数的表达式(一个复杂的表达式)(例如上述表达式),该如何处理呢?为了正确确定表达式的值,似乎类型检查器实际上必须执行表达式本身并记录结果。但这显然似乎破坏了将编译和执行阶段分开的目的。
我想可以做到的唯一另一种方法是递归检查AST中每个子表达式的叶子,并验证所有叶子的类型都与期望的运算符类型匹配。因此,从=
运算符开始,类型检查器将扫描左侧的所有AST并验证叶子都是整数。然后,它将对子表达式中的每个运算符重复此操作。
我曾尝试在《龙书》的副本中研究该主题,但似乎没有涉及太多细节,只是重申了我已经知道的内容。
当编译器对具有多个运算符和操作数的表达式进行类型检查时,通常使用的方法是什么?我上面提到的任何方法都使用吗?如果没有,那么方法是什么,它们将如何工作?
double a = 7/2
将尝试将右侧解释为double,因此将尝试将分子和分母解释为double并在需要时进行转换;结果a = 3.5
。自下而上的将执行整数除法,并且仅在最后一步(赋值)时进行转换,因此a = 3.0
。
int a = 1 + 2 - 3 * 4 - 5
而是int a = 5 - ((4*3) - (1+2))