関数呼び出しの引数リストが評価されるとき、コードジェネレータは、リストをシンボルテーブルに格納されている関数シグネチャと比較することによって、どの引数が欠けているかを知ることができます。どの引数を置き換える必要があるのか分かったら、引数レジスタ(またはスタックフレーム)にデフォルト値を投げることだけです。 OO言語を扱っていて、仮パラメータがオブジェクトの場合は、スタックの次の単語に0(NULL)をプッシュします。パラメータが組み込みプリミティブである場合、言語が指定するデフォルト値をプッシュします。
もちろん、コンパイラはさまざまですが、単純なものでは、シンボルテーブルにデフォルト値を関連付けることは絶対に必要ではありません。まず、シンボルテーブルがすべての変数宣言を記録することを明確にします。これらの宣言(クラス、メソッド、型、行、charなど)に関する情報を格納する必要がありますが、型が数種類しかなく、したがってわずかな場合に、各変数のデフォルト値を記録する必要はありません可能なデフォルト値。
一部の言語(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++コンストラクタのデフォルトのargsに似ていると仮定しています。その場合、Iraが言及したように、シンボルテーブルレコードのフィールドを作ることは、それを行う最も簡単な方法のように聞こえます。欠落している引数のコードを生成するときは、表のデフォルト値を参照してください。
もう一度ありがとうございます。あなたが私の別の質問に答えたことを覚えています私はコンパイラが "クラス"または "タイプ"の "デフォルト"の代わりにプログラマによって設定されたデフォルト値をどのように処理するのだろうかと思います。ありがとう。 –
@SimonGuo:更新されました。 – blackcompe