2

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

更新:プログラムパラメータb以下の私はPythonで言う意味 ここではデフォルト値は、デフォルト値0を持っています。

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

我々が得る01を発生します。では、これは実行時やコンパイル時にどのようにコンパイラによって処理されますか?

答えて

1

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

+0

もう一度ありがとうございます。あなたが私の別の質問に答えたことを覚えています私はコンパイラが "クラス"または "タイプ"の "デフォルト"の代わりにプログラマによって設定されたデフォルト値をどのように処理するのだろうかと思います。ありがとう。 –

+0

@SimonGuo:更新されました。 – blackcompe

3

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

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

コンパイラは、通常、これらの小さな名前空間にシンボルテーブルエントリを持ち、シンボル(例えば、任意のタイプ情報)と他の情報を関連付けるので、これはかなり自然な場所です。

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

関連する問題