blueloveTH 2 лет назад
Родитель
Сommit
6452acf327
9 измененных файлов с 39 добавлено и 46 удалено
  1. 3 8
      src/ceval.h
  2. 5 1
      src/codeobject.h
  3. 6 7
      src/compiler.h
  4. 8 6
      src/expr.h
  5. 0 2
      src/gc.h
  6. 2 2
      src/obj.h
  7. 0 1
      src/opcodes.h
  8. 1 1
      src/pocketpy.h
  9. 14 18
      src/vm.h

+ 3 - 8
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();

+ 5 - 1
src/codeobject.h

@@ -60,7 +60,7 @@ struct CodeObject {
     std::set<StrName> global_names;
     std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
     std::map<StrName, int> labels;
-    std::vector<FunctionDecl> functions;
+    std::vector<FunctionDecl> 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();
+        }
     }
 };
 

+ 6 - 7
src/compiler.h

@@ -170,13 +170,13 @@ class Compiler {
     // PASS
     void exprLambda(){
         auto e = make_expr<LambdaExpr>();
-        e->func.name = "<lambda>";
+        e->decl.name = "<lambda>";
         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, "<lambda>");
+        e->decl.code = push_context(lexer->src, "<lambda>");
         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<NameExpr>(func.name, name_scope());

+ 8 - 6
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 "<lambda>"; }
 
     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);
     }
 };
 

+ 0 - 2
src/gc.h

@@ -130,8 +130,6 @@ template<> inline void _mark<Tuple>(Tuple& t){
 }
 
 template<> inline void _mark<Function>(Function& t){
-    t.code->_mark();
-    t.kwargs._mark();
     if(t._module != nullptr) OBJ_MARK(t._module);
     if(t._closure != nullptr) t._closure->_mark();
 }

+ 2 - 2
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 {

+ 0 - 1
src/opcodes.h

@@ -16,7 +16,6 @@ OPCODE(TRY_BLOCK_EXIT)
 
 OPCODE(YIELD_VALUE)
 
-OPCODE(SETUP_CLOSURE)
 OPCODE(SETUP_DECORATOR)
 
 OPCODE(BEGIN_CLASS)

+ 1 - 1
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;
     });

+ 14 - 18
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; i<co->consts.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<NameDict>(
-            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; i<kwargs.size(); i+=2){
             const Str& key = CAST(Str&, kwargs[i]);
-            if(!fn.kwargs.contains(key)){
-                TypeError(key.escape(true) + " is an invalid keyword argument for " + fn.name.str() + "()");
+            if(!fn.decl->kwargs.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();