2

一部のプログラミング言語では、関数呼び出しでパラメータにデフォルト値を設定したり、構造体の属性にデフォルト値を設定したりできます。Python や JavaScript のように、関数呼び出しでいくつかのパラメーターを省略すると、デフォルト値が関数で置き換えられます (構造体が属性にもデフォルトを持つことができるのと同じです)。では、コンパイラは実際にこれをどのように処理するのでしょうか? 特にシンボルテーブルで?デフォルト値を指すポインターにもう1つの属性を追加すると、実行時にデフォルト値がスタックにプッシュされると思いますか? 私が正しいかどうか教えてください。ありがとう。

更新: ここでのデフォルト値は、Python で言うと、次のプログラム パラメータbにはデフォルト値があります0

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

結果0とが得られ1ます。では、これは実行時またはコンパイル時にコンパイラによってどのように処理されるのでしょうか?

4

2 に答える 2

3

どのようにしても、デフォルト値を特定の識別子に関連付ける必要があります。

パラメーター リストと構造体メンバーは小さな名前空間を形成し、コンパイラは通常、それらの名前空間のシンボル テーブルと、名前空間の関係を追跡するより大きなシンボル テーブルを構築することによってそれらを追跡します。

コンパイラは通常、他の情報 (たとえば、型情報) をシンボルに関連付けるこれらの小さな名前空間にシンボル テーブル エントリを既に持っているので、これはそれを記録する非常に自然な場所です。

初期値として正確に何を記録するかという問題があります。簡単なことは、初期値/デフォルト値を表す AST へのポインタを記録することです。それに加えて、その式を評価するコンテキスト (「環境」など) を記録する必要があります。このコンテキストは、多くの場合、構造体/パラメーターが定義されたコンテキストと同じであるため、暗黙のままにすることができます。その情報は、すべてを結合するより大きなシンボル テーブルに格納されます。

于 2012-04-16T05:44:37.393 に答える
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 が述べたように、シンボル テーブル レコードのフィールドを作成するのが最も簡単な方法のように思えます。欠落している引数のコードを生成するときは、表でデフォルト値を調べてください。

于 2012-04-16T18:44:23.190 に答える