関数呼び出しの引数リストが評価されると、コード ジェネレーターは、リストをシンボル テーブルに格納されている関数シグネチャと比較することによって、どの引数が欠落しているかを知ることができます。どの引数を置き換える必要があるかを識別したら、引数レジスタ (またはスタック フレーム) にデフォルト値をスローするだけです。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 が述べたように、シンボル テーブル レコードのフィールドを作成するのが最も簡単な方法のように思えます。欠落している引数のコードを生成するときは、表でデフォルト値を調べてください。