3

自分のプログラミング言語でコードを生成するために、私は訪問者パターンを使用しています。代入文を処理するためのより良い方法を探したいと思います。ビジターパターンとコンパイラコードの生成、割り当ての処理方法は?

私の仮想マシンをベースに登録し、各式ノードは、ちょうど私がバイナリ式ノードを訪問するときに、私は次のようなコードを実行するグ​​ローバルスタックにレジスタ番号をPUSH訪れている:私はすることができます。このコードで

static void visit_binary_expr (gvisitor_t *self, gnode_binary_expr_t *node) { 
    DECLARE_CODE(); 

    bool is_assignment = (node->op == TOK_OP_ASSIGN); 
    if (is_assignment) { 
     // assignment is right associative 
     visit(node->right); 
     visit(node->left); 
    } else { 
     // visiting binary operation from left to right 
     visit(node->left); 
     visit(node->right); 
    } 

    if (!is_assignment) { 
     uint32_t r3 = ircode_register_pop(code); 
     uint32_t r2 = ircode_register_pop(code); 
     uint32_t r1 = ircode_register_push_temp(code); 

     opcode_t op = token2opcode(node->op); 
     ircode_add(code, op, r1, r2, r3); 
    } 
} 

以下のような処理指示:レジスタのレジスタ1と変数Bに変数Aを仮定すると、A + B が生成2のコードは次のようになります

ADD 3 1 2 

問題を割り当て、命令の異なるセットを必要とするで有することですスタック上のレジスタ番号は不十分です。たとえば、グローバル変数にアクセス(読み込み)するには、GLOAD命令を使用してグローバル変数に格納(書き込み)する必要があります.GSTORE命令を使用する必要があります。

私は現在、各ノードにboolean is_assignment値を格納することで問題を解決しています。そのため、どの命令を生成するかを再帰的に確認できますが、それは多くのロジックを訪問ノードに分散させる必要があります。 visit_binary_expr関数だけが、生成する最適な命令が何であるかを判断できる、よりエレガントな方法です。

答えて

1

割り当ては他のバイナリ操作(左辺のオペランドを変更する副作用があります)とはかなり異なるため、バイナリ操作にはまったく関係なく、完全に別の操作として処理することは理にかなっています。その場合、対応する型の第2引数を持つvisit_assignmentのようなものがあります。

これで、現在のコードに存在するすべてのチェックを避けることができます。また、あなたの言語が許すターゲットの種類に応じて、代入ターゲットの処理では、ターゲットが処理されていることを示すフラグを持つ別のトラバーサル関数、別のビジター、同じビジターを正規表現ではなく使用することができます。アプローチがより良いかどうかの判断は、生成する必要がある言語とコードによって異なります。

関連する問題