void VM::GenerateClosure(Value *a, Instruction i) { GET_CALLINFO_AND_PROTO(); auto a_proto = proto->GetChildFunction(Instruction::GetParamBx(i)); a->type_ = ValueT_Closure; a->closure_ = state_->NewClosure(); a->closure_->SetPrototype(a_proto); // Prepare all upvalues auto new_closure = a->closure_; auto closure = call->func_->closure_; auto count = a_proto->GetUpvalueCount(); for (std::size_t i = 0; i < count; ++i) { auto upvalue_info = a_proto->GetUpvalue(i); if (upvalue_info->parent_local_) { // Transform local variable to upvalue auto reg = call->register_ + upvalue_info->register_index_; if (reg->type_ != ValueT_Upvalue) { auto upvalue = state_->NewUpvalue(); upvalue->SetValue(*reg); reg->type_ = ValueT_Upvalue; reg->upvalue_ = upvalue; new_closure->AddUpvalue(upvalue); } else { new_closure->AddUpvalue(reg->upvalue_); } } else { // Get upvalue from parent upvalue list auto upvalue = closure->GetUpvalue(upvalue_info->register_index_); new_closure->AddUpvalue(upvalue); } } }
void CodeGenerateVisitor::Visit(Chunk *chunk, void *data) { // Generate function auto func = state_->NewFunction(); func->SetBaseInfo(chunk->module_, 0); func->SetSuperior(func_); func_ = func; func_state_ = gen_state_.PushFunctionState(); chunk->block_->Accept(this, data); // Generate closure auto cl = state_->NewClosure(); cl->SetPrototype(func); // Add Env as closure upvalue cl->AddUpvalue(state_->GetGlobal(), Upvalue::Stack); // Add closure to stack state_->stack_.top_->closure_ = cl; state_->stack_.top_->type_ = ValueT_Closure; state_->stack_.top_++; }