blueloveTH 2 年之前
父節點
當前提交
d1f5d31849
共有 5 個文件被更改,包括 181 次插入180 次删除
  1. 117 103
      src/ceval.h
  2. 10 1
      src/expr.h
  3. 38 38
      src/opcodes.h
  4. 1 1
      src/str.h
  5. 15 37
      src/vm.h

+ 117 - 103
src/ceval.h

@@ -13,19 +13,28 @@ inline PyObject* VM::run_frame(Frame* frame){
         switch (byte.op)
         {
         case OP_NO_OP: continue;
-        case OP_SETUP_DECORATOR: continue;
+        /*****************************************/
+        case OP_POP_TOP: frame->pop(); continue;
+        case OP_DUP_TOP: frame->push(frame->top()); continue;
+        case OP_ROT_TWO: std::swap(frame->top(), frame->top_1()); continue;
+        case OP_PRINT_EXPR: {
+            PyObject* obj = frame->top();  // use top() here to avoid accidental gc
+            if(obj != None) *_stdout << CAST(Str, asRepr(obj)) << '\n';
+            frame->pop();
+        } continue;
+        /*****************************************/
         case OP_LOAD_CONST: frame->push(frame->co->consts[byte.arg]); continue;
+        case OP_LOAD_NONE: frame->push(None); continue;
+        case OP_LOAD_TRUE: frame->push(True); continue;
+        case OP_LOAD_FALSE: frame->push(False); continue;
+        case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); continue;
+        case OP_LOAD_BUILTINS_EVAL: frame->push(builtins->attr(m_eval)); continue;
         case OP_LOAD_FUNCTION: {
             PyObject* obj = frame->co->consts[byte.arg];
-            Function f = CAST(Function, obj);  // copy
-            f._module = frame->_module;
-            frame->push(VAR(f));
-        } continue;
-        case OP_SETUP_CLOSURE: {
-            Function& f = CAST(Function&, frame->top());    // reference
-            f._closure = frame->_locals;
+            Function f = CAST(Function, obj);   // copy it!
+            f._module = frame->_module;         // setup module
+            frame->push(VAR(std::move(f)));
         } continue;
-        case OP_ROT_TWO: ::std::swap(frame->top(), frame->top_1()); continue;
         /*****************************************/
         case OP_LOAD_NAME: {
             StrName name = frame->co->names[byte.arg];
@@ -116,9 +125,9 @@ inline PyObject* VM::run_frame(Frame* frame){
             PyObject* stop = frame->popx();
             PyObject* start = frame->popx();
             Slice s;
-            if(start != None) { s.start = CAST(int, start);}
-            if(stop != None) { s.stop = CAST(int, stop);}
-            if(step != None) { s.step = CAST(int, step);}
+            if(start != None) s.start = CAST(int, start);
+            if(stop != None) s.stop = CAST(int, stop);
+            if(step != None) s.step = CAST(int, step);
             frame->push(VAR(s));
         } continue;
         case OP_BUILD_TUPLE: {
@@ -132,7 +141,99 @@ inline PyObject* VM::run_frame(Frame* frame){
             frame->push(VAR(ss.str()));
         } continue;
         /*****************************************/
-        case OP_LOAD_EVAL_FN: frame->push(builtins->attr(m_eval)); continue;
+        case OP_BINARY_OP: {
+            Args args(2);
+            args[1] = frame->popx();    // lhs
+            args[0] = frame->top();     // rhs
+            frame->top() = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args));
+        } continue;
+        case OP_COMPARE_OP: {
+            Args args(2);
+            args[1] = frame->popx();    // lhs
+            args[0] = frame->top();     // rhs
+            frame->top() = fast_call(COMPARE_SPECIAL_METHODS[byte.arg], std::move(args));
+        } continue;
+        case OP_BITWISE_OP: {
+            Args args(2);
+            args[1] = frame->popx();    // lhs
+            args[0] = frame->top();     // rhs
+            frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args));
+        } continue;
+        case OP_IS_OP: {
+            PyObject* rhs = frame->popx();
+            PyObject* lhs = frame->top();
+            bool ret_c = lhs == rhs;
+            if(byte.arg == 1) ret_c = !ret_c;
+            frame->top() = VAR(ret_c);
+        } continue;
+        case OP_CONTAINS_OP: {
+            Args args(2);
+            args[0] = frame->popx();
+            args[1] = frame->top();
+            PyObject* ret = fast_call(__contains__, std::move(args));
+            bool ret_c = CAST(bool, ret);
+            if(byte.arg == 1) ret_c = !ret_c;
+            frame->top() = VAR(ret_c);
+        } continue;
+        /*****************************************/
+        case OP_JUMP_ABSOLUTE: frame->jump_abs(byte.arg); continue;
+        case OP_SAFE_JUMP_ABSOLUTE: frame->jump_abs_safe(byte.arg); continue;
+        case OP_POP_JUMP_IF_FALSE:
+            if(!asBool(frame->popx())) frame->jump_abs(byte.arg);
+            continue;
+        case OP_JUMP_IF_TRUE_OR_POP:
+            if(asBool(frame->top()) == true) frame->jump_abs(byte.arg);
+            else frame->pop();
+            continue;
+        case OP_JUMP_IF_FALSE_OR_POP:
+            if(asBool(frame->top()) == false) frame->jump_abs(byte.arg);
+            else frame->pop();
+            continue;
+        case OP_LOOP_CONTINUE: {
+            int target = frame->co->blocks[byte.block].start;
+            frame->jump_abs(target);
+        } continue;
+        case OP_LOOP_BREAK: {
+            int target = frame->co->blocks[byte.block].end;
+            frame->jump_abs_safe(target);
+        } continue;
+        case OP_GOTO: {
+            StrName label = frame->co->names[byte.arg];
+            auto it = frame->co->labels.find(label);
+            if(it == frame->co->labels.end()) _error("KeyError", "label " + label.str().escape(true) + " not found");
+            frame->jump_abs_safe(it->second);
+        } continue;
+        /*****************************************/
+        // TODO: examine this later
+        case OP_CALL: case OP_CALL_UNPACK: {
+            Args args = frame->popx_n_reversed(byte.arg);
+            if(byte.op == OP_CALL_UNPACK) unpack_args(args);
+            PyObject* callable = frame->popx();
+            PyObject* ret = call(callable, std::move(args), no_arg(), true);
+            if(ret == _py_op_call) return ret;
+            frame->push(std::move(ret));
+        } continue;
+        case OP_CALL_KWARGS: case OP_CALL_KWARGS_UNPACK: {
+            int ARGC = byte.arg & 0xFFFF;
+            int KWARGC = (byte.arg >> 16) & 0xFFFF;
+            Args kwargs = frame->popx_n_reversed(KWARGC*2);
+            Args args = frame->popx_n_reversed(ARGC);
+            if(byte.op == OP_CALL_KWARGS_UNPACK) unpack_args(args);
+            PyObject* callable = frame->popx();
+            PyObject* ret = call(callable, std::move(args), kwargs, true);
+            if(ret == _py_op_call) return ret;
+            frame->push(std::move(ret));
+        } continue;
+        case OP_RETURN_VALUE: return frame->popx();
+        /*****************************************/
+
+        /*****************************************/
+        case OP_SETUP_DECORATOR: continue;
+
+        case OP_SETUP_CLOSURE: {
+            Function& f = CAST(Function&, frame->top());    // reference
+            f._closure = frame->_locals;
+        } continue;
         case OP_BEGIN_CLASS: {
             StrName name = frame->co->names[byte.arg];
             PyObject* clsBase = frame->popx();
@@ -151,43 +252,7 @@ inline PyObject* VM::run_frame(Frame* frame){
             PyObject* cls = frame->top();
             cls->attr().set(name, obj);
         } continue;
-        case OP_RETURN_VALUE: return frame->popx();
-        case OP_PRINT_EXPR: {
-            PyObject* expr = frame->top();  // use top() here to avoid accidental gc
-            if(expr != None) *_stdout << CAST(Str, asRepr(expr)) << '\n';
-            frame->pop();
-        } continue;
-        case OP_POP_TOP: frame->_pop(); continue;
-        case OP_BINARY_OP: {
-            Args args(2);
-            args[1] = frame->pop_value(this);
-            args[0] = frame->top_value(this);
-            frame->top() = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args));
-        } continue;
-        case OP_BITWISE_OP: {
-            Args args(2);
-            args[1] = frame->pop_value(this);
-            args[0] = frame->top_value(this);
-            frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args));
-        } continue;
-        case OP_COMPARE_OP: {
-            Args args(2);
-            args[1] = frame->pop_value(this);
-            args[0] = frame->top_value(this);
-            frame->top() = fast_call(CMP_SPECIAL_METHODS[byte.arg], std::move(args));
-        } continue;
-        case OP_IS_OP: {
-            PyObject* rhs = frame->pop_value(this);
-            bool ret_c = rhs == frame->top_value(this);
-            if(byte.arg == 1) ret_c = !ret_c;
-            frame->top() = VAR(ret_c);
-        } continue;
-        case OP_CONTAINS_OP: {
-            PyObject* rhs = frame->pop_value(this);
-            bool ret_c = CAST(bool, call(rhs, __contains__, Args{frame->pop_value(this)}));
-            if(byte.arg == 1) ret_c = !ret_c;
-            frame->push(VAR(ret_c));
-        } continue;
+        
         case OP_UNARY_NEGATIVE:
             frame->top() = num_negated(frame->top_value(this));
             continue;
@@ -196,13 +261,7 @@ inline PyObject* VM::run_frame(Frame* frame){
             PyObject* obj_bool = asBool(obj);
             frame->push(VAR(!_CAST(bool, obj_bool)));
         } continue;
-        case OP_POP_JUMP_IF_FALSE:
-            if(!_CAST(bool, asBool(frame->pop_value(this)))) frame->jump_abs(byte.arg);
-            continue;
-        case OP_LOAD_NONE: frame->push(None); continue;
-        case OP_LOAD_TRUE: frame->push(True); continue;
-        case OP_LOAD_FALSE: frame->push(False); continue;
-        case OP_LOAD_ELLIPSIS: frame->push(Ellipsis); continue;
+
         case OP_ASSERT: {
             PyObject* _msg = frame->pop_value(this);
             Str msg = CAST(Str, asStr(_msg));
@@ -236,7 +295,6 @@ inline PyObject* VM::run_frame(Frame* frame){
             PyObject* obj = frame->pop_value(this);
             call(frame->top_1(), "add", Args{obj});
         } continue;
-        case OP_DUP_TOP: frame->push(frame->top()); continue;
         case OP_UNARY_STAR: {
             if(byte.arg > 0){   // rvalue
                 frame->top() = VAR(StarWrapper(frame->top_value(this), true));
@@ -245,33 +303,6 @@ inline PyObject* VM::run_frame(Frame* frame){
                 frame->top() = VAR(StarWrapper(frame->top(), false));
             }
         } continue;
-        case OP_CALL_KWARGS_UNPACK: case OP_CALL_KWARGS: {
-            int ARGC = byte.arg & 0xFFFF;
-            int KWARGC = (byte.arg >> 16) & 0xFFFF;
-            Args kwargs = frame->pop_n_values_reversed(this, KWARGC*2);
-            Args args = frame->pop_n_values_reversed(this, ARGC);
-            if(byte.op == OP_CALL_KWARGS_UNPACK) unpack_args(args);
-            PyObject* callable = frame->pop_value(this);
-            PyObject* ret = call(callable, std::move(args), kwargs, true);
-            if(ret == _py_op_call) return ret;
-            frame->push(std::move(ret));
-        } continue;
-        case OP_CALL_UNPACK: case OP_CALL: {
-            Args args = frame->pop_n_values_reversed(this, byte.arg);
-            if(byte.op == OP_CALL_UNPACK) unpack_args(args);
-            PyObject* callable = frame->pop_value(this);
-            PyObject* ret = call(callable, std::move(args), no_arg(), true);
-            if(ret == _py_op_call) return ret;
-            frame->push(std::move(ret));
-        } continue;
-        case OP_JUMP_ABSOLUTE: frame->jump_abs(byte.arg); continue;
-        case OP_SAFE_JUMP_ABSOLUTE: frame->jump_abs_safe(byte.arg); continue;
-        case OP_GOTO: {
-            StrName label = frame->co->names[byte.arg].first;
-            auto it = frame->co->labels.find(label);
-            if(it == frame->co->labels.end()) _error("KeyError", "label " + label.str().escape(true) + " not found");
-            frame->jump_abs_safe(it->second);
-        } continue;
         case OP_GET_ITER: {
             PyObject* obj = frame->pop_value(this);
             PyObject* iter = asIter(obj);
@@ -289,24 +320,7 @@ inline PyObject* VM::run_frame(Frame* frame){
                 frame->jump_abs_safe(blockEnd);
             }
         } continue;
-        case OP_LOOP_CONTINUE: {
-            int blockStart = frame->co->blocks[byte.block].start;
-            frame->jump_abs(blockStart);
-        } continue;
-        case OP_LOOP_BREAK: {
-            int blockEnd = frame->co->blocks[byte.block].end;
-            frame->jump_abs_safe(blockEnd);
-        } continue;
-        case OP_JUMP_IF_FALSE_OR_POP: {
-            PyObject* expr = frame->top_value(this);
-            if(asBool(expr)==False) frame->jump_abs(byte.arg);
-            else frame->pop_value(this);
-        } continue;
-        case OP_JUMP_IF_TRUE_OR_POP: {
-            PyObject* expr = frame->top_value(this);
-            if(asBool(expr)==True) frame->jump_abs(byte.arg);
-            else frame->pop_value(this);
-        } continue;
+
 
         case OP_IMPORT_NAME: {
             StrName name = frame->co->names[byte.arg].first;

+ 10 - 1
src/expr.h

@@ -425,7 +425,7 @@ struct FStringExpr: Expr{
                 ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
                 size++;
             }
-            ctx->emit(OP_LOAD_EVAL_FN, BC_NOARG, line);
+            ctx->emit(OP_LOAD_BUILTINS_EVAL, BC_NOARG, line);
             ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(m[1].str())), line);
             ctx->emit(OP_CALL, 1, line);
             size++;
@@ -514,7 +514,16 @@ struct CallExpr: Expr{
     }
 
     void emit(CodeEmitContext* ctx) override {
+        VM* vm = ctx->vm;
         callable->emit(ctx);
+        // emit args
+        for(auto& item: args) item->emit(ctx);
+        // emit kwargs
+        for(auto& item: kwargs){
+            // TODO: optimize this
+            ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(item.first)), line);
+            item.second->emit(ctx);
+        }
         int KWARGC = (int)kwargs.size();
         int ARGC = (int)args.size();
         if(KWARGC > 0){

+ 38 - 38
src/opcodes.h

@@ -1,21 +1,5 @@
 #ifdef OPCODE
 
-OPCODE(NO_OP)
-OPCODE(POP_TOP)
-OPCODE(DUP_TOP)
-OPCODE(CALL)
-OPCODE(CALL_UNPACK)
-OPCODE(CALL_KWARGS)
-OPCODE(CALL_KWARGS_UNPACK)
-OPCODE(RETURN_VALUE)
-OPCODE(ROT_TWO)
-
-OPCODE(BINARY_OP)
-OPCODE(COMPARE_OP)
-OPCODE(BITWISE_OP)
-OPCODE(IS_OP)
-OPCODE(CONTAINS_OP)
-
 OPCODE(UNARY_NEGATIVE)
 OPCODE(UNARY_NOT)
 OPCODE(UNARY_STAR)
@@ -23,32 +7,14 @@ OPCODE(UNARY_STAR)
 OPCODE(LIST_APPEND)
 OPCODE(MAP_ADD)
 OPCODE(SET_ADD)
+
 OPCODE(IMPORT_NAME)
-OPCODE(PRINT_EXPR)
 
 OPCODE(GET_ITER)
 OPCODE(FOR_ITER)
 
 OPCODE(WITH_ENTER)
 OPCODE(WITH_EXIT)
-OPCODE(LOOP_BREAK)
-OPCODE(LOOP_CONTINUE)
-
-OPCODE(POP_JUMP_IF_FALSE)
-OPCODE(JUMP_ABSOLUTE)
-OPCODE(SAFE_JUMP_ABSOLUTE)
-OPCODE(JUMP_IF_TRUE_OR_POP)
-OPCODE(JUMP_IF_FALSE_OR_POP)
-
-OPCODE(GOTO)
-
-OPCODE(LOAD_CONST)
-OPCODE(LOAD_NONE)
-OPCODE(LOAD_TRUE)
-OPCODE(LOAD_FALSE)
-OPCODE(LOAD_EVAL_FN)
-OPCODE(LOAD_FUNCTION)
-OPCODE(LOAD_ELLIPSIS)
 
 OPCODE(ASSERT)
 OPCODE(EXCEPTION_MATCH)
@@ -62,9 +28,6 @@ OPCODE(TRY_BLOCK_EXIT)
 
 OPCODE(YIELD_VALUE)
 
-OPCODE(FAST_INDEX)      // a[x]
-OPCODE(FAST_INDEX_REF)       // a[x]
-
 OPCODE(SETUP_CLOSURE)
 OPCODE(SETUP_DECORATOR)
 OPCODE(STORE_ALL_NAMES)
@@ -73,6 +36,22 @@ OPCODE(BEGIN_CLASS)
 OPCODE(END_CLASS)
 OPCODE(STORE_CLASS_ATTR)
 
+
+/**************************/
+OPCODE(NO_OP)
+/**************************/
+OPCODE(POP_TOP)
+OPCODE(DUP_TOP)
+OPCODE(ROT_TWO)
+OPCODE(PRINT_EXPR)
+/**************************/
+OPCODE(LOAD_CONST)
+OPCODE(LOAD_NONE)
+OPCODE(LOAD_TRUE)
+OPCODE(LOAD_FALSE)
+OPCODE(LOAD_ELLIPSIS)
+OPCODE(LOAD_BUILTINS_EVAL)
+OPCODE(LOAD_FUNCTION)
 /**************************/
 OPCODE(LOAD_NAME)
 OPCODE(LOAD_ATTR)
@@ -95,5 +74,26 @@ OPCODE(BUILD_SLICE)
 OPCODE(BUILD_TUPLE)
 OPCODE(BUILD_STRING)
 /**************************/
+OPCODE(BINARY_OP)
+OPCODE(COMPARE_OP)
+OPCODE(BITWISE_OP)
+OPCODE(IS_OP)
+OPCODE(CONTAINS_OP)
+/**************************/
+OPCODE(JUMP_ABSOLUTE)
+OPCODE(SAFE_JUMP_ABSOLUTE)
+OPCODE(POP_JUMP_IF_FALSE)
+OPCODE(JUMP_IF_TRUE_OR_POP)
+OPCODE(JUMP_IF_FALSE_OR_POP)
+OPCODE(LOOP_CONTINUE)
+OPCODE(LOOP_BREAK)
+OPCODE(GOTO)
+/**************************/
+OPCODE(CALL)
+OPCODE(CALL_UNPACK)
+OPCODE(CALL_KWARGS)
+OPCODE(CALL_KWARGS_UNPACK)
+OPCODE(RETURN_VALUE)
+/**************************/
 
 #endif

+ 1 - 1
src/str.h

@@ -214,7 +214,7 @@ const StrName m_set = StrName::get("set");
 const StrName __enter__ = StrName::get("__enter__");
 const StrName __exit__ = StrName::get("__exit__");
 
-const StrName CMP_SPECIAL_METHODS[] = {
+const StrName COMPARE_SPECIAL_METHODS[] = {
     StrName::get("__lt__"), StrName::get("__le__"), StrName::get("__eq__"),
     StrName::get("__ne__"), StrName::get("__gt__"), StrName::get("__ge__")
 };

+ 15 - 37
src/vm.h

@@ -320,7 +320,7 @@ public:
     CodeObject_ compile(Str source, Str filename, CompileMode mode);
     PyObject* num_negated(PyObject* obj);
     f64 num_to_float(PyObject* obj);
-    PyObject* asBool(PyObject* obj);
+    bool asBool(PyObject* obj);
     i64 hash(PyObject* obj);
     PyObject* asRepr(PyObject* obj);
     PyObject* new_module(StrName name);
@@ -357,30 +357,13 @@ inline void CodeObject::optimize(VM* vm){
     perfect_locals_capacity = find_next_capacity(base_n);
     perfect_hash_seed = find_perfect_hash_seed(perfect_locals_capacity, keys);
 
-    // for(int i=1; i<codes.size(); i++){
-    //     if(codes[i].op == OP_UNARY_NEGATIVE && codes[i-1].op == OP_LOAD_CONST){
-    //         codes[i].op = OP_NO_OP;
-    //         int pos = codes[i-1].arg;
-    //         consts[pos] = vm->num_negated(consts[pos]);
-    //     }
-
-    //     if(i>=2 && codes[i].op == OP_BUILD_INDEX){
-    //         const Bytecode& a = codes[i-1];
-    //         const Bytecode& x = codes[i-2];
-    //         if(codes[i].arg == 1){
-    //             if(a.op == OP_LOAD_NAME && x.op == OP_LOAD_NAME){
-    //                 codes[i].op = OP_FAST_INDEX;
-    //             }else continue;
-    //         }else{
-    //             if(a.op == OP_LOAD_NAME_REF && x.op == OP_LOAD_NAME_REF){
-    //                 codes[i].op = OP_FAST_INDEX_REF;
-    //             }else continue;
-    //         }
-    //         codes[i].arg = (a.arg << 16) | x.arg;
-    //         codes[i-1].op = OP_NO_OP;
-    //         codes[i-2].op = OP_NO_OP;
-    //     }
-    // }
+    for(int i=1; i<codes.size(); i++){
+        if(codes[i].op == OP_UNARY_NEGATIVE && codes[i-1].op == OP_LOAD_CONST){
+            codes[i].op = OP_NO_OP;
+            int pos = codes[i-1].arg;
+            consts[pos] = vm->num_negated(consts[pos]);
+        }
+    }
 
     // pre-compute sn in co_consts
     for(int i=0; i<consts.size(); i++){
@@ -525,17 +508,17 @@ inline f64 VM::num_to_float(PyObject* obj){
     return 0;
 }
 
-inline PyObject* VM::asBool(PyObject* obj){
-    if(is_type(obj, tp_bool)) return obj;
-    if(obj == None) return False;
-    if(is_type(obj, tp_int)) return VAR(CAST(i64, obj) != 0);
-    if(is_type(obj, tp_float)) return VAR(CAST(f64, obj) != 0.0);
+inline bool VM::asBool(PyObject* obj){
+    if(is_type(obj, tp_bool)) return obj == True;
+    if(obj == None) return false;
+    if(is_type(obj, tp_int)) return CAST(i64, obj) != 0;
+    if(is_type(obj, tp_float)) return CAST(f64, obj) != 0.0;
     PyObject* len_f = getattr(obj, __len__, false, true);
     if(len_f != nullptr){
         PyObject* ret = call(len_f, no_arg());
-        return VAR(CAST(i64, ret) > 0);
+        return CAST(i64, ret) > 0;
     }
-    return True;
+    return true;
 }
 
 inline i64 VM::hash(PyObject* obj){
@@ -617,11 +600,6 @@ inline Str VM::disassemble(CodeObject_ co){
         if(byte.op == OP_LOAD_NAME_REF || byte.op == OP_LOAD_NAME || byte.op == OP_RAISE || byte.op == OP_STORE_NAME){
             argStr += " (" + co->names[byte.arg].first.str().escape(true) + ")";
         }
-        if(byte.op == OP_FAST_INDEX || byte.op == OP_FAST_INDEX_REF){
-            auto& a = co->names[byte.arg & 0xFFFF];
-            auto& x = co->names[(byte.arg >> 16) & 0xFFFF];
-            argStr += " (" + a.first.str() + '[' + x.first.str() + "])";
-        }
         ss << argStr;
         // ss << pad(argStr, 20);      // may overflow
         // ss << co->blocks[byte.block].to_string();