diff --git a/src/codeobject.h b/src/codeobject.h index e90f4a49..8ee7f9ad 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -19,7 +19,7 @@ static const char* OP_NAMES[] = { struct ByteCode{ uint8_t op; int arg; - uint16_t line; + int line; uint16_t block; // the block id of this bytecode }; @@ -149,7 +149,8 @@ struct CodeObject { class Frame { private: std::vector s_data; - int ip = 0; + int ip = -1; + int next_ip = 0; public: const _Code code; PyVar _module; @@ -167,12 +168,14 @@ public: : code(code), _module(_module), f_locals(std::move(locals)) { } - inline const ByteCode& readCode() { - return code->co_code[ip++]; + inline const ByteCode& next_bytecode() { + ip = next_ip; + next_ip = ip + 1; + return code->co_code[ip]; } _Str errorSnapshot(){ - int line = code->co_code[ip-1].line; + int line = code->co_code[ip].line; return code->src->snapshot(line); } @@ -180,8 +183,8 @@ public: return s_data.size(); } - inline bool isCodeEnd() const { - return ip >= code->co_code.size(); + inline bool has_next_bytecode() const { + return next_ip < code->co_code.size(); } inline PyVar __pop(){ @@ -191,15 +194,18 @@ public: return v; } - inline PyVar __deref_pointer(VM*, PyVar); + inline void __deref(VM*, PyVar&); inline PyVar popValue(VM* vm){ - return __deref_pointer(vm, __pop()); + PyVar value = __pop(); + __deref(vm, value); + return value; } inline PyVar topValue(VM* vm){ - if(s_data.empty()) throw std::runtime_error("s_data.empty() is true"); - return __deref_pointer(vm, s_data.back()); + PyVar value = __top(); + __deref(vm, value); + return value; } inline PyVar& __top(){ @@ -208,7 +214,9 @@ public: } inline PyVar __topValueN(VM* vm, int n=-1){ - return __deref_pointer(vm, s_data[s_data.size() + n]); + PyVar value = s_data[s_data.size() + n]; + __deref(vm, value); + return value; } template @@ -217,14 +225,14 @@ public: } inline void jumpAbsolute(int i){ - this->ip = i; + next_ip = i; } void jumpAbsoluteSafe(int target){ - const ByteCode& prev = code->co_code[this->ip]; + const ByteCode& prev = code->co_code[ip]; int i = prev.block; - this->ip = target; - if(isCodeEnd()){ + next_ip = target; + if(next_ip >= code->co_code.size()){ while(i>=0){ if(code->co_blocks[i].type == FOR_LOOP) __pop(); i = code->co_blocks[i].parent; @@ -242,8 +250,14 @@ public: } pkpy::ArgList popNValuesReversed(VM* vm, int n){ + int new_size = s_data.size() - n; + if(new_size < 0) throw std::runtime_error("stackSize() < n"); pkpy::ArgList v(n); - for(int i=n-1; i>=0; i--) v._index(i) = popValue(vm); + for(int i=n-1; i>=0; i--){ + v._index(i) = std::move(s_data[new_size + i]); + __deref(vm, v._index(i)); + } + s_data.resize(new_size); return v; } diff --git a/src/compiler.h b/src/compiler.h index d4e5b264..a37932af 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -698,7 +698,7 @@ __LISTCOMP: int emitCode(Opcode opcode, int arg=-1) { int line = parser->previous.line; getCode()->co_code.push_back( - ByteCode{(uint8_t)opcode, arg, (uint16_t)line, (uint16_t)getCode()->_currBlockIndex} + ByteCode{(uint8_t)opcode, arg, line, (uint16_t)getCode()->_currBlockIndex} ); return getCode()->co_code.size() - 1; } diff --git a/src/main.cpp b/src/main.cpp index 04e599c3..58b3c02e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,7 +3,7 @@ #include "pocketpy.h" -//#define PK_DEBUG_TIME +#define PK_DEBUG_TIME //#define PK_DEBUG_THREADED struct Timer{ diff --git a/src/pointer.h b/src/pointer.h index ff532aee..197cb106 100644 --- a/src/pointer.h +++ b/src/pointer.h @@ -19,7 +19,7 @@ enum NameScope { struct NameRef : BaseRef { const std::pair<_Str, NameScope>* pair; - NameRef(const std::pair<_Str, NameScope>* pair) : pair(pair) {} + NameRef(const std::pair<_Str, NameScope>& pair) : pair(&pair) {} PyVar get(VM* vm, Frame* frame) const; void set(VM* vm, Frame* frame, PyVar val) const; diff --git a/src/vm.h b/src/vm.h index de2cc943..aeb54b4f 100644 --- a/src/vm.h +++ b/src/vm.h @@ -37,8 +37,8 @@ protected: } PyVar runFrame(Frame* frame){ - while(!frame->isCodeEnd()){ - const ByteCode& byte = frame->readCode(); + while(frame->has_next_bytecode()){ + const ByteCode& byte = frame->next_bytecode(); //printf("[%d] %s (%d)\n", frame->stackSize(), OP_NAMES[byte.op], byte.arg); //printf("%s\n", frame->code->src->getLine(byte.line).c_str()); @@ -54,18 +54,16 @@ protected: frame->push(obj); } break; case OP_LOAD_NAME_REF: { - frame->push(PyRef(NameRef( - &(frame->code->co_names[byte.arg]) - ))); + frame->push(PyRef(NameRef(frame->code->co_names[byte.arg]))); } break; case OP_STORE_NAME_REF: { const auto& p = frame->code->co_names[byte.arg]; - NameRef(&p).set(this, frame, frame->popValue(this)); + NameRef(p).set(this, frame, frame->popValue(this)); } break; case OP_BUILD_ATTR_REF: { const auto& attr = frame->code->co_names[byte.arg]; PyVar obj = frame->popValue(this); - frame->push(PyRef(AttrRef(obj, NameRef(&attr)))); + frame->push(PyRef(AttrRef(obj, NameRef(attr)))); } break; case OP_BUILD_INDEX_REF: { PyVar index = frame->popValue(this); @@ -88,10 +86,8 @@ protected: for(int i=0; iisType(_tp_ref)) { done = true; - PyVarList values(items.size()); - for(int i=0; i__deref_pointer(this, items[i]); - } + PyVarList values = items.toList(); + for(int j=i; j__deref(this, values[j]); frame->push(PyTuple(values)); break; } @@ -151,6 +147,10 @@ protected: fastCall(BINARY_SPECIAL_METHODS[byte.arg], frame->popNValuesReversed(this, 2)) ); + // pkpy::ArgList args(2); + // args._index(1) = frame->popValue(this); + // args._index(0) = frame->topValue(this); + // frame->__top() = fastCall(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); } break; case OP_BITWISE_OP: { @@ -624,7 +624,7 @@ public: template inline PyVar newObject(PyVar type, T _value) { - __checkType(type, _tp_type); + if(!type->isType(_tp_type)) UNREACHABLE(); return pkpy::make_shared>(_value, type); } @@ -678,30 +678,15 @@ public: return nullptr; } - void setAttr(PyVar& obj, const _Str& name, const PyVar& value) { - if(obj->isType(_tp_super)){ - const PyVar* root = &obj; - while(true){ - root = &UNION_GET(PyVar, *root); - if(!(*root)->isType(_tp_super)) break; - } - (*root)->attribs[name] = value; - }else{ - obj->attribs[name] = value; - } + template + void setAttr(PyObject* obj, const _Str& name, T&& value) { + while(obj->isType(_tp_super)) obj = ((Py_*)obj)->_valueT.get(); + obj->attribs[name] = value; } - void setAttr(PyVar& obj, const _Str& name, PyVar&& value) { - if(obj->isType(_tp_super)){ - const PyVar* root = &obj; - while(true){ - root = &UNION_GET(PyVar, *root); - if(!(*root)->isType(_tp_super)) break; - } - (*root)->attribs[name] = std::move(value); - }else{ - obj->attribs[name] = std::move(value); - } + template + inline void setAttr(PyVar& obj, const _Str& name, T&& value) { + setAttr(obj.get(), name, value); } void bindMethod(_Str typeName, _Str funcName, _CppFunc fn) { @@ -1093,9 +1078,8 @@ void TupleRef::del(VM* vm, Frame* frame) const{ } /***** Frame's Impl *****/ -inline PyVar Frame::__deref_pointer(VM* vm, PyVar v){ - if(v->isType(vm->_tp_ref)) return vm->PyRef_AS_C(v)->get(vm, this); - return v; +inline void Frame::__deref(VM* vm, PyVar& v){ + if(v->isType(vm->_tp_ref)) v = vm->PyRef_AS_C(v)->get(vm, this); } /***** Iterators' Impl *****/ diff --git a/test_cpp.sh b/test_cpp.sh index d79f9fd9..a0aee33f 100644 --- a/test_cpp.sh +++ b/test_cpp.sh @@ -1,4 +1,4 @@ -g++ -o pocketpy src/main.cpp --std=c++17 -pg -O1 -pthread +g++ -o pocketpy src/main.cpp --std=c++17 -pg -O1 -pthread -fno-rtti ./pocketpy tests/1.py