當計算函數調用的參數列表時,代碼生成器可以通過將列表與存儲在符號表中的函數簽名進行比較來判斷缺少哪些參數。一旦你辨別出哪個參數需要被替換,它只是將缺省值拋入參數寄存器(或棧幀)。如果您正在處理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