vendredi 22 avril 2016

Visitor pattern and compiler code generation how to process assignment?

For code generation in my programming language I am using the visitor pattern and I'd like to find a better way to handle assignment statements.

My virtual machine is registered based and each expression node visited just PUSH a register number into a global stack so when I visit the binary expression node I perform a code like:

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);
    }
}

With this code I can process instructions like: a + b Assuming variable a in register 1 and variable b in register 2 code generated will be:

ADD 3 1 2

The problem is that assignments require a different set of instructions and having only register numbers on the stack is not sufficient. For example in order to access (read) a global variable I should use a GLOAD instruction while to store (write) into a global variable I should use a GSTORE instruction.

I am currently solving the issue by storing a boolean is_assignment value into each node, so I can recursively check which instruction to generate but that requires a lot of logic distributed into every visited node and I really would like to find out a more elegant way where only the visit_binary_expr function can decide what is the best instruction to generate.

Aucun commentaire:

Enregistrer un commentaire