blueloveTH 3 лет назад
Родитель
Сommit
1ea7c151a3
4 измененных файлов с 42 добавлено и 38 удалено
  1. 1 1
      src/ceval.h
  2. 13 21
      src/iter.h
  3. 4 7
      src/pocketpy.h
  4. 24 9
      src/vm.h

+ 1 - 1
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));

+ 13 - 21
src/iter.h

@@ -48,25 +48,17 @@ public:
     }
 };
 
-class Generator: public BaseIter {
-    std::unique_ptr<Frame> frame;
-    int state; // 0,1,2
-public:
-    Generator(VM* vm, std::unique_ptr<Frame>&& 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;
     }
-};
+}

+ 4 - 7
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<BaseIter, RangeIter>(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<BaseIter, StringIter>(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<BaseIter, ArrayIter<pkpy::List>>(vm, args[0]));
+        return vm->PyIter(ArrayIter<pkpy::List>(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<BaseIter, ArrayIter<pkpy::Args>>(vm, args[0]));
+        return vm->PyIter(ArrayIter<pkpy::Args>(vm, args[0]));
     });
 
     _vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, pkpy::Args& args) {

+ 24 - 9
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> frame;
+    int state; // 0,1,2
+public:
+    Generator(VM* vm, std::unique_ptr<Frame>&& 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<BaseIter, Generator>(
-                    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<typename P>
     inline PyVarRef PyRef(P&& value) {
-        static_assert(std::is_base_of<BaseRef, std::remove_reference_t<P>>::value, "P should derive from BaseRef");
+        static_assert(std::is_base_of_v<BaseRef, RAW(P)>);
         return new_object(tp_ref, std::forward<P>(value));
     }
 
@@ -533,6 +537,18 @@ public:
         return static_cast<const BaseRef*>(obj->value());
     }
 
+    template<typename P>
+    inline PyVar PyIter(P&& value) {
+        static_assert(std::is_base_of_v<BaseIter, RAW(P)>);
+        return new_object(tp_native_iterator, std::forward<P>(value));
+    }
+
+    inline BaseIter* PyIter_AS_C(const PyVar& obj)
+    {
+        check_type(obj, tp_native_iterator);
+        return static_cast<BaseIter*>(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<BaseIter>, 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<BaseIter> iter = vm->PyIter_AS_C(val);
+    BaseIter* iter = vm->PyIter_AS_C(val);
     for(int i=0; i<objs.size(); i++){
         PyVarOrNull x;
         if(is_type(objs[i], vm->tp_star_wrapper)){