访问者模式和编译器代码生成,如何处理赋值?(Visitor pattern and compiler code generation, how to process assignment?)
对于我的编程语言中的代码生成,我使用访问者模式,我想找到一种更好的方法来处理赋值语句。
我的虚拟机是基于注册的,每个表达式节点只访问一个寄存器编号到全局堆栈中,所以当我访问二进制表达式节点时,我执行如下代码:
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); } }
使用此代码,我可以处理如下指令:a + b假设寄存器1中的变量a和寄存器2中的变量b生成的代码将是:
ADD 3 1 2
问题是分配需要一组不同的指令,并且只有堆栈上的寄存器号是不够的。 例如,为了访问(读取)全局变量,我应该使用GLOAD指令,而在存储(写入)全局变量时,我应该使用GSTORE指令。
我目前正在通过将boolean is_assignment值存储到每个节点来解决这个问题,所以我可以递归地检查要生成哪条指令但是需要将大量逻辑分配到每个被访问节点中,我真的想找到一种更优雅的方式只有visit_binary_expr函数可以决定生成的最佳指令是什么。
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.
原文:https://stackoverflow.com/questions/36800908