diff --git a/src/ceval.h b/src/ceval.h index 5bdefb92..60557718 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -15,7 +15,7 @@ __NEXT_STEP:; * For example, frame->popx() returns a strong reference which may be dangerous * `Args` containing strong references is safe if it is passed to `call` or `fast_call` */ - heap._auto_collect(this); + //heap._auto_collect(this); const Bytecode& byte = frame->next_bytecode(); switch (byte.op) @@ -38,7 +38,7 @@ __NEXT_STEP:; case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); DISPATCH(); case OP_LOAD_BUILTIN_EVAL: frame->push(builtins->attr(m_eval)); DISPATCH(); case OP_LOAD_FUNCTION: { - const FunctionDecl* decl = &frame->co->func_decls[byte.arg]; + FuncDecl_ decl = frame->co->func_decls[byte.arg]; PyObject* obj = VAR(Function({decl, frame->_module, frame->_locals})); frame->push(obj); } DISPATCH(); diff --git a/src/codeobject.h b/src/codeobject.h index ab74e909..dd2682e6 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -60,7 +60,7 @@ struct CodeObject { std::set global_names; std::vector blocks = { CodeBlock{NO_BLOCK, -1} }; std::map labels; - std::vector func_decls; + std::vector func_decls; // may be.. just use a large NameDict? uint32_t perfect_locals_capacity = 2; @@ -71,8 +71,8 @@ struct CodeObject { void _mark() const { for(PyObject* v : consts) OBJ_MARK(v); for(auto& decl: func_decls){ - decl.kwargs._mark(); - decl.code->_mark(); + decl->kwargs._mark(); + decl->code->_mark(); } } }; diff --git a/src/compiler.h b/src/compiler.h index 274b63b9..81a453af 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -169,14 +169,12 @@ class Compiler { // PASS void exprLambda(){ - auto e = make_expr(); - e->decl.name = ""; - e->scope = name_scope(); + auto e = make_expr(name_scope()); if(!match(TK(":"))){ _compile_f_args(e->decl, false); consume(TK(":")); } - e->decl.code = push_context(lexer->src, ""); + e->decl->code = push_context(lexer->src, e->decl->name.str()); EXPR(false); // https://github.com/blueloveTH/pocketpy/issues/37 ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); pop_context(); @@ -754,7 +752,7 @@ class Compiler { ctx()->emit(OP_END_CLASS, BC_NOARG, BC_KEEPLINE); } - void _compile_f_args(FunctionDecl& func, bool enable_type_hints){ + void _compile_f_args(FuncDecl_ decl, bool enable_type_hints){ int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs do { if(state == 3) SyntaxError("**kwargs should be the last argument"); @@ -769,7 +767,7 @@ class Compiler { consume(TK("@id")); const Str& name = prev().str(); - if(func.has_name(name)) SyntaxError("duplicate argument name"); + if(decl->has_name(name)) SyntaxError("duplicate argument name"); // eat type hints if(enable_type_hints && match(TK(":"))) consume(TK("@id")); @@ -778,16 +776,16 @@ class Compiler { switch (state) { - case 0: func.args.push_back(name); break; - case 1: func.starred_arg = name; state+=1; break; + case 0: decl->args.push_back(name); break; + case 1: decl->starred_arg = name; state+=1; break; case 2: { consume(TK("=")); PyObject* value = read_literal(); if(value == nullptr){ SyntaxError(Str("expect a literal, not ") + TK_STR(curr().type)); } - func.kwargs.set(name, value); - func.kwargs_order.push_back(name); + decl->kwargs.set(name, value); + decl->kwargs_order.push_back(name); } break; case 3: SyntaxError("**kwargs is not supported yet"); break; } @@ -796,38 +794,38 @@ class Compiler { void compile_function(){ // TODO: bug, if there are multiple decorators, will cause error - FunctionDecl func; + FuncDecl_ decl = make_sp(); StrName obj_name; consume(TK("@id")); - func.name = prev().str(); + decl->name = prev().str(); if(!ctx()->is_compiling_class && match(TK("::"))){ consume(TK("@id")); - obj_name = func.name; - func.name = prev().str(); + obj_name = decl->name; + decl->name = prev().str(); } consume(TK("(")); if (!match(TK(")"))) { - _compile_f_args(func, true); + _compile_f_args(decl, true); consume(TK(")")); } if(match(TK("->"))){ if(!match(TK("None"))) consume(TK("@id")); } - func.code = push_context(lexer->src, func.name.str()); + decl->code = push_context(lexer->src, decl->name.str()); compile_block_body(); pop_context(); - ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(func), prev().line); + ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line); if(!ctx()->is_compiling_class){ if(obj_name.empty()){ - auto e = make_expr(func.name, name_scope()); + auto e = make_expr(decl->name, name_scope()); e->emit_store(ctx()); } else { ctx()->emit(OP_LOAD_NAME, ctx()->add_name(obj_name), prev().line); - int index = ctx()->add_name(func.name); + int index = ctx()->add_name(decl->name); ctx()->emit(OP_STORE_ATTR, index, prev().line); } }else{ - ctx()->emit(OP_STORE_CLASS_ATTR, ctx()->add_name(func.name), BC_KEEPLINE); + ctx()->emit(OP_STORE_CLASS_ATTR, ctx()->add_name(decl->name), BC_KEEPLINE); } } diff --git a/src/expr.h b/src/expr.h index 463c2aff..21df0215 100644 --- a/src/expr.h +++ b/src/expr.h @@ -96,7 +96,7 @@ struct CodeEmitContext{ return co->consts.size() - 1; } - int add_func_decl(FunctionDecl decl){ + int add_func_decl(FuncDecl_ decl){ co->func_decls.push_back(decl); return co->func_decls.size() - 1; } @@ -477,9 +477,15 @@ struct SetCompExpr: CompExpr{ }; struct LambdaExpr: Expr{ - FunctionDecl decl; + FuncDecl_ decl; NameScope scope; Str str() const override { return ""; } + + LambdaExpr(NameScope scope){ + this->decl = make_sp(); + this->decl->name = ""; + this->scope = scope; + } void emit(CodeEmitContext* ctx) override { int index = ctx->add_func_decl(decl); diff --git a/src/obj.h b/src/obj.h index 3dd46322..372b69ae 100644 --- a/src/obj.h +++ b/src/obj.h @@ -24,7 +24,7 @@ struct NativeFunc { PyObject* operator()(VM* vm, Args& args) const; }; -struct FunctionDecl { +struct FuncDecl { StrName name; CodeObject_ code; std::vector args; @@ -40,8 +40,10 @@ struct FunctionDecl { } }; +using FuncDecl_ = shared_ptr; + struct Function{ - const FunctionDecl* decl; + FuncDecl_ decl; PyObject* _module; NameDict_ _closure; }; diff --git a/src/vm.h b/src/vm.h index f40c1000..846b05f6 100644 --- a/src/vm.h +++ b/src/vm.h @@ -626,8 +626,8 @@ inline Str VM::disassemble(CodeObject_ co){ ss << '\n' << consts.str() << '\n' << names.str(); for(auto& decl: co->func_decls){ - ss << "\n\n" << "Disassembly of " << decl.name.str() << ":\n"; - ss << disassemble(decl.code); + ss << "\n\n" << "Disassembly of " << decl->name.str() << ":\n"; + ss << disassemble(decl->code); } return Str(ss.str()); }