break change of m__next__

This commit is contained in:
blueloveTH 2024-04-29 11:57:21 +08:00
parent 2929addbd8
commit f752acdfc8
7 changed files with 78 additions and 68 deletions

View File

@ -110,6 +110,10 @@ struct Frame {
int _exit_block(ValueStack*, int); int _exit_block(ValueStack*, int);
void jump_abs_break(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; } int curr_lineno() const { return co->lines[_ip].lineno; }
void _gc_mark() const { void _gc_mark() const {

View File

@ -57,8 +57,7 @@ struct PyTypeInfo{
i64 (*m__hash__)(VM* vm, PyObject*) = nullptr; i64 (*m__hash__)(VM* vm, PyObject*) = nullptr;
i64 (*m__len__)(VM* vm, PyObject*) = nullptr; i64 (*m__len__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__iter__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__iter__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__next__)(VM* vm, PyObject*) = nullptr; unsigned (*m__next__)(VM* vm, PyObject*) = nullptr;
unsigned int (*m__next__unpack)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__neg__)(VM* vm, PyObject*) = nullptr; PyObject* (*m__neg__)(VM* vm, PyObject*) = nullptr;
PyObject* (*m__invert__)(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__repr__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__str__(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__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__neg__(Type type, PyObject* (*f)(VM*, PyObject*));
void bind__invert__(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*)); void bind__hash__(Type type, i64 (*f)(VM* vm, PyObject*));
@ -310,6 +309,7 @@ public:
i64 normalized_index(i64 index, int size); i64 normalized_index(i64 index, int size);
PyObject* py_next(PyObject* obj); PyObject* py_next(PyObject* obj);
PyObject* _pack_next_retval(unsigned);
bool py_callable(PyObject* obj); bool py_callable(PyObject* obj);
/***** Error Reporter *****/ /***** Error Reporter *****/

View File

@ -356,19 +356,10 @@ struct Array2dIter{
void _gc_mark() const{ PK_OBJ_MARK(ref); } void _gc_mark() const{ PK_OBJ_MARK(ref); }
static void _register(VM* vm, PyObject* mod, PyObject* type){ static void _register(VM* vm, PyObject* mod, PyObject* type){
PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, type)]; vm->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false;
info.subclass_enabled = false;
vm->bind_notimplemented_constructor<Array2dIter>(type); vm->bind_notimplemented_constructor<Array2dIter>(type);
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) { return _0; }); 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{
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{
Array2dIter& self = PK_OBJ_GET(Array2dIter, _0); Array2dIter& self = PK_OBJ_GET(Array2dIter, _0);
Array2d& a = PK_OBJ_GET(Array2d, self.ref); Array2d& a = PK_OBJ_GET(Array2d, self.ref);
if(self.i == a.numel) return 0; if(self.i == a.numel) return 0;
@ -377,7 +368,7 @@ struct Array2dIter{
vm->s_data.push(VAR(res.quot)); vm->s_data.push(VAR(res.quot));
vm->s_data.push(a.data[self.i++]); vm->s_data.push(a.data[self.i++]);
return 3; return 3;
}; });
} }
}; };

View File

@ -760,45 +760,45 @@ __NEXT_STEP:;
DISPATCH(); DISPATCH();
TARGET(FOR_ITER){ TARGET(FOR_ITER){
PyObject* _0 = py_next(TOP()); PyObject* _0 = py_next(TOP());
if(_0 != StopIteration){ if(_0 == StopIteration) frame->loop_break(&s_data, co);
PUSH(_0); else PUSH(_0);
}else{
frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end);
}
} DISPATCH(); } DISPATCH();
TARGET(FOR_ITER_STORE_FAST){ TARGET(FOR_ITER_STORE_FAST){
PyObject* _0 = py_next(TOP()); PyObject* _0 = py_next(TOP());
if(_0 != StopIteration){ if(_0 == StopIteration){
frame->_locals[byte.arg] = _0; frame->loop_break(&s_data, co);
}else{ }else{
frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); frame->_locals[byte.arg] = _0;
} }
} DISPATCH() } DISPATCH()
TARGET(FOR_ITER_STORE_GLOBAL){ TARGET(FOR_ITER_STORE_GLOBAL){
PyObject* _0 = py_next(TOP()); PyObject* _0 = py_next(TOP());
if(_0 != StopIteration){ if(_0 == StopIteration){
frame->f_globals().set(StrName(byte.arg), _0); frame->loop_break(&s_data, co);
}else{ }else{
frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); frame->f_globals().set(StrName(byte.arg), _0);
} }
} DISPATCH() } DISPATCH()
TARGET(FOR_ITER_YIELD_VALUE){ TARGET(FOR_ITER_YIELD_VALUE){
PyObject* _0 = py_next(TOP()); PyObject* _0 = py_next(TOP());
if(_0 != StopIteration){ if(_0 == StopIteration){
frame->loop_break(&s_data, co);
}else{
PUSH(_0); PUSH(_0);
return PY_OP_YIELD; return PY_OP_YIELD;
}else{
frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end);
} }
} DISPATCH() } DISPATCH()
TARGET(FOR_ITER_UNPACK){ TARGET(FOR_ITER_UNPACK){
PyObject* _0 = TOP(); PyObject* _0 = TOP();
const PyTypeInfo* _ti = _inst_type_info(_0); const PyTypeInfo* _ti = _inst_type_info(_0);
if(_ti->m__next__unpack){ if(_ti->m__next__){
unsigned int n = _ti->m__next__unpack(this, _0); unsigned n = _ti->m__next__(this, _0);
if(n == 0){ if(n == 0){
// StopIteration // 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{ }else{
if(n != byte.arg){ if(n != byte.arg){
ValueError(_S("expected ", (int)byte.arg, " values to unpack, got ", (int)n)); ValueError(_S("expected ", (int)byte.arg, " values to unpack, got ", (int)n));
@ -806,14 +806,13 @@ __NEXT_STEP:;
} }
}else{ }else{
// FOR_ITER // FOR_ITER
if(_ti->m__next__) _0 = _ti->m__next__(this, _0); _0 = call_method(_0, __next__);
else _0 = call_method(_0, __next__);
if(_0 != StopIteration){ if(_0 != StopIteration){
PUSH(_0); PUSH(_0);
// UNPACK_SEQUENCE // UNPACK_SEQUENCE
_op_unpack_sequence(byte.arg); _op_unpack_sequence(byte.arg);
}else{ }else{
frame->jump_abs_break(&s_data, co->_get_block_codei(frame->_ip).end); frame->loop_break(&s_data, co);
} }
} }
} DISPATCH() } DISPATCH()

View File

@ -30,20 +30,20 @@ namespace pkpy
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject *obj) vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject *obj)
{ return 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); PyDequeIter& self = _CAST(PyDequeIter&, obj);
if(self.is_reversed){ if(self.is_reversed){
if(self.rcurrent == self.rend) return vm->StopIteration; if(self.rcurrent == self.rend) return 0;
PyObject* ret = *self.rcurrent; vm->s_data.push(*self.rcurrent);
++self.rcurrent; ++self.rcurrent;
return ret; return 1;
} }
else{ else{
if(self.current == self.end) return vm->StopIteration; if(self.current == self.end) return 0;
PyObject* ret = *self.current; vm->s_data.push(*self.current);
++self.current; ++self.current;
return ret; return 1;
} }); } });
} }
struct PyDeque struct PyDeque

View File

@ -6,16 +6,16 @@ namespace pkpy{
vm->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false; vm->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false;
vm->bind_notimplemented_constructor<RangeIter>(type); vm->bind_notimplemented_constructor<RangeIter>(type);
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); 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); RangeIter& self = PK_OBJ_GET(RangeIter, _0);
if(self.r.step > 0){ if(self.r.step > 0){
if(self.current >= self.r.stop) return vm->StopIteration; if(self.current >= self.r.stop) return 0;
}else{ }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; 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->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false;
vm->bind_notimplemented_constructor<ArrayIter>(type); vm->bind_notimplemented_constructor<ArrayIter>(type);
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); 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); ArrayIter& self = _CAST(ArrayIter&, _0);
if(self.current == self.end) return vm->StopIteration; if(self.current == self.end) return 0;
return *self.current++; 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->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false;
vm->bind_notimplemented_constructor<StringIter>(type); vm->bind_notimplemented_constructor<StringIter>(type);
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); 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); StringIter& self = _CAST(StringIter&, _0);
Str& s = PK_OBJ_GET(Str, self.ref); 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 start = self.i;
int len = utf8len(s.data[self.i]); int len = utf8len(s.data[self.i]);
self.i += len; 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->_all_types[PK_OBJ_GET(Type, type)].subclass_enabled = false;
vm->bind_notimplemented_constructor<Generator>(type); vm->bind_notimplemented_constructor<Generator>(type);
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); 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); 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; info.subclass_enabled = false;
vm->bind_notimplemented_constructor<DictItemsIter>(type); vm->bind_notimplemented_constructor<DictItemsIter>(type);
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; }); 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{
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{
DictItemsIter& self = _CAST(DictItemsIter&, _0); DictItemsIter& self = _CAST(DictItemsIter&, _0);
Dict& d = PK_OBJ_GET(Dict, self.ref); Dict& d = PK_OBJ_GET(Dict, self.ref);
if(self.i == -1) return 0; if(self.i == -1) return 0;
@ -110,7 +106,7 @@ namespace pkpy{
vm->s_data.push(d._items[self.i].second); vm->s_data.push(d._items[self.i].second);
self.i = d._nodes[self.i].next; self.i = d._nodes[self.i].next;
return 2; return 2;
}; });
} }
PyObject* VM::_py_generator(Frame&& frame, ArgsView buffer){ PyObject* VM::_py_generator(Frame&& frame, ArgsView buffer){

View File

@ -252,7 +252,10 @@ namespace pkpy{
PyObject* VM::py_next(PyObject* obj){ PyObject* VM::py_next(PyObject* obj){
const PyTypeInfo* ti = _inst_type_info(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__); 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); 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<unsigned(*)(VM*, PyObject*)>(args.begin())(vm, args[0]);\
return vm->_pack_next_retval(n); \
}); \
PK_OBJ_GET(NativeFunc, nf).set_userdata(f); \
}
#define BIND_UNARY_SPECIAL(name) \ #define BIND_UNARY_SPECIAL(name) \
void VM::bind##name(Type type, PyObject* (*f)(VM*, PyObject*)){ \ void VM::bind##name(Type type, PyObject* (*f)(VM*, PyObject*)){ \
_all_types[type].m##name = f; \ _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(__repr__)
BIND_UNARY_SPECIAL(__str__) BIND_UNARY_SPECIAL(__str__)
BIND_UNARY_SPECIAL(__iter__) BIND_UNARY_SPECIAL(__iter__)
BIND_UNARY_SPECIAL(__next__)
BIND_UNARY_SPECIAL(__neg__) BIND_UNARY_SPECIAL(__neg__)
BIND_UNARY_SPECIAL(__invert__) BIND_UNARY_SPECIAL(__invert__)
#undef BIND_UNARY_SPECIAL #undef BIND_UNARY_SPECIAL