diff --git a/src/ceval.h b/src/ceval.h index 2ada8589..06af350a 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -247,7 +247,7 @@ PyVar VM::run_frame(Frame* frame){ frame->push(std::move(iter)); } continue; case OP_FOR_ITER: { - auto& it = PyIter_AS_C(frame->top()); + BaseIter* it = PyIter_AS_C(frame->top()); PyVar obj = it->next(); if(obj != nullptr){ PyRef_AS_C(it->loop_var)->set(this, frame, std::move(obj)); diff --git a/src/iter.h b/src/iter.h index 88a2e34c..311e5497 100644 --- a/src/iter.h +++ b/src/iter.h @@ -48,25 +48,17 @@ public: } }; -class Generator: public BaseIter { - std::unique_ptr frame; - int state; // 0,1,2 -public: - Generator(VM* vm, std::unique_ptr&& frame) - : BaseIter(vm, nullptr), frame(std::move(frame)), state(0) {} - - PyVar next() { - if(state == 2) return nullptr; - vm->callstack.push(std::move(frame)); - PyVar ret = vm->_exec(); - if(ret == vm->_py_op_yield){ - frame = std::move(vm->callstack.top()); - vm->callstack.pop(); - state = 1; - return frame->pop_value(vm); - }else{ - state = 2; - return nullptr; - } +PyVar Generator::next(){ + if(state == 2) return nullptr; + vm->callstack.push(std::move(frame)); + PyVar ret = vm->_exec(); + if(ret == vm->_py_op_yield){ + frame = std::move(vm->callstack.top()); + vm->callstack.pop(); + state = 1; + return frame->pop_value(vm); + }else{ + state = 2; + return nullptr; } -}; \ No newline at end of file +} \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index 9e7ceacc..ce6acec5 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -169,7 +169,7 @@ void init_builtins(VM* _vm) { }); _vm->bind_method<0>("range", "__iter__", CPP_LAMBDA( - vm->PyIter(pkpy::make_shared(vm, args[0])) + vm->PyIter(RangeIter(vm, args[0])) )); _vm->bind_method<0>("NoneType", "__repr__", CPP_LAMBDA(vm->PyStr("None"))); @@ -303,10 +303,7 @@ void init_builtins(VM* _vm) { }); _vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0])); - - _vm->bind_method<0>("str", "__iter__", CPP_LAMBDA( - vm->PyIter(pkpy::make_shared(vm, args[0])) - )); + _vm->bind_method<0>("str", "__iter__", CPP_LAMBDA(vm->PyIter(StringIter(vm, args[0])))); _vm->bind_method<0>("str", "__repr__", [](VM* vm, pkpy::Args& args) { const Str& _self = vm->PyStr_AS_C(args[0]); @@ -447,7 +444,7 @@ void init_builtins(VM* _vm) { }); _vm->bind_method<0>("list", "__iter__", [](VM* vm, pkpy::Args& args) { - return vm->PyIter(pkpy::make_shared>(vm, args[0])); + return vm->PyIter(ArrayIter(vm, args[0])); }); _vm->bind_method<1>("list", "__getitem__", [](VM* vm, pkpy::Args& args) { @@ -489,7 +486,7 @@ void init_builtins(VM* _vm) { }); _vm->bind_method<0>("tuple", "__iter__", [](VM* vm, pkpy::Args& args) { - return vm->PyIter(pkpy::make_shared>(vm, args[0])); + return vm->PyIter(ArrayIter(vm, args[0])); }); _vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, pkpy::Args& args) { diff --git a/src/vm.h b/src/vm.h index 3b661168..6bf5f375 100644 --- a/src/vm.h +++ b/src/vm.h @@ -11,7 +11,15 @@ inline PyVar Py##type(const ctype& value) { return new_object(ptype, value);} \ inline PyVar Py##type(ctype&& value) { return new_object(ptype, std::move(value));} -class Generator; +class Generator: public BaseIter { + std::unique_ptr frame; + int state; // 0,1,2 +public: + Generator(VM* vm, std::unique_ptr&& frame) + : BaseIter(vm, nullptr), frame(std::move(frame)), state(0) {} + + PyVar next(); +}; class VM { public: @@ -192,10 +200,7 @@ public: } const PyVar& _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(pkpy::make_shared( - this, std::move(_frame))); - } + if(fn.code->is_generator) return PyIter(Generator(this, std::move(_frame))); callstack.push(std::move(_frame)); if(opCall) return _py_op_call; return _exec(); @@ -204,7 +209,6 @@ public: return None; } - // repl mode is only for setting `frame->id` to 0 PyVarOrNull exec(Str source, Str filename, CompileMode mode, PyVar _module=nullptr){ if(_module == nullptr) _module = _main; @@ -523,7 +527,7 @@ public: template inline PyVarRef PyRef(P&& value) { - static_assert(std::is_base_of>::value, "P should derive from BaseRef"); + static_assert(std::is_base_of_v); return new_object(tp_ref, std::forward

(value)); } @@ -533,6 +537,18 @@ public: return static_cast(obj->value()); } + template + inline PyVar PyIter(P&& value) { + static_assert(std::is_base_of_v); + return new_object(tp_native_iterator, std::forward

(value)); + } + + inline BaseIter* PyIter_AS_C(const PyVar& obj) + { + check_type(obj, tp_native_iterator); + return static_cast(obj->value()); + } + inline const Str& PyStr_AS_C(const PyVar& obj) { check_type(obj, tp_str); return OBJ_GET(Str, obj); @@ -587,7 +603,6 @@ public: DEF_NATIVE(Tuple, pkpy::Tuple, tp_tuple) DEF_NATIVE(Function, pkpy::Function, tp_function) DEF_NATIVE(NativeFunc, pkpy::NativeFunc, tp_native_function) - DEF_NATIVE(Iter, pkpy::shared_ptr, tp_native_iterator) DEF_NATIVE(BoundMethod, pkpy::BoundMethod, tp_bound_method) DEF_NATIVE(Range, pkpy::Range, tp_range) DEF_NATIVE(Slice, pkpy::Slice, tp_slice) @@ -860,7 +875,7 @@ PyVar TupleRef::get(VM* vm, Frame* frame) const{ void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{ val = vm->asIter(val); - pkpy::shared_ptr iter = vm->PyIter_AS_C(val); + BaseIter* iter = vm->PyIter_AS_C(val); for(int i=0; itp_star_wrapper)){