void CodeGenerateVisitor::Visit(LocalNameListStatement *local_name, void *data) { // Visit local names local_name->name_list_->Accept(this, data); int reg = func_->GetNextRegister(); int names = func_state_->names_register_.size(); // Visit exp list if (local_name->exp_list_) { func_state_->PushExpListValueCount(names); local_name->exp_list_->Accept(this, data); } // Set local name init value int exp_reg = reg; for (int i = 0; i < names; ++i, ++exp_reg) { int name_reg = func_state_->names_register_[i].register_; func_->AddInstruction(Instruction::ABCode(OpType_Move, name_reg, exp_reg), func_state_->names_register_[i].token_->line_); } func_state_->names_register_.clear(); // Restore register func_->SetNextRegister(reg); func_->AddInstruction(Instruction::ACode(OpType_SetTop, reg), 0); }
void CodeGenerateVisitor::Visit(NormalFuncCall *func_call, void *data) { int reg = func_->GetNextRegister(); int result_count = func_state_->PopExpValueCount(); // Load function func_state_->PushExpValueCount(1); func_call->caller_->Accept(this, data); // Prepare args func_call->args_->Accept(this, data); func_->AddInstruction(Instruction::AsBxCode(OpType_Call, reg, result_count), 0); }
void CodeGenerateVisitor::Visit(Block *block, void *data) { NameScope current(scope_name_list_, func_); int reg = func_->GetNextRegister(); // Visit all statements for (auto &s : block->statements_) s->Accept(this, data); // Visit return statement if exist if (block->return_stmt_) block->return_stmt_->Accept(this, data); // Restore register func_->SetNextRegister(reg); func_->AddInstruction(Instruction::ACode(OpType_SetTop, reg), 0); }
void CodeGenerateVisitor::Visit(Terminator *term, void *data) { const TokenDetail &t = term->token_; int value_count = func_state_->PopExpValueCount(); if (t.token_ == Token_Number || t.token_ == Token_String) { int index = 0; if (t.token_ == Token_Number) index = func_->AddConstNumber(t.number_); else index = func_->AddConstString(t.str_); if (value_count != 0) { int reg = func_->AllocaNextRegister(); func_->AddInstruction(Instruction::ABCode(OpType_LoadConst, reg, index), t.line_); } } else if (t.token_ == Token_Id) { auto s = scope_name_list_.current_scope_->GetBlongsToScope(t.str_); // Token_Id not in scope, then this id is in env table if (!s.first) { int index = func_->AddConstString(t.str_); if (value_count != 0) { int reg = func_->AllocaNextRegister(); // Load key func_->AddInstruction(Instruction::ABCode(OpType_LoadConst, reg, index), t.line_); // Get value from uptable func_->AddInstruction(Instruction::ABCCode(OpType_GetUpTable, reg, ENV_TABLE_INDEX, reg), t.line_); } } else { if (s.second == scope_name_list_.current_scope_->GetOwnerFunction()) { int src_reg = s.first->GetNameRegister(t.str_); assert(src_reg >= 0); if (value_count != 0) { int dst_reg = func_->AllocaNextRegister(); func_->AddInstruction(Instruction::ABCode(OpType_Move, dst_reg, src_reg), t.line_); } } else { assert(!"TODO: generate code for upvalue."); } } } else assert(!"maybe miss some term type."); }