From f752acdfc880d4da8a7a652f049b7dcf107c1ab2 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 29 Apr 2024 11:57:21 +0800 Subject: [PATCH] break change of `m__next__` --- include/pocketpy/frame.h | 4 ++++ include/pocketpy/vm.h | 6 +++--- src/array2d.cpp | 15 +++----------- src/ceval.cpp | 39 +++++++++++++++++------------------ src/collections.cpp | 14 ++++++------- src/iter.cpp | 44 ++++++++++++++++++---------------------- src/vm.cpp | 24 ++++++++++++++++++++-- 7 files changed, 78 insertions(+), 68 deletions(-) diff --git a/include/pocketpy/frame.h b/include/pocketpy/frame.h index 3bc608ed..8b01db66 100644 --- a/include/pocketpy/frame.h +++ b/include/pocketpy/frame.h @@ -110,6 +110,10 @@ struct Frame { int _exit_block(ValueStack*, int); void jump_abs_break(ValueStack*, int); + void loop_break(ValueStack* s_data, const CodeObject*){ + jump_abs_break(s_data, co->_get_block_codei(_ip).end); + } + int curr_lineno() const { return co->lines[_ip].lineno; } void _gc_mark() const { diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 35a9653d..fa4e9b2d 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -57,8 +57,7 @@ struct PyTypeInfo{ i64 (*m__hash__)(VM* vm, PyObject*) = nullptr; i64 (*m__len__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__iter__)(VM* vm, PyObject*) = nullptr; - PyObject* (*m__next__)(VM* vm, PyObject*) = nullptr; - unsigned int (*m__next__unpack)(VM* vm, PyObject*) = nullptr; + unsigned (*m__next__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__neg__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__invert__)(VM* vm, PyObject*) = nullptr; @@ -253,7 +252,7 @@ public: void bind__repr__(Type type, PyObject* (*f)(VM*, PyObject*)); void bind__str__(Type type, PyObject* (*f)(VM*, PyObject*)); void bind__iter__(Type type, PyObject* (*f)(VM*, PyObject*)); - void bind__next__(Type type, PyObject* (*f)(VM*, PyObject*)); + void bind__next__(Type type, unsigned (*f)(VM*, PyObject*)); void bind__neg__(Type type, PyObject* (*f)(VM*, PyObject*)); void bind__invert__(Type type, PyObject* (*f)(VM*, PyObject*)); void bind__hash__(Type type, i64 (*f)(VM* vm, PyObject*)); @@ -310,6 +309,7 @@ public: i64 normalized_index(i64 index, int size); PyObject* py_next(PyObject* obj); + PyObject* _pack_next_retval(unsigned); bool py_callable(PyObject* obj); /***** Error Reporter *****/ diff --git a/src/array2d.cpp b/src/array2d.cpp index 96058de0..437aaf78 100644 --- a/src/array2d.cpp +++ b/src/array2d.cpp @@ -356,19 +356,10 @@ struct Array2dIter{ void _gc_mark() const{ PK_OBJ_MARK(ref); } static void _register(VM* vm, PyObject* mod, PyObject* type){ - PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, type)]; - info.subclass_enabled = false; + vm->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false; vm->bind_notimplemented_constructor(type); vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) { return _0; }); - vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ - Array2dIter& self = PK_OBJ_GET(Array2dIter, _0); - Array2d& a = PK_OBJ_GET(Array2d, self.ref); - if(self.i == a.numel) return vm->StopIteration; - std::div_t res = std::div(self.i, a.n_cols); - return VAR(Tuple(VAR(res.rem), VAR(res.quot), a.data[self.i++])); - }); - - info.m__next__unpack = [](VM* vm, PyObject* _0) -> unsigned int{ + vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{ Array2dIter& self = PK_OBJ_GET(Array2dIter, _0); Array2d& a = PK_OBJ_GET(Array2d, self.ref); if(self.i == a.numel) return 0; @@ -377,7 +368,7 @@ struct Array2dIter{ vm->s_data.push(VAR(res.quot)); vm->s_data.push(a.data[self.i++]); return 3; - }; + }); } }; diff --git a/src/ceval.cpp b/src/ceval.cpp index 994115ba..741c1c89 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -760,45 +760,45 @@ __NEXT_STEP:; DISPATCH(); TARGET(FOR_ITER){ PyObject* _0 = py_next(TOP()); - if(_0 != StopIteration){ - PUSH(_0); - }else{ - frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); - } + if(_0 == StopIteration) frame->loop_break(&s_data, co); + else PUSH(_0); } DISPATCH(); TARGET(FOR_ITER_STORE_FAST){ PyObject* _0 = py_next(TOP()); - if(_0 != StopIteration){ - frame->_locals[byte.arg] = _0; + if(_0 == StopIteration){ + frame->loop_break(&s_data, co); }else{ - frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); + frame->_locals[byte.arg] = _0; } } DISPATCH() TARGET(FOR_ITER_STORE_GLOBAL){ PyObject* _0 = py_next(TOP()); - if(_0 != StopIteration){ - frame->f_globals().set(StrName(byte.arg), _0); + if(_0 == StopIteration){ + frame->loop_break(&s_data, co); }else{ - frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); + frame->f_globals().set(StrName(byte.arg), _0); } } DISPATCH() TARGET(FOR_ITER_YIELD_VALUE){ PyObject* _0 = py_next(TOP()); - if(_0 != StopIteration){ + if(_0 == StopIteration){ + frame->loop_break(&s_data, co); + }else{ PUSH(_0); return PY_OP_YIELD; - }else{ - frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); } } DISPATCH() TARGET(FOR_ITER_UNPACK){ PyObject* _0 = TOP(); const PyTypeInfo* _ti = _inst_type_info(_0); - if(_ti->m__next__unpack){ - unsigned int n = _ti->m__next__unpack(this, _0); + if(_ti->m__next__){ + unsigned n = _ti->m__next__(this, _0); if(n == 0){ // StopIteration - frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); + frame->loop_break(&s_data, co); + }else if(n == 1){ + // UNPACK_SEQUENCE + _op_unpack_sequence(byte.arg); }else{ if(n != byte.arg){ ValueError(_S("expected ", (int)byte.arg, " values to unpack, got ", (int)n)); @@ -806,14 +806,13 @@ __NEXT_STEP:; } }else{ // FOR_ITER - if(_ti->m__next__) _0 = _ti->m__next__(this, _0); - else _0 = call_method(_0, __next__); + _0 = call_method(_0, __next__); if(_0 != StopIteration){ PUSH(_0); // UNPACK_SEQUENCE _op_unpack_sequence(byte.arg); }else{ - frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); + frame->loop_break(&s_data, co); } } } DISPATCH() diff --git a/src/collections.cpp b/src/collections.cpp index c53b7620..b3a8cd80 100644 --- a/src/collections.cpp +++ b/src/collections.cpp @@ -30,20 +30,20 @@ namespace pkpy vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject *obj) { return obj; }); - vm->bind__next__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject *obj) + vm->bind__next__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject *obj) -> unsigned { PyDequeIter& self = _CAST(PyDequeIter&, obj); if(self.is_reversed){ - if(self.rcurrent == self.rend) return vm->StopIteration; - PyObject* ret = *self.rcurrent; + if(self.rcurrent == self.rend) return 0; + vm->s_data.push(*self.rcurrent); ++self.rcurrent; - return ret; + return 1; } else{ - if(self.current == self.end) return vm->StopIteration; - PyObject* ret = *self.current; + if(self.current == self.end) return 0; + vm->s_data.push(*self.current); ++self.current; - return ret; + return 1; } }); } struct PyDeque diff --git a/src/iter.cpp b/src/iter.cpp index 48ebd6df..f76da05c 100644 --- a/src/iter.cpp +++ b/src/iter.cpp @@ -6,16 +6,16 @@ namespace pkpy{ vm->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false; vm->bind_notimplemented_constructor(type); vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); - vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ + vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{ RangeIter& self = PK_OBJ_GET(RangeIter, _0); if(self.r.step > 0){ - if(self.current >= self.r.stop) return vm->StopIteration; + if(self.current >= self.r.stop) return 0; }else{ - if(self.current <= self.r.stop) return vm->StopIteration; + if(self.current <= self.r.stop) return 0; } - PyObject* ret = VAR(self.current); + vm->s_data.push(VAR(self.current)); self.current += self.r.step; - return ret; + return 1; }); } @@ -23,10 +23,11 @@ namespace pkpy{ vm->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false; vm->bind_notimplemented_constructor(type); vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); - vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ + vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{ ArrayIter& self = _CAST(ArrayIter&, _0); - if(self.current == self.end) return vm->StopIteration; - return *self.current++; + if(self.current == self.end) return 0; + vm->s_data.push(*self.current++); + return 1; }); } @@ -34,14 +35,15 @@ namespace pkpy{ vm->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false; vm->bind_notimplemented_constructor(type); vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); - vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ + vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{ StringIter& self = _CAST(StringIter&, _0); Str& s = PK_OBJ_GET(Str, self.ref); - if(self.i == s.size) return vm->StopIteration; + if(self.i == s.size) return 0; int start = self.i; int len = utf8len(s.data[self.i]); self.i += len; - return VAR(s.substr(start, len)); + vm->s_data.push(VAR(s.substr(start, len))); + return 1; }); } @@ -82,9 +84,12 @@ namespace pkpy{ vm->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false; vm->bind_notimplemented_constructor(type); vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); - vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ + vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{ Generator& self = _CAST(Generator&, _0); - return self.next(vm); + PyObject* retval = self.next(vm); + if(retval == vm->StopIteration) return 0; + vm->s_data.push(retval); + return 1; }); } @@ -93,16 +98,7 @@ namespace pkpy{ info.subclass_enabled = false; vm->bind_notimplemented_constructor(type); vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); - vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ - DictItemsIter& self = _CAST(DictItemsIter&, _0); - Dict& d = PK_OBJ_GET(Dict, self.ref); - if(self.i == -1) return vm->StopIteration; - PyObject* retval = VAR(Tuple(d._items[self.i].first, d._items[self.i].second)); - self.i = d._nodes[self.i].next; - return retval; - }); - - info.m__next__unpack = [](VM* vm, PyObject* _0) -> unsigned int{ + vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{ DictItemsIter& self = _CAST(DictItemsIter&, _0); Dict& d = PK_OBJ_GET(Dict, self.ref); if(self.i == -1) return 0; @@ -110,7 +106,7 @@ namespace pkpy{ vm->s_data.push(d._items[self.i].second); self.i = d._nodes[self.i].next; return 2; - }; + }); } PyObject* VM::_py_generator(Frame&& frame, ArgsView buffer){ diff --git a/src/vm.cpp b/src/vm.cpp index b5fabf35..0cd75c80 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -252,7 +252,10 @@ namespace pkpy{ PyObject* VM::py_next(PyObject* obj){ const PyTypeInfo* ti = _inst_type_info(obj); - if(ti->m__next__) return ti->m__next__(this, obj); + if(ti->m__next__){ + unsigned n = ti->m__next__(this, obj); + return _pack_next_retval(n); + } return call_method(obj, __next__); } @@ -1312,6 +1315,24 @@ void VM::bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*)){ PK_OBJ_GET(NativeFunc, nf).set_userdata(f); } + + PyObject* VM::_pack_next_retval(unsigned n){ + if(n == 0) return StopIteration; + if(n == 1) return s_data.popx(); + PyObject* retval = VAR(s_data.view(n).to_tuple()); + s_data._sp -= n; + return retval; + } + + void VM::bind__next__(Type type, unsigned (*f)(VM*, PyObject*)){ \ + _all_types[type].m__next__ = f; \ + PyObject* nf = bind_method<0>(_t(type), __next__, [](VM* vm, ArgsView args){ \ + int n = lambda_get_userdata(args.begin())(vm, args[0]);\ + return vm->_pack_next_retval(n); \ + }); \ + PK_OBJ_GET(NativeFunc, nf).set_userdata(f); \ + } + #define BIND_UNARY_SPECIAL(name) \ void VM::bind##name(Type type, PyObject* (*f)(VM*, PyObject*)){ \ _all_types[type].m##name = f; \ @@ -1324,7 +1345,6 @@ void VM::bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*)){ BIND_UNARY_SPECIAL(__repr__) BIND_UNARY_SPECIAL(__str__) BIND_UNARY_SPECIAL(__iter__) - BIND_UNARY_SPECIAL(__next__) BIND_UNARY_SPECIAL(__neg__) BIND_UNARY_SPECIAL(__invert__) #undef BIND_UNARY_SPECIAL