2

某些編程語言允許參數在函數調用中具有默認值,或者struct中的屬性具有默認值。像python或javascript一樣,當我們在函數調用中省略一些參數時,默認值將在函數中被替換(與struct同樣可以具有默認屬性)。那麼編譯器如何處理呢?特別是在符號表中?我認爲增加一個額外的屬性指針指向默認值也猜測默認值在堆棧上運行時推送?請讓我知道我是否正確。謝謝。編譯器如何處理符號表中的默認值

更新: 這裏默認值我的意思是說,在Python中,下面的程序參數b有默認值0

def foo(a, b=0): 
    return a+b 
print foo(1) 
print foo(1, 1) 

我們將得到結果01。那麼編譯器在運行時或編譯時如何處理呢?

回答

1

當計算函數調用的參數列表時,代碼生成器可以通過將列表與存儲在符號表中的函數簽名進行比較來判斷缺少哪些參數。一旦你辨別出哪個參數需要被替換,它只是將缺省值拋入參數寄存器(或棧幀)。如果您正在處理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所說的,在符號表記錄中創建一個字段聽起來就像是最簡單的方法。在爲缺少的參數生成代碼時,查找表中的默認值。

+0

再次感謝您。我記得你回答我的另一個問題。我想知道編譯器如何處理由程序員設置的默認值,而不是「類」或「類型」的「默認」。謝謝。 – 2012-04-16 20:47:02

+0

@SimonGuo:更新。 – blackcompe 2012-04-16 21:09:22

3

無論您如何操作,您都必須將默認值與特定標識符相關聯。

參數列表和結構成員形成小的名稱空間,編譯器通常通過爲這些名稱空間構建符號表來跟蹤它們,以及一個跟蹤命名空間如何相關的更大符號表。

由於編譯器通常在這些將其他信息與符號(例如任何類型信息)相關聯的小命名空間中包含符號表條目,因此這是記錄它的一個很自然的地方。

有什麼問題需要記錄初始值。一個簡單的事情就是簡單地記錄一個指向代表初始/默認值的AST的指針。除此之外,還必須記錄評估該表達的環境(例如「環境」)。這個上下文通常可以保持隱含,因爲它通常與定義結構/參數的上下文相同,並且該信息存儲在將所有內容粘合在一起的較大符號表中。