From 6452acf3275e9fee12034ee2f2f46802c6e88e33 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Wed, 5 Apr 2023 13:57:40 +0800 Subject: [PATCH] up --- src/ceval.h | 11 +++-------- src/codeobject.h | 6 +++++- src/compiler.h | 13 ++++++------- src/expr.h | 14 ++++++++------ src/gc.h | 2 -- src/obj.h | 4 ++-- src/opcodes.h | 1 - src/pocketpy.h | 2 +- src/vm.h | 32 ++++++++++++++------------------ 9 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index acfcbc70..5bdefb92 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -38,10 +38,9 @@ __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: { - PyObject* obj = frame->co->consts[byte.arg]; - Function f = CAST(Function, obj); // copy it! - f._module = frame->_module; // setup module - frame->push(VAR(std::move(f))); + const FunctionDecl* decl = &frame->co->func_decls[byte.arg]; + PyObject* obj = VAR(Function({decl, frame->_module, frame->_locals})); + frame->push(obj); } DISPATCH(); /*****************************************/ case OP_LOAD_NAME: { @@ -312,10 +311,6 @@ __NEXT_STEP:; /*****************************************/ /*****************************************/ // case OP_SETUP_DECORATOR: DISPATCH(); - // case OP_SETUP_CLOSURE: { - // Function& f = CAST(Function&, frame->top()); // reference - // f._closure = frame->_locals; - // } DISPATCH(); // case OP_BEGIN_CLASS: { // StrName name = frame->co->names[byte.arg]; // PyObject* clsBase = frame->popx(); diff --git a/src/codeobject.h b/src/codeobject.h index c390aaf3..ab74e909 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 functions; + std::vector func_decls; // may be.. just use a large NameDict? uint32_t perfect_locals_capacity = 2; @@ -70,6 +70,10 @@ struct CodeObject { void _mark() const { for(PyObject* v : consts) OBJ_MARK(v); + for(auto& decl: func_decls){ + decl.kwargs._mark(); + decl.code->_mark(); + } } }; diff --git a/src/compiler.h b/src/compiler.h index 40c70d6f..274b63b9 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -170,13 +170,13 @@ class Compiler { // PASS void exprLambda(){ auto e = make_expr(); - e->func.name = ""; + e->decl.name = ""; e->scope = name_scope(); if(!match(TK(":"))){ - _compile_f_args(e->func, false); + _compile_f_args(e->decl, false); consume(TK(":")); } - e->func.code = push_context(lexer->src, ""); + e->decl.code = push_context(lexer->src, ""); EXPR(false); // https://github.com/blueloveTH/pocketpy/issues/37 ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); pop_context(); @@ -754,7 +754,7 @@ class Compiler { ctx()->emit(OP_END_CLASS, BC_NOARG, BC_KEEPLINE); } - void _compile_f_args(Function& func, bool enable_type_hints){ + void _compile_f_args(FunctionDecl& func, 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"); @@ -796,7 +796,7 @@ class Compiler { void compile_function(){ // TODO: bug, if there are multiple decorators, will cause error - Function func; + FunctionDecl func; StrName obj_name; consume(TK("@id")); func.name = prev().str(); @@ -816,8 +816,7 @@ class Compiler { func.code = push_context(lexer->src, func.name.str()); compile_block_body(); pop_context(); - ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_const(VAR(func)), prev().line); - if(name_scope() == NAME_LOCAL) ctx()->emit(OP_SETUP_CLOSURE, BC_NOARG, prev().line); + ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(func), prev().line); if(!ctx()->is_compiling_class){ if(obj_name.empty()){ auto e = make_expr(func.name, name_scope()); diff --git a/src/expr.h b/src/expr.h index 4d2354f0..463c2aff 100644 --- a/src/expr.h +++ b/src/expr.h @@ -95,6 +95,11 @@ struct CodeEmitContext{ co->consts.push_back(v); return co->consts.size() - 1; } + + int add_func_decl(FunctionDecl decl){ + co->func_decls.push_back(decl); + return co->func_decls.size() - 1; + } }; // PASS @@ -472,16 +477,13 @@ struct SetCompExpr: CompExpr{ }; struct LambdaExpr: Expr{ - Function func; + FunctionDecl decl; NameScope scope; Str str() const override { return ""; } void emit(CodeEmitContext* ctx) override { - VM* vm = ctx->vm; - ctx->emit(OP_LOAD_FUNCTION, ctx->add_const(VAR(func)), line); - if(scope == NAME_LOCAL){ - ctx->emit(OP_SETUP_CLOSURE, BC_NOARG, BC_KEEPLINE); - } + int index = ctx->add_func_decl(decl); + ctx->emit(OP_LOAD_FUNCTION, index, line); } }; diff --git a/src/gc.h b/src/gc.h index 7ce845e6..89286c5d 100644 --- a/src/gc.h +++ b/src/gc.h @@ -130,8 +130,6 @@ template<> inline void _mark(Tuple& t){ } template<> inline void _mark(Function& t){ - t.code->_mark(); - t.kwargs._mark(); if(t._module != nullptr) OBJ_MARK(t._module); if(t._closure != nullptr) t._closure->_mark(); } diff --git a/src/obj.h b/src/obj.h index 7d64a098..3dd46322 100644 --- a/src/obj.h +++ b/src/obj.h @@ -42,8 +42,8 @@ struct FunctionDecl { struct Function{ const FunctionDecl* decl; - PyObject* _module = nullptr; - NameDict_ _closure = nullptr; + PyObject* _module; + NameDict_ _closure; }; struct BoundMethod { diff --git a/src/opcodes.h b/src/opcodes.h index ffd63177..46a81360 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -16,7 +16,6 @@ OPCODE(TRY_BLOCK_EXIT) OPCODE(YIELD_VALUE) -OPCODE(SETUP_CLOSURE) OPCODE(SETUP_DECORATOR) OPCODE(BEGIN_CLASS) diff --git a/src/pocketpy.h b/src/pocketpy.h index 938e92fd..58b75418 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -627,7 +627,7 @@ inline void add_module_dis(VM* vm){ vm->bind_func<1>(mod, "dis", [](VM* vm, Args& args) { PyObject* f = args[0]; if(is_type(f, vm->tp_bound_method)) f = CAST(BoundMethod, args[0]).method; - CodeObject_ code = CAST(Function, f).code; + CodeObject_ code = CAST(Function&, f).decl->code; (*vm->_stdout) << vm->disassemble(code); return vm->None; }); diff --git a/src/vm.h b/src/vm.h index f649d3e4..f40c1000 100644 --- a/src/vm.h +++ b/src/vm.h @@ -625,13 +625,9 @@ inline Str VM::disassemble(CodeObject_ co){ names << CAST(Str, asRepr(VAR(list))); ss << '\n' << consts.str() << '\n' << names.str(); - for(int i=0; iconsts.size(); i++){ - PyObject* obj = co->consts[i]; - if(is_type(obj, tp_function)){ - const auto& f = CAST(Function&, obj); - ss << "\n\n" << "Disassembly of " << f.name.str() << ":\n"; - ss << disassemble(f.code); - } + for(auto& decl: co->func_decls){ + ss << "\n\n" << "Disassembly of " << decl.name.str() << ":\n"; + ss << disassemble(decl.code); } return Str(ss.str()); } @@ -718,13 +714,13 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo } else if(is_type(callable, tp_function)){ const Function& fn = CAST(Function&, callable); NameDict_ locals = make_sp( - fn.code->perfect_locals_capacity, + fn.decl->code->perfect_locals_capacity, kLocalsLoadFactor, - fn.code->perfect_hash_seed + fn.decl->code->perfect_hash_seed ); int i = 0; - for(StrName name : fn.args){ + for(StrName name : fn.decl->args){ if(i < args.size()){ locals->set(name, args[i++]); continue; @@ -732,14 +728,14 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo TypeError("missing positional argument " + name.str().escape(true)); } - locals->update(fn.kwargs); + locals->update(fn.decl->kwargs); - if(!fn.starred_arg.empty()){ + if(!fn.decl->starred_arg.empty()){ List vargs; // handle *args while(i < args.size()) vargs.push_back(args[i++]); - locals->set(fn.starred_arg, VAR(Tuple(std::move(vargs)))); + locals->set(fn.decl->starred_arg, VAR(Tuple(std::move(vargs)))); }else{ - for(StrName key : fn.kwargs_order){ + for(StrName key : fn.decl->kwargs_order){ if(i < args.size()){ locals->set(key, args[i++]); }else{ @@ -751,14 +747,14 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo for(int i=0; ikwargs.contains(key)){ + TypeError(key.escape(true) + " is an invalid keyword argument for " + fn.decl->name.str() + "()"); } locals->set(key, kwargs[i+1]); } PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module; - auto _frame = _new_frame(fn.code, _module, locals, fn._closure); - if(fn.code->is_generator) return PyIter(Generator(this, std::move(_frame))); + auto _frame = _new_frame(fn.decl->code, _module, locals, fn._closure); + if(fn.decl->code->is_generator) return PyIter(Generator(this, std::move(_frame))); callstack.push(std::move(_frame)); if(opCall) return _py_op_call; return _exec();