bool compiler::compile_assign_stmt(codegen & cg, assign_stmt * as) { FKLOG("[compiler] compile_assign_stmt %p", as); command var = 0; command value = 0; if (!compile_node(cg, as->value)) { FKERR("[compiler] compile_assign_stmt value fail"); return false; } value = m_cur_addr; FKLOG("[compiler] compile_assign_stmt value = %d", m_cur_addr); m_new_var = as->isnew; if (!compile_node(cg, as->var)) { FKERR("[compiler] compile_assign_stmt var fail"); return false; } m_new_var = false; var = m_cur_addr; FKLOG("[compiler] compile_assign_stmt var = %d", m_cur_addr); cg.push(MAKE_OPCODE(OPCODE_ASSIGN), as->lineno()); cg.push(var, as->lineno()); cg.push(value, as->lineno()); FKLOG("[compiler] compile_assign_stmt %p OK", as); return true; }
NODE(sl_node_def_t, def) { sl_vm_insn_t insn; sl_compile_state_t sub_cs; size_t i, on_reg; init_compile_state(&sub_cs, cs->vm, cs, node->req_arg_count + node->opt_arg_count + 1); for(i = 0; i < node->req_arg_count; i++) { st_insert(sub_cs.vars, (st_data_t)node->req_args[i], (st_data_t)(i + 1)); } for(i = 0; i < node->opt_arg_count; i++) { st_insert(sub_cs.vars, (st_data_t)node->opt_args[i].name, (st_data_t)(node->req_arg_count + i + 1)); } sub_cs.section->name = node->name; sub_cs.section->req_registers = node->req_arg_count; sub_cs.section->arg_registers = node->req_arg_count + node->opt_arg_count; sub_cs.section->opt_skip = sl_alloc(cs->vm->arena, sizeof(size_t) * (node->opt_arg_count + 1)); for(i = 0; i < node->opt_arg_count; i++) { sub_cs.section->opt_skip[i] = sub_cs.section->insns_count; compile_node(&sub_cs, node->opt_args[i].default_value, node->req_arg_count + i + 1); } sub_cs.section->opt_skip[node->opt_arg_count] = sub_cs.section->insns_count; compile_node(&sub_cs, node->body, 0); insn.opcode = SL_OP_RETURN; emit(&sub_cs, insn); insn.uint = 0; emit(&sub_cs, insn); if(node->on) { on_reg = reg_alloc(cs); compile_node(cs, node->on, on_reg); insn.opcode = SL_OP_DEFINE_ON; emit(cs, insn); insn.uint = on_reg; emit(cs, insn); reg_free(cs, on_reg); } else { insn.opcode = SL_OP_DEFINE; emit(cs, insn); } insn.imm = node->name; emit(cs, insn); insn.section = sub_cs.section; emit(cs, insn); insn.uint = dest; emit(cs, insn); }
bool compiler::compile_return_stmt(codegen & cg, return_stmt * rs) { FKLOG("[compiler] compile_return_stmt %p", rs); if (rs->returnlist) { if (!compile_node(cg, rs->returnlist)) { FKERR("[compiler] compile_return_stmt ret fail"); return false; } cg.push(MAKE_OPCODE(OPCODE_RETURN), rs->lineno()); cg.push(MAKE_POS(rs->returnlist->returnlist.size()), rs->lineno()); for (int i = 0; i < (int)rs->returnlist->returnlist.size(); i++) { cg.push(m_cur_addrs[i], rs->lineno()); } } else { cg.push(MAKE_OPCODE(OPCODE_RETURN), rs->lineno()); cg.push(MAKE_POS(0), rs->lineno()); } FKLOG("[compiler] compile_return_stmt %p OK", rs); return true; }
bool compiler::compile_return_value_list(codegen & cg, return_value_list_node * rn) { FKLOG("[compiler] compile_return_value_list %p", rn); if (rn->returnlist.size() > MAX_FAKE_RETURN_NUM) { FKERR("[compiler] compile_return_value_list return too much"); compile_seterror(rn, m_fk, efk_compile_variable_not_found, "return too much"); return false; } command tmp[MAX_FAKE_RETURN_NUM]; for (int i = 0; i < (int)rn->returnlist.size(); i++) { if (!compile_node(cg, rn->returnlist[i])) { FKERR("[compiler] compile_return_value_list value fail"); return false; } tmp[i] = m_cur_addr; } memcpy(m_cur_addrs, tmp, sizeof(command) * MAX_FAKE_RETURN_NUM); m_cur_addr = m_cur_addrs[0]; FKLOG("[compiler] compile_return_value_list %p OK", rn); return true; }
NODE(sl_node_lambda_t, lambda) { sl_vm_insn_t insn; sl_compile_state_t sub_cs; size_t i; init_compile_state(&sub_cs, cs->vm, cs, node->arg_count + 1); for(i = 0; i < node->arg_count; i++) { st_insert(sub_cs.vars, (st_data_t)node->args[i], (st_data_t)(i + 1)); } sub_cs.section->req_registers = node->arg_count; sub_cs.section->arg_registers = node->arg_count; sub_cs.section->name = sl_make_cstring(cs->vm, "<lambda>"); compile_node(&sub_cs, node->body, 0); insn.opcode = SL_OP_RETURN; emit(&sub_cs, insn); insn.uint = 0; emit(&sub_cs, insn); insn.opcode = SL_OP_LAMBDA; emit(cs, insn); insn.section = sub_cs.section; emit(cs, insn); insn.uint = dest; emit(cs, insn); }
static void emit_assignment(sl_compile_state_t* cs, sl_node_base_t* lval, size_t reg) { sl_node_assign_var_t a_var; sl_node_send_t send; size_t dest_reg = reg_alloc(cs); sl_node__register_t node; node.base.type = SL_NODE__REGISTER; node.base.line = 0; node.reg = reg; switch(lval->type) { case SL_NODE_VAR: a_var.base.type = SL_NODE_ASSIGN_VAR; break; case SL_NODE_IVAR: a_var.base.type = SL_NODE_ASSIGN_IVAR; break; case SL_NODE_CVAR: a_var.base.type = SL_NODE_ASSIGN_CVAR; break; case SL_NODE_CONST: a_var.base.type = SL_NODE_ASSIGN_CONST; break; case SL_NODE_ARRAY: a_var.base.type = SL_NODE_ASSIGN_ARRAY; break; case SL_NODE_SEND: /* special case that turns a.b = 1 into a.send("b=", 1) */ /* this is separate to the other method of handling send assignments which also handles compound assignments. */ memcpy(&send, lval, sizeof(sl_node_send_t)); send.id = sl_id_make_setter(cs->vm, send.id); sl_node_base_t** args = sl_alloc(cs->vm->arena, sizeof(sl_node_base_t*) * (send.arg_count + 1)); memcpy(args, send.args, sizeof(sl_node_base_t*) * send.arg_count); args[send.arg_count++] = (sl_node_base_t*)&node; send.args = args; compile_node(cs, (sl_node_base_t*)&send, dest_reg); reg_free(cs, dest_reg); return; default: { SLVAL err = sl_make_cstring(cs->vm, "Invalid lval in assignment"); err = sl_make_error2(cs->vm, cs->vm->lib.SyntaxError, err); sl_error_add_frame(cs->vm, err, sl_make_cstring(cs->vm, "<compiler>"), sl_make_cstring(cs->vm, (char*)cs->section->filename), sl_make_int(cs->vm, lval->line)); sl_throw(cs->vm, err); } } a_var.base.line = 0; a_var.lval = (void*)lval; a_var.rval = (sl_node_base_t*)&node; compile_node(cs, (sl_node_base_t*)&a_var, dest_reg); reg_free(cs, dest_reg); }
bool compiler::compile_multi_assign_stmt(codegen & cg, multi_assign_stmt * as) { FKLOG("[compiler] compile_multi_assign_stmt %p", as); // 目前多重赋值只支持a,b,c = myfunc1(),需要告诉func1多返回几个值 m_func_ret_num = as->varlist->varlist.size(); // 编译value if (!compile_node(cg, as->value)) { FKERR("[compiler] compile_multi_assign_stmt value fail"); return false; } // 挨个编译var std::vector<command> varlist; for (int i = 0; i < (int)as->varlist->varlist.size(); i++) { m_new_var = as->isnew; if (!compile_node(cg, as->varlist->varlist[i])) { FKERR("[compiler] compile_multi_assign_stmt var fail"); return false; } m_new_var = false; varlist.push_back(m_cur_addr); } // 挨个赋值 for (int i = 0; i < (int)as->varlist->varlist.size(); i++) { command var = 0; command value = 0; var = varlist[i]; value = m_cur_addrs[i]; cg.push(MAKE_OPCODE(OPCODE_ASSIGN), as->lineno()); cg.push(var, as->lineno()); cg.push(value, as->lineno()); } FKLOG("[compiler] compile_multi_assign_stmt %p OK", as); return true; }
NODE(sl_node_interp_string_t, interp_string) { size_t base_reg = reg_alloc_block(cs, node->components_count); for(size_t i = 0; i < node->components_count; i++) { compile_node(cs, node->components[i], base_reg + i); } op_build_string(cs, base_reg, node->components_count, dest); reg_free_block(cs, base_reg, node->components_count); }
NODE(sl_node_echo_t, echo_raw) { sl_vm_insn_t insn; compile_node(cs, node->expr, dest); insn.opcode = SL_OP_ECHO_RAW; emit(cs, insn); insn.uint = dest; emit(cs, insn); }
NODE(sl_node_def_t, def) { sl_compile_state_t sub_cs; size_t i, on_reg; size_t init_regs = 1 + node->req_arg_count + node->opt_arg_count; if(node->rest_arg) { init_regs++; } init_compile_state(&sub_cs, cs->vm, cs, init_regs); for(i = 0; i < node->req_arg_count; i++) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->req_args[i], (sl_st_data_t)(i + 1)); } for(i = 0; i < node->opt_arg_count; i++) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->opt_args[i].name, (sl_st_data_t)(node->req_arg_count + i + 1)); } if(node->rest_arg) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->rest_arg, (sl_st_data_t)(node->req_arg_count + node->opt_arg_count + 1)); sub_cs.section->has_extra_rest_arg = 1; } sub_cs.section->name = node->name; sub_cs.section->req_registers = node->req_arg_count; sub_cs.section->arg_registers = node->req_arg_count + node->opt_arg_count; sub_cs.section->opt_skip = sl_alloc(cs->vm->arena, sizeof(size_t) * (node->opt_arg_count + 1)); for(i = 0; i < node->opt_arg_count; i++) { sub_cs.section->opt_skip[i] = sub_cs.section->insns_count; compile_node(&sub_cs, node->opt_args[i].default_value, node->req_arg_count + i + 1); } sub_cs.section->opt_skip[node->opt_arg_count] = sub_cs.section->insns_count; compile_node(&sub_cs, node->body, 0); op_return(&sub_cs, 0); if(node->on) { on_reg = reg_alloc(cs); compile_node(cs, node->on, on_reg); op_define_on(cs, on_reg, node->name, node->doc, sub_cs.section, dest); reg_free(cs, on_reg); } else { op_define(cs, node->name, node->doc, sub_cs.section, dest); } }
NODE(sl_node_seq_t, seq) { size_t i; for(i = 0; i < node->node_count; i++) { /* we only care about the result of the last node so we'll write all results to the same output register we were given */ compile_node(cs, node->nodes[i], dest); } if(node->node_count == 0) { op_immediate(cs, cs->vm->lib.nil, dest); } }
NODE(sl_node_lambda_t, lambda) { sl_compile_state_t sub_cs; size_t i; init_compile_state(&sub_cs, cs->vm, cs, node->arg_count + 1); for(i = 0; i < node->arg_count; i++) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->args[i], (sl_st_data_t)(i + 1)); } sub_cs.section->req_registers = node->arg_count; sub_cs.section->arg_registers = node->arg_count; sub_cs.section->name = sl_intern(cs->vm, "<lambda>"); compile_node(&sub_cs, node->body, 0); op_return(&sub_cs, 0); op_lambda(cs, sub_cs.section, dest); }
bool compiler::compile_block(codegen & cg, block_node * blocknode) { FKLOG("[compiler] compile_block block_node %p", blocknode); for (int i = 0; i < (int)blocknode->stmtlist.size(); i++) { syntree_node * stmt = blocknode->stmtlist[i]; if (!compile_node(cg, stmt)) { FKERR("[compiler] compile_block compile_node %p fail %s", blocknode, stmt->gettypename()); return false; } } FKLOG("[compiler] compile_block block_node %p OK", blocknode); return true; }
bool compiler::compile_container_get(codegen & cg, container_get_node * cn) { FKLOG("[compiler] compile_container_get %p", cn); // 编译con command con = 0; // 看看是否是全局常量定义 variant * gcv = m_fk->pa.get_const_define(cn->container.c_str()); if (gcv) { int pos = cg.getconst(*gcv); con = MAKE_ADDR(ADDR_CONST, pos); } else { int pos = cg.getvariable(cn->container); if (pos == -1) { FKERR("[compiler] compile_container_get variable not found %s", cn->container.c_str()); compile_seterror(cn, m_fk, efk_compile_variable_not_found, "variable %s not found", cn->container.c_str()); return false; } con = MAKE_ADDR(ADDR_STACK, pos); } // 编译key command key = 0; if (!compile_node(cg, cn->key)) { FKERR("[compiler] compile_container_get key fail"); return false; } key = m_cur_addr; // 返回 int addrpos = cg.getcontaineraddr(con, key); m_cur_addr = MAKE_ADDR(ADDR_CONTAINER, addrpos); FKLOG("[compiler] compile_container_get %p OK", cn); return true; }
bool compiler::compile_yield_stmt(codegen & cg, yield_stmt * ys) { FKLOG("[compiler] compile_yield_stmt %p", ys); // 编译time command time = 0; if (!compile_node(cg, ys->time)) { FKERR("[compiler] compile_sleep_stmt time fail"); return false; } time = m_cur_addr; cg.push(MAKE_OPCODE(OPCODE_YIELD), ys->lineno()); cg.push(time, ys->lineno()); FKLOG("[compiler] compile_yield_stmt %p OK", ys); return true; }
bool compiler::compile_while_stmt(codegen & cg, while_stmt * ws) { FKLOG("[compiler] compile_while_stmt %p", ws); int startpos = 0; int jnepos = 0; m_loop_break_pos_stack.push_back(beak_pos_list()); startpos = cg.byte_code_size(); m_loop_continue_pos_stack.push_back(startpos); // 条件 cg.push_stack_identifiers(); if (!compile_node(cg, ws->cmp)) { FKERR("[compiler] compile_while_stmt cmp fail"); return false; } cg.pop_stack_identifiers(); // cmp与jne结合 if (m_cmp_jne) { cg.push(EMPTY_CMD, ws->cmp->lineno()); // 先塞个位置 jnepos = cg.byte_code_size() - 1; } else { cg.push(MAKE_OPCODE(OPCODE_JNE), ws->lineno()); cg.push(m_cur_addr, ws->lineno()); cg.push(EMPTY_CMD, ws->lineno()); // 先塞个位置 jnepos = cg.byte_code_size() - 1; } m_cmp_deps = 0; m_cmp_jne = false; // block块 if (ws->block) { cg.push_stack_identifiers(); if (!compile_node(cg, ws->block)) { FKERR("[compiler] compile_while_stmt block fail"); return false; } cg.pop_stack_identifiers(); } // 跳回判断地方 cg.push(MAKE_OPCODE(OPCODE_JMP), ws->lineno()); cg.push(MAKE_POS(startpos), ws->lineno()); // 跳转出block块 cg.set(jnepos, MAKE_POS(cg.byte_code_size())); // 替换掉break beak_pos_list & bplist = m_loop_break_pos_stack[m_loop_break_pos_stack.size() - 1]; for (int i = 0; i < (int)bplist.size(); i++) { cg.set(bplist[i], MAKE_POS(cg.byte_code_size())); } m_loop_break_pos_stack.pop_back(); m_loop_continue_pos_stack.pop_back(); FKLOG("[compiler] compile_while_stmt %p OK", ws); return true; }
bool compiler::compile_function_call_node(codegen & cg, function_call_node * fn) { FKLOG("[compiler] compile_function_call_node %p", fn); fake * fk = m_fk; myflexer * mf = m_mf; int ret_num = m_func_ret_num; m_func_ret_num = 1; // 参数 std::vector<command> arglist; if (fn->arglist) { for (int i = 0; i < (int)fn->arglist->arglist.size(); i++) { syntree_node* sn = fn->arglist->arglist[i]; if (!compile_node(cg, sn)) { FKERR("[compiler] compile_function_call_node arg fail"); return false; } arglist.push_back(m_cur_addr); } } // 调用位置 command callpos; if (!fn->prefunc) { String func = fn->fuc; // 1 检查变量 int pos = cg.getvariable(func); if (pos != -1) { // 是用变量来调用函数 callpos = MAKE_ADDR(ADDR_STACK, pos); } // 2 检查struct else if (mf->is_have_struct(func)) { // 直接替换成map variant v; v = fk->sh.allocsysstr(MAP_FUNC_NAME); pos = cg.getconst(v); callpos = MAKE_ADDR(ADDR_CONST, pos); } // 3 检查本地函数 else if (mf->is_have_func(func)) { // 申请字符串变量 variant v; // 拼上包名 String pname = fkgen_package_name(mf->get_package(), func); v = fk->sh.allocsysstr(pname.c_str()); pos = cg.getconst(v); callpos = MAKE_ADDR(ADDR_CONST, pos); } // 4 直接字符串使用 else { // 申请字符串变量 variant v; v = fk->sh.allocsysstr(func.c_str()); pos = cg.getconst(v); callpos = MAKE_ADDR(ADDR_CONST, pos); } } else { if (!compile_node(cg, fn->prefunc)) { FKERR("[compiler] compile_function_call_node arg fail"); return false; } callpos = m_cur_addr; } // oper command oper; oper = MAKE_OPCODE(OPCODE_CALL); // 调用类型 command calltype; if (fn->fakecall) { calltype = MAKE_POS(CALL_FAKE); } else if (fn->classmem_call) { calltype = MAKE_POS(CALL_CLASSMEM); } else { calltype = MAKE_POS(CALL_NORMAL); } // 参数个数 command argnum; argnum = MAKE_POS(arglist.size()); if (arglist.size() > MAX_FAKE_PARAM_NUM) { FKERR("[compiler] compile_function_call_node arg too much"); compile_seterror(fn, m_fk, efk_compile_variable_not_found, "arg too much"); return false; } // 返回值个数 command retnum; retnum = MAKE_POS(ret_num); // 返回值 std::vector<command> ret; for (int i = 0; i < ret_num; i++) { int retpos = cg.alloc_stack_identifier(); ret.push_back(MAKE_ADDR(ADDR_STACK, retpos)); m_cur_addrs[i] = ret[i]; } m_cur_addr = ret[0]; cg.push(oper, fn->lineno()); cg.push(calltype, fn->lineno()); cg.push(callpos, fn->lineno()); cg.push(retnum, fn->lineno()); for (int i = 0; i < ret_num; i++) { cg.push(ret[i], fn->lineno()); } cg.push(argnum, fn->lineno()); for (int i = 0; i < (int)arglist.size(); i++) { cg.push(arglist[i], fn->lineno()); } FKLOG("[compiler] compile_function_call_node %p OK", fn); return true; }
bool compiler::compile_math_expr_node(codegen & cg, math_expr_node * mn) { FKLOG("[compiler] compile_math_expr_node %p", mn); command oper = 0; command left = 0; command right = 0; command dest = 0; if (mn->oper == "+") { oper = MAKE_OPCODE(OPCODE_PLUS); } else if (mn->oper == "-") { oper = MAKE_OPCODE(OPCODE_MINUS); } else if (mn->oper == "*") { oper = MAKE_OPCODE(OPCODE_MULTIPLY); } else if (mn->oper == "/") { oper = MAKE_OPCODE(OPCODE_DIVIDE); } else if (mn->oper == "%") { oper = MAKE_OPCODE(OPCODE_DIVIDE_MOD); } else if (mn->oper == "..") { oper = MAKE_OPCODE(OPCODE_STRING_CAT); } else { FKERR("[compiler] compile_math_expr_node error oper type fail"); compile_seterror(mn, m_fk, efk_compile_math_type_error, "compile math oper type %s error", mn->oper.c_str()); return false; } // left if (!compile_node(cg, mn->left)) { FKERR("[compiler] compile_math_expr_node left fail"); return false; } left = m_cur_addr; // right if (!compile_node(cg, mn->right)) { FKERR("[compiler] compile_math_expr_node left fail"); return false; } right = m_cur_addr; // result int despos = cg.alloc_stack_identifier(); dest = MAKE_ADDR(ADDR_STACK, despos); m_cur_addr = dest; cg.push(oper, mn->lineno()); cg.push(left, mn->lineno()); cg.push(right, mn->lineno()); cg.push(dest, mn->lineno()); FKLOG("[compiler] compile_math_expr_node %p OK", mn); return true; }
NODE(sl_node_echo_t, echo_raw) { compile_node(cs, node->expr, dest); op_echo_raw(cs, dest); }
bool compiler::compile_cmp_stmt(codegen & cg, cmp_stmt * cs) { FKLOG("[compiler] compile_cmp_stmt %p", cs); int deps = m_cmp_deps; m_cmp_deps++; command oper = 0; command left = 0; command right = 0; command dest = 0; if (cs->cmp != "not") { // oper if (cs->cmp == "&&") { oper = !deps ? MAKE_OPCODE(OPCODE_AND_JNE) : MAKE_OPCODE(OPCODE_AND); } else if (cs->cmp == "||") { oper = !deps ? MAKE_OPCODE(OPCODE_OR_JNE) : MAKE_OPCODE(OPCODE_OR); } else if (cs->cmp == "<") { oper = !deps ? MAKE_OPCODE(OPCODE_LESS_JNE) : MAKE_OPCODE(OPCODE_LESS); } else if (cs->cmp == ">") { oper = !deps ? MAKE_OPCODE(OPCODE_MORE_JNE) : MAKE_OPCODE(OPCODE_MORE); } else if (cs->cmp == "==") { oper = !deps ? MAKE_OPCODE(OPCODE_EQUAL_JNE) : MAKE_OPCODE(OPCODE_EQUAL); } else if (cs->cmp == ">=") { oper = !deps ? MAKE_OPCODE(OPCODE_MOREEQUAL_JNE) : MAKE_OPCODE(OPCODE_MOREEQUAL); } else if (cs->cmp == "<=") { oper = !deps ? MAKE_OPCODE(OPCODE_LESSEQUAL_JNE) : MAKE_OPCODE(OPCODE_LESSEQUAL); } else if (cs->cmp == "!=") { oper = !deps ? MAKE_OPCODE(OPCODE_NOTEQUAL_JNE) : MAKE_OPCODE(OPCODE_NOTEQUAL); } else if (cs->cmp == "true") { variant v; V_SET_REAL((&v), 1); int pos = cg.getconst(v); m_cur_addr = MAKE_ADDR(ADDR_CONST, pos); m_cmp_deps--; m_cmp_jne = false; return true; } else if (cs->cmp == "false") { variant v; V_SET_REAL((&v), 0); int pos = cg.getconst(v); m_cur_addr = MAKE_ADDR(ADDR_CONST, pos); m_cmp_deps--; m_cmp_jne = false; return true; } else if (cs->cmp == "is") { // left if (!compile_node(cg, cs->left)) { FKERR("[compiler] compile_cmp_stmt left fail"); return false; } m_cmp_deps--; m_cmp_jne = false; return true; } else { FKERR("[compiler] compile_cmp_stmt cmp error %s", cs->cmp.c_str()); compile_seterror(cs, m_fk, efk_compile_cmp_error, "cmp error %s", cs->cmp.c_str()); return false; } // left if (!compile_node(cg, cs->left)) { FKERR("[compiler] compile_cmp_stmt left fail"); return false; } left = m_cur_addr; // right if (!compile_node(cg, cs->right)) { FKERR("[compiler] compile_cmp_stmt right fail"); return false; } right = m_cur_addr; // result int despos = cg.alloc_stack_identifier(); dest = MAKE_ADDR(ADDR_STACK, despos); m_cur_addr = dest; cg.push(oper, cs->lineno()); cg.push(left, cs->lineno()); cg.push(right, cs->lineno()); cg.push(dest, cs->lineno()); } /* "not" */ else { oper = !deps ? MAKE_OPCODE(OPCODE_NOT_JNE) : MAKE_OPCODE(OPCODE_NOT); // left if (!compile_node(cg, cs->left)) { FKERR("[compiler] compile_cmp_stmt left fail"); return false; } left = m_cur_addr; int despos = cg.alloc_stack_identifier(); dest = MAKE_ADDR(ADDR_STACK, despos); m_cur_addr = dest; cg.push(oper, cs->lineno()); cg.push(left, cs->lineno()); cg.push(dest, cs->lineno()); } m_cmp_deps--; if (!deps) { m_cmp_jne = true; } FKLOG("[compiler] compile_cmp_stmt %p OK", cs); return true; }
bool compiler::compile_math_assign_stmt(codegen & cg, math_assign_stmt * ms) { FKLOG("[compiler] compile_math_assign_stmt %p", ms); command oper = 0; command var = 0; command value = 0; if (ms->oper == "+=") { oper = MAKE_OPCODE(OPCODE_PLUS_ASSIGN); } else if (ms->oper == "-=") { oper = MAKE_OPCODE(OPCODE_MINUS_ASSIGN); } else if (ms->oper == "*=") { oper = MAKE_OPCODE(OPCODE_MULTIPLY_ASSIGN); } else if (ms->oper == "/=") { oper = MAKE_OPCODE(OPCODE_DIVIDE_ASSIGN); } else if (ms->oper == "%=") { oper = MAKE_OPCODE(OPCODE_DIVIDE_MOD_ASSIGN); } else { FKERR("[compiler] compile_math_assign_stmt error oper type fail"); compile_seterror(ms, m_fk, efk_compile_math_type_error, "compile math assign oper type %s error", ms->oper.c_str()); return false; } // value if (!compile_node(cg, ms->value)) { FKERR("[compiler] compile_math_assign_stmt value fail"); return false; } value = m_cur_addr; FKLOG("[compiler] compile_math_assign_stmt value = %d", m_cur_addr); // var if (!compile_node(cg, ms->var)) { FKERR("[compiler] compile_math_assign_stmt var fail"); return false; } var = m_cur_addr; FKLOG("[compiler] compile_math_assign_stmt var = %d", m_cur_addr); cg.push(oper, ms->lineno()); cg.push(var, ms->lineno()); cg.push(value, ms->lineno()); FKLOG("[compiler] compile_math_assign_stmt %p OK", ms); return true; }
bool compiler::compile_switch_stmt(codegen & cg, switch_stmt * ss) { FKLOG("[compiler] compile_switch_stmt %p", ss); command caseleft; command caseresult; cg.push_stack_identifiers(); // caseleft if (!compile_node(cg, ss->cmp)) { FKERR("[compiler] compile_switch_stmt cmp fail"); return false; } caseleft = m_cur_addr; // caseresult int despos = cg.alloc_stack_identifier(); caseresult = MAKE_ADDR(ADDR_STACK, despos); switch_caselist_node * scln = dynamic_cast<switch_caselist_node *>(ss->caselist); std::vector<int> jmpswitchposlist; // 挨个和case的比较 for (int i = 0; i < (int)scln->list.size(); i++) { command oper = MAKE_OPCODE(OPCODE_EQUAL); command left = caseleft; command right = 0; command dest = caseresult; switch_case_node * scn = dynamic_cast<switch_case_node *>(scln->list[i]); // right if (!compile_node(cg, scn->cmp)) { FKERR("[compiler] compile_switch_stmt case cmp fail"); return false; } right = m_cur_addr; // push case cg.push(oper, scn->lineno()); cg.push(left, scn->lineno()); cg.push(right, scn->lineno()); cg.push(dest, scn->lineno()); // push jmp cg.push(MAKE_OPCODE(OPCODE_JNE), scn->lineno()); cg.push(dest, scn->lineno()); cg.push(EMPTY_CMD, scn->lineno()); // 先塞个位置 int jnepos = cg.byte_code_size() - 1; // build block if (scn->block) { cg.push_stack_identifiers(); if (!compile_node(cg, scn->block)) { FKERR("[compiler] compile_switch_stmt block fail"); return false; } cg.pop_stack_identifiers(); } // 跳出switch块 cg.push(MAKE_OPCODE(OPCODE_JMP), scn->lineno()); cg.push(EMPTY_CMD, scn->lineno()); // 先塞个位置 int jmpswitchpos = cg.byte_code_size() - 1; jmpswitchposlist.push_back(jmpswitchpos); // 跳转出case块 cg.set(jnepos, MAKE_POS(cg.byte_code_size())); } // default if (ss->def) { cg.push_stack_identifiers(); if (!compile_node(cg, ss->def)) { FKERR("[compiler] compile_switch_stmt default fail"); return false; } cg.pop_stack_identifiers(); } cg.pop_stack_identifiers(); // 塞跳出的 for (int i = 0; i < (int)jmpswitchposlist.size(); i++) { cg.set(jmpswitchposlist[i], MAKE_POS(cg.byte_code_size())); } FKLOG("[compiler] compile_switch_stmt %p OK", ss); return true; }
bool compiler::compile_if_stmt(codegen & cg, if_stmt * is) { FKLOG("[compiler] compile_if_stmt %p", is); int jnepos = 0; std::vector<int> jmpifpos; // 条件 cg.push_stack_identifiers(); if (!compile_node(cg, is->cmp)) { FKERR("[compiler] compile_if_stmt cmp fail"); return false; } cg.pop_stack_identifiers(); // cmp与jne结合 if (m_cmp_jne) { cg.push(EMPTY_CMD, is->cmp->lineno()); // 先塞个位置 jnepos = cg.byte_code_size() - 1; } else { cg.push(MAKE_OPCODE(OPCODE_JNE), is->lineno()); cg.push(m_cur_addr, is->lineno()); cg.push(EMPTY_CMD, is->lineno()); // 先塞个位置 jnepos = cg.byte_code_size() - 1; } m_cmp_deps = 0; m_cmp_jne = false; // if块 if (is->block) { cg.push_stack_identifiers(); if (!compile_node(cg, is->block)) { FKERR("[compiler] compile_if_stmt block fail"); return false; } cg.pop_stack_identifiers(); } // 跳出if块 if (is->elseifs || (is->elses && is->elses->block)) { cg.push(MAKE_OPCODE(OPCODE_JMP), is->lineno()); cg.push(EMPTY_CMD, is->lineno()); // 先塞个位置 jmpifpos.push_back(cg.byte_code_size() - 1); } // 开始处理elseif的 if (is->elseifs) { stmt_node_list & list = is->elseifs->stmtlist; for (int i = 0; i < (int)list.size(); i++) { elseif_stmt * eis = dynamic_cast<elseif_stmt *>(list[i]); // 跳转到else if cg.set(jnepos, MAKE_POS(cg.byte_code_size())); // 条件 cg.push_stack_identifiers(); if (!compile_node(cg, eis->cmp)) { FKERR("[compiler] compile_if_stmt cmp fail"); return false; } cg.pop_stack_identifiers(); // cmp与jne结合 if (m_cmp_jne) { cg.push(EMPTY_CMD, eis->cmp->lineno()); // 先塞个位置 jnepos = cg.byte_code_size() - 1; } else { cg.push(MAKE_OPCODE(OPCODE_JNE), eis->lineno()); cg.push(m_cur_addr, eis->lineno()); cg.push(EMPTY_CMD, eis->lineno()); // 先塞个位置 jnepos = cg.byte_code_size() - 1; } m_cmp_deps = 0; m_cmp_jne = false; // else if块 if (eis->block) { cg.push_stack_identifiers(); if (!compile_node(cg, eis->block)) { FKERR("[compiler] compile_if_stmt block fail"); return false; } cg.pop_stack_identifiers(); } // 跳出if块 cg.push(MAKE_OPCODE(OPCODE_JMP), eis->lineno()); cg.push(EMPTY_CMD, eis->lineno()); // 先塞个位置 jmpifpos.push_back(cg.byte_code_size() - 1); } } // 跳转到else cg.set(jnepos, MAKE_POS(cg.byte_code_size())); // else块 if (is->elses && is->elses->block) { cg.push_stack_identifiers(); if (!compile_node(cg, is->elses->block)) { FKERR("[compiler] compile_if_stmt else block fail"); return false; } cg.pop_stack_identifiers(); } // 跳转到结束 for (int i = 0; i < (int)jmpifpos.size(); i++) { cg.set(jmpifpos[i], MAKE_POS(cg.byte_code_size())); } FKLOG("[compiler] compile_if_stmt %p OK", is); return true; }
bool compiler::compile_for_loop_stmt(codegen & cg, for_loop_stmt * fs) { FKLOG("[compiler] compile_for_loop_stmt %p", fs); int startpos = 0; int jnepos = 0; int continuepos = 0; m_loop_break_pos_stack.push_back(beak_pos_list()); m_continue_end_pos_stack.push_back(continue_end_pos_list()); // 初始值 if (!compile_node(cg, fs->begin)) { FKERR("[compiler] compile_for_loop_stmt begin fail"); return false; } command begin = m_cur_addr; // 循环变量,这个作用域是全for都有效的 cg.push_stack_identifiers(); if (!compile_node(cg, fs->var)) { FKERR("[compiler] compile_for_loop_stmt var fail"); return false; } command var = m_cur_addr; // 最大值 if (!compile_node(cg, fs->end)) { FKERR("[compiler] compile_for_loop_stmt end fail"); return false; } command end = m_cur_addr; // 变化值 if (!compile_node(cg, fs->add)) { FKERR("[compiler] compile_for_loop_stmt add fail"); return false; } command add = m_cur_addr; // 塞for头 cg.push(MAKE_OPCODE(OPCODE_FORBEGIN), fs->lineno()); cg.push(var, fs->lineno()); cg.push(begin, fs->lineno()); cg.push(end, fs->lineno()); cg.push(add, fs->lineno()); cg.push(EMPTY_CMD, fs->lineno()); // 先塞个位置 jnepos = cg.byte_code_size() - 1; // 需要continue end m_loop_continue_pos_stack.push_back(-1); startpos = cg.byte_code_size(); // block块 if (fs->block) { cg.push_stack_identifiers(); if (!compile_node(cg, fs->block)) { FKERR("[compiler] compile_for_loop_stmt block fail"); return false; } cg.pop_stack_identifiers(); } continuepos = cg.byte_code_size(); // 最大值 if (!compile_node(cg, fs->end)) { FKERR("[compiler] compile_for_loop_stmt end fail"); return false; } end = m_cur_addr; // 变化值 if (!compile_node(cg, fs->add)) { FKERR("[compiler] compile_for_loop_stmt add fail"); return false; } add = m_cur_addr; // 塞for loop cg.push(MAKE_OPCODE(OPCODE_FORLOOP), fs->lineno()); cg.push(var, fs->lineno()); cg.push(end, fs->lineno()); cg.push(add, fs->lineno()); cg.push(MAKE_POS(startpos), fs->lineno()); // 跳转出block块 cg.set(jnepos, MAKE_POS(cg.byte_code_size())); // 替换掉break beak_pos_list & bplist = m_loop_break_pos_stack[m_loop_break_pos_stack.size() - 1]; for (int i = 0; i < (int)bplist.size(); i++) { cg.set(bplist[i], MAKE_POS(cg.byte_code_size())); } m_loop_break_pos_stack.pop_back(); // 替换掉continue continue_end_pos_list & cplist = m_continue_end_pos_stack[m_continue_end_pos_stack.size() - 1]; for (int i = 0; i < (int)cplist.size(); i++) { cg.set(cplist[i], MAKE_POS(continuepos)); } m_continue_end_pos_stack.pop_back(); m_loop_continue_pos_stack.pop_back(); // 离开作用域 cg.pop_stack_identifiers(); FKLOG("[compiler] compile_for_loop_stmt %p OK", fs); return true; }