当计算函数调用的参数列表时,代码生成器可以通过将列表与存储在符号表中的函数签名进行比较来判断缺少哪些参数。一旦你辨别出哪个参数需要被替换,它只是将缺省值抛入参数寄存器(或栈帧)。如果您正在处理OO语言并且形式参数是对象,则可以将0(NULL)推入堆栈的下一个字中。如果该参数是内置原语,那么您将推动该语言指定的任何默认值。
当然,编译器可能会有所不同,但简单来说,在符号表中关联一个默认值并不是绝对必要的。首先,让我们清楚一个符号表记录所有变量声明。您必须存储有关这些声明的信息(例如,类,方法,类型,行,字符等),但当只有几种类型时,不必为每个变量记录默认值,因此只有少数可能的默认值。
某些语言(Java/C++)指定具有未初始化对象属性的类具有默认值NULL。在实现类似的东西时,当代码生成器创建类构造函数时,它肯定会生成将映射到该属性的对象内存中放置0的代码(假设所有内容都是基于指针的)。当你去生成构造函数,并且遍历类属性列表(一个AST节点)时,如果该属性没有初始化表达式,则调用一个方法来执行默认操作。
private void genConstructor(int classId) {
//allocate new object
codeGen.write("li $a0, "+classId);
codeGen.write("jal Runtime.newObject");
//call parent constructor
codeGen.write("move $a0, $v0");
codeGen.write("jal ParentInit");
//initialize the attributes this class has declared
for(Attributes a: getAttributes(classId)) {
//provide default value
if(a.getInitExpr() == null)
doDefault(a.getType(), a.getNum());
else
doInit(a.getInitExpr(), a.getNum());
}
}
// An 'Int' default value is 1, everything else is 0 (Objects included)
// $t0 has the object address
// attributes start at the 5th word of each object
private void doDefault(String type, int attrNum) {
switch(type) {
case "Int": {
codeGen.write("sw $one, "+(5+attrNum)+"($t0)");
}
default: {
codeGen.write("sw $zero, "+(5+attrNum)+"($t0)");
}
}
}
更新:
我想知道编译器如何处理由程序员 而不是“默认”为“类”或“类型”设置为默认值。
我假设你讲的东西类似于C++构造函数中的默认参数。在那种情况下,正如Ira所说的,在符号表记录中创建一个字段听起来就像是最简单的方法。在为缺少的参数生成代码时,查找表中的默认值。
再次感谢您。我记得你回答我的另一个问题。我想知道编译器如何处理由程序员设置的默认值,而不是“类”或“类型”的“默认”。谢谢。 – 2012-04-16 20:47:02
@SimonGuo:更新。 – blackcompe 2012-04-16 21:09:22