blueloveTH 2 роки тому
батько
коміт
680a678123
9 змінених файлів з 132 додано та 141 видалено
  1. 1 1
      src/cffi.h
  2. 0 1
      src/common.h
  3. 101 68
      src/iter.h
  4. 0 12
      src/linalg.h
  5. 2 5
      src/memory.h
  6. 3 2
      src/namedict.h
  7. 0 9
      src/obj.h
  8. 10 12
      src/pocketpy.h
  9. 15 31
      src/vm.h

+ 1 - 1
src/cffi.h

@@ -296,7 +296,7 @@ struct C99ReflType final: ReflType{
     }
 
     static void _register(VM* vm, PyObject* mod, PyObject* type){
-        vm->bind_constructor<-1>(type, CPP_NOT_IMPLEMENTED());
+        vm->bind_notimplemented_constructor<C99ReflType>(type);
 
         vm->bind_method<0>(type, "__call__", [](VM* vm, ArgsView args){
             C99ReflType& self = _CAST(C99ReflType&, args[0]);

+ 0 - 1
src/common.h

@@ -131,7 +131,6 @@ struct Type {
 
 #define THREAD_LOCAL	// thread_local
 #define CPP_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; })
-#define CPP_NOT_IMPLEMENTED() ([](VM* vm, ArgsView args) { vm->NotImplementedError(); return vm->None; })
 
 #ifdef POCKETPY_H
 #define FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!");

+ 101 - 68
src/iter.h

@@ -1,98 +1,131 @@
 #pragma once
 
-#include "ceval.h"
+#include "cffi.h"
+#include "common.h"
 #include "frame.h"
 
 namespace pkpy{
 
-class RangeIter final: public BaseIter {
+struct RangeIter{
+    PY_CLASS(RangeIter, builtins, "_range_iterator")
+    Range r;
     i64 current;
-    Range r;    // copy by value, so we don't need to keep ref
-public:
-    RangeIter(VM* vm, PyObject* ref) : BaseIter(vm) {
-        this->r = OBJ_GET(Range, ref);
-        this->current = r.start;
-    }
+    RangeIter(Range r) : r(r), current(r.start) {}
 
-    bool _has_next(){
-        return r.step > 0 ? current < r.stop : current > r.stop;
+    static void _register(VM* vm, PyObject* mod, PyObject* type){
+        vm->_all_types[OBJ_GET(Type, type)].subclass_enabled = false;
+        vm->bind_notimplemented_constructor<RangeIter>(type);
+        vm->bind__iter__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){ return obj; });
+        vm->bind__next__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            RangeIter& self = _CAST(RangeIter&, obj);
+            bool has_next = self.r.step > 0 ? self.current < self.r.stop : self.current > self.r.stop;
+            if(!has_next) return vm->StopIteration;
+            self.current += self.r.step;
+            return VAR(self.current - self.r.step);
+        });
     }
+};
+
+struct ArrayIter{
+    PY_CLASS(ArrayIter, builtins, "_array_iterator")
+    PyObject* ref;
+    PyObject** begin;
+    PyObject** end;
+    PyObject** current;
+
+    ArrayIter(PyObject* ref, PyObject** begin, PyObject** end)
+        : ref(ref), begin(begin), end(end), current(begin) {}
 
-    PyObject* next(){
-        if(!_has_next()) return vm->StopIteration;
-        current += r.step;
-        return VAR(current-r.step);
+    void _gc_mark() const{ OBJ_MARK(ref); }
+
+    static void _register(VM* vm, PyObject* mod, PyObject* type){
+        vm->_all_types[OBJ_GET(Type, type)].subclass_enabled = false;
+        vm->bind_notimplemented_constructor<ArrayIter>(type);
+        vm->bind__iter__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){ return obj; });
+        vm->bind__next__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            ArrayIter& self = _CAST(ArrayIter&, obj);
+            if(self.current == self.end) return vm->StopIteration;
+            return *self.current++;
+        });
     }
 };
 
-template <typename T>
-class ArrayIter final: public BaseIter {
+struct StringIter{
+    PY_CLASS(StringIter, builtins, "_string_iterator")
     PyObject* ref;
-    T* array;
+    Str* str;
     int index;
-public:
-    ArrayIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref) {
-        array = &OBJ_GET(T, ref);
-        index = 0;
-    }
 
-    PyObject* next() override{
-        if(index >= array->size()) return vm->StopIteration;
-        return array->operator[](index++);
-    }
+    StringIter(PyObject* ref) : ref(ref), str(&OBJ_GET(Str, ref)), index(0) {}
 
-    void _gc_mark() const{
-        OBJ_MARK(ref);
+    void _gc_mark() const{ OBJ_MARK(ref); }
+
+    static void _register(VM* vm, PyObject* mod, PyObject* type){
+        vm->_all_types[OBJ_GET(Type, type)].subclass_enabled = false;
+        vm->bind_notimplemented_constructor<StringIter>(type);
+        vm->bind__iter__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){ return obj; });
+        vm->bind__next__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            StringIter& self = _CAST(StringIter&, obj);
+            // TODO: optimize this... operator[] is of O(n) complexity
+            if(self.index == self.str->u8_length()) return vm->StopIteration;
+            return VAR(self.str->u8_getitem(self.index++));
+        });
     }
 };
 
-class StringIter final: public BaseIter {
-    PyObject* ref;
-    int index;
-public:
-    StringIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref), index(0) {}
-
-    PyObject* next() override{
-        // TODO: optimize this to use iterator
-        // operator[] is O(n) complexity
-        Str* str = &OBJ_GET(Str, ref);
-        if(index == str->u8_length()) return vm->StopIteration;
-        return VAR(str->u8_getitem(index++));
+struct Generator{
+    PY_CLASS(Generator, builtins, "_generator")
+    Frame frame;
+    int state;      // 0,1,2
+    List s_backup;
+
+    Generator(Frame&& frame, ArgsView buffer): frame(std::move(frame)), state(0) {
+        for(PyObject* obj: buffer) s_backup.push_back(obj);
     }
 
     void _gc_mark() const{
-        OBJ_MARK(ref);
+        frame._gc_mark();
+        for(PyObject* obj: s_backup) OBJ_MARK(obj);
     }
-};
 
-inline PyObject* Generator::next(){
-    if(state == 2) return vm->StopIteration;
-    // reset frame._sp_base
-    frame._sp_base = frame._s->_sp;
-    frame._locals.a = frame._s->_sp;
-    // restore the context
-    for(PyObject* obj: s_backup) frame._s->push(obj);
-    s_backup.clear();
-    vm->callstack.push(std::move(frame));
-    PyObject* ret = vm->_run_top_frame();
-    if(ret == PY_OP_YIELD){
-        // backup the context
-        frame = std::move(vm->callstack.top());
-        PyObject* ret = frame._s->popx();
-        for(PyObject* obj: frame.stack_view()) s_backup.push_back(obj);
-        vm->_pop_frame();
-        state = 1;
-        if(ret == vm->StopIteration) state = 2;
-        return ret;
-    }else{
-        state = 2;
-        return vm->StopIteration;
+    PyObject* next(VM* vm){
+        if(state == 2) return vm->StopIteration;
+        // reset frame._sp_base
+        frame._sp_base = frame._s->_sp;
+        frame._locals.a = frame._s->_sp;
+        // restore the context
+        for(PyObject* obj: s_backup) frame._s->push(obj);
+        s_backup.clear();
+        vm->callstack.push(std::move(frame));
+        PyObject* ret = vm->_run_top_frame();
+        if(ret == PY_OP_YIELD){
+            // backup the context
+            frame = std::move(vm->callstack.top());
+            PyObject* ret = frame._s->popx();
+            for(PyObject* obj: frame.stack_view()) s_backup.push_back(obj);
+            vm->_pop_frame();
+            state = 1;
+            if(ret == vm->StopIteration) state = 2;
+            return ret;
+        }else{
+            state = 2;
+            return vm->StopIteration;
+        }
     }
-}
 
-inline void Generator::_gc_mark() const{
-    frame._gc_mark();
-    for(PyObject* obj: s_backup) OBJ_MARK(obj);
+    static void _register(VM* vm, PyObject* mod, PyObject* type){
+        vm->_all_types[OBJ_GET(Type, type)].subclass_enabled = false;
+        vm->bind_notimplemented_constructor<Generator>(type);
+        vm->bind__iter__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){ return obj; });
+        vm->bind__next__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            Generator& self = _CAST(Generator&, obj);
+            return self.next(vm);
+        });
+    }
+};
+
+inline PyObject* VM::_py_generator(Frame&& frame, ArgsView buffer){
+    return VAR_T(Generator, std::move(frame), buffer);
 }
 
 } // namespace pkpy

+ 0 - 12
src/linalg.h

@@ -204,12 +204,6 @@ struct Mat3x3{
     }
 
     /*************** affine transformations ***************/
-    static Mat3x3 translate(Vec2 v){
-        return Mat3x3(1.0f, 0.0f, v.x,
-                      0.0f, 1.0f, v.y,
-                      0.0f, 0.0f, 1.0f);
-    }
-
     static Mat3x3 rotate(float radian){
         float cr = cosf(radian);
         float sr = sinf(radian);
@@ -218,12 +212,6 @@ struct Mat3x3{
                       0.0f, 0.0f, 1.0f);
     }
 
-    static Mat3x3 scale(Vec2 s){
-        return Mat3x3(s.x,  0.0f,   0.0f,
-                      0.0f, s.y,    0.0f,
-                      0.0f, 0.0f,   1.0f);
-    }
-
     static Mat3x3 trs(Vec2 t, float radian, Vec2 s){
         float cr = cosf(radian);
         float sr = sinf(radian);

+ 2 - 5
src/memory.h

@@ -246,16 +246,13 @@ inline size_t memory_usage(){
     return pool64.allocated_size() + pool128.allocated_size();
 }
 
-#define SP_MALLOC(size) pool128.alloc(size)
-#define SP_FREE(p) pool128.dealloc(p)
-
 template <typename T>
 struct shared_ptr {
     int* counter;
 
     T* _t() const noexcept { return (T*)(counter + 1); }
     void _inc_counter() { if(counter) ++(*counter); }
-    void _dec_counter() { if(counter && --(*counter) == 0) {((T*)(counter + 1))->~T(); SP_FREE(counter);} }
+    void _dec_counter() { if(counter && --(*counter) == 0) {((T*)(counter + 1))->~T(); pool128.dealloc(counter);} }
 
 public:
     shared_ptr() : counter(nullptr) {}
@@ -307,7 +304,7 @@ public:
 
 template <typename T, typename... Args>
 shared_ptr<T> make_sp(Args&&... args) {
-    int* p = (int*)SP_MALLOC(sizeof(int) + sizeof(T));
+    int* p = (int*)pool128.alloc(sizeof(int) + sizeof(T));
     *p = 1;
     new(p+1) T(std::forward<Args>(args)...);
     return shared_ptr<T>(p);

+ 3 - 2
src/namedict.h

@@ -6,7 +6,7 @@
 
 namespace pkpy{
 
-const std::vector<uint16_t> kHashSeeds = {9629, 43049, 13267, 59509, 39251, 1249, 27689, 9719, 19913};
+const uint16_t kHashSeeds[] = {9629, 43049, 13267, 59509, 39251, 1249, 27689, 9719, 19913};
 
 #define _hash(key, mask, hash_seed) ( ( (key).index * (hash_seed) >> 8 ) & (mask) )
 
@@ -15,7 +15,8 @@ inline uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vector<StrN
     static std::set<uint16_t> indices;
     indices.clear();
     std::pair<uint16_t, float> best_score = {kHashSeeds[0], 0.0f};
-    for(int i=0; i<kHashSeeds.size(); i++){
+    const int kHashSeedsSize = sizeof(kHashSeeds) / sizeof(kHashSeeds[0]);
+    for(int i=0; i<kHashSeedsSize; i++){
         indices.clear();
         for(auto key: keys){
             uint16_t index = _hash(key, capacity-1, kHashSeeds[i]);

+ 0 - 9
src/obj.h

@@ -115,15 +115,6 @@ struct Slice {
     Slice(PyObject* start, PyObject* stop, PyObject* step) : start(start), stop(stop), step(step) {}
 };
 
-class BaseIter {
-protected:
-    VM* vm;
-public:
-    BaseIter(VM* vm) : vm(vm) {}
-    virtual PyObject* next() = 0;
-    virtual ~BaseIter() = default;
-};
-
 struct GCHeader {
     bool enabled;   // whether this object is managed by GC
     bool marked;    // whether this object is marked

+ 10 - 12
src/pocketpy.h

@@ -223,10 +223,7 @@ inline void init_builtins(VM* _vm) {
         return VAR(r);
     });
 
-    _vm->bind__iter__(_vm->tp_range, [](VM* vm, PyObject* obj) {
-        return vm->PyIter(RangeIter(vm, obj));
-    });
-
+    _vm->bind__iter__(_vm->tp_range, [](VM* vm, PyObject* obj) { return VAR_T(RangeIter, OBJ_GET(Range, obj)); });
     _vm->bind__repr__(_vm->_type("NoneType"), [](VM* vm, PyObject* obj) { return VAR("None"); });
     _vm->bind__json__(_vm->_type("NoneType"), [](VM* vm, PyObject* obj) { return VAR("null"); });
 
@@ -373,7 +370,7 @@ inline void init_builtins(VM* _vm) {
         return self.index(other) != -1;
     });
     _vm->bind__str__(_vm->tp_str, [](VM* vm, PyObject* obj) { return obj; });
-    _vm->bind__iter__(_vm->tp_str, [](VM* vm, PyObject* obj) { return vm->PyIter(StringIter(vm, obj)); });
+    _vm->bind__iter__(_vm->tp_str, [](VM* vm, PyObject* obj) { return VAR_T(StringIter, obj); });
     _vm->bind__repr__(_vm->tp_str, [](VM* vm, PyObject* obj) {
         const Str& self = _CAST(Str&, obj);
         return VAR(self.escape(true));
@@ -551,7 +548,8 @@ inline void init_builtins(VM* _vm) {
         return (i64)_CAST(List&, obj).size();
     });
     _vm->bind__iter__(_vm->tp_list, [](VM* vm, PyObject* obj) {
-        return vm->PyIter(ArrayIter<List>(vm, obj));
+        List& self = _CAST(List&, obj);
+        return VAR_T(ArrayIter, obj, self.begin(), self.end());
     });
     _vm->bind__getitem__(_vm->tp_list, PyArrayGetItem<List>);
     _vm->bind__setitem__(_vm->tp_list, [](VM* vm, PyObject* obj, PyObject* index, PyObject* value){
@@ -584,13 +582,13 @@ inline void init_builtins(VM* _vm) {
         return x;
     });
 
-    _vm->bind__iter__(_vm->tp_tuple, [](VM* vm, PyObject* self) {
-        return vm->PyIter(ArrayIter<Tuple>(vm, self));
+    _vm->bind__iter__(_vm->tp_tuple, [](VM* vm, PyObject* obj) {
+        Tuple& self = _CAST(Tuple&, obj);
+        return VAR_T(ArrayIter, obj, self.begin(), self.end());
     });
     _vm->bind__getitem__(_vm->tp_tuple, PyArrayGetItem<Tuple>);
-    _vm->bind__len__(_vm->tp_tuple, [](VM* vm, PyObject* self) {
-        const Tuple& tuple = _CAST(Tuple&, self);
-        return (i64)tuple.size();
+    _vm->bind__len__(_vm->tp_tuple, [](VM* vm, PyObject* obj) {
+        return (i64)_CAST(Tuple&, obj).size();
     });
 
     /************ bool ************/
@@ -1068,7 +1066,7 @@ struct ReMatch {
     ReMatch(i64 start, i64 end, std::cmatch m) : start(start), end(end), m(m) {}
 
     static void _register(VM* vm, PyObject* mod, PyObject* type){
-        vm->bind_constructor<-1>(type, CPP_NOT_IMPLEMENTED());
+        vm->bind_notimplemented_constructor<ReMatch>(type);
         vm->bind_method<0>(type, "start", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).start)));
         vm->bind_method<0>(type, "end", CPP_LAMBDA(VAR(_CAST(ReMatch&, args[0]).end)));
 

+ 15 - 31
src/vm.h

@@ -48,19 +48,6 @@ inline int set_read_file_cwd(ReadFileCwdFunc func) { _read_file_cwd = func; retu
     inline PyObject* py_var(VM* vm, ctype&& value) { return vm->heap.gcnew(vm->ptype, std::move(value));}
 
 
-class Generator final: public BaseIter {
-    Frame frame;
-    int state;      // 0,1,2
-    List s_backup;
-public:
-    Generator(VM* vm, Frame&& frame, ArgsView buffer): BaseIter(vm), frame(std::move(frame)), state(0) {
-        for(PyObject* obj: buffer) s_backup.push_back(obj);
-    }
-
-    PyObject* next() override;
-    void _gc_mark() const;
-};
-
 struct PyTypeInfo{
     PyObject* obj;
     Type base;
@@ -144,7 +131,7 @@ public:
     // for quick access
     Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str;
     Type tp_list, tp_tuple;
-    Type tp_function, tp_native_func, tp_iterator, tp_bound_method;
+    Type tp_function, tp_native_func, tp_bound_method;
     Type tp_slice, tp_range, tp_module;
     Type tp_super, tp_exception, tp_bytes, tp_mappingproxy;
     Type tp_dict;
@@ -189,7 +176,6 @@ public:
     }
 
     PyObject* py_iter(PyObject* obj){
-        if(is_type(obj, tp_iterator)) return obj;
         const PyTypeInfo* ti = _inst_type_info(obj);
         if(ti->m__iter__) return ti->m__iter__(this, obj);
         PyObject* self;
@@ -477,12 +463,20 @@ public:
 
     template<typename T, typename __T>
     PyObject* bind_default_constructor(__T&& type) {
-        return bind_constructor<-1>(std::forward<__T>(type), [](VM* vm, ArgsView args){
+        return bind_constructor<1>(std::forward<__T>(type), [](VM* vm, ArgsView args){
             Type t = OBJ_GET(Type, args[0]);
             return vm->heap.gcnew<T>(t, T());
         });
     }
 
+    template<typename T, typename __T>
+    PyObject* bind_notimplemented_constructor(__T&& type) {
+        return bind_constructor<-1>(std::forward<__T>(type), [](VM* vm, ArgsView args){
+            vm->NotImplementedError();
+            return vm->None;
+        });
+    }
+
     template<int ARGC>
     PyObject* bind_builtin_func(Str name, NativeFuncC fn) {
         return bind_func<ARGC>(builtins, name, fn);
@@ -496,17 +490,9 @@ public:
         return index;
     }
 
-    template<typename P>
-    PyObject* PyIter(P&& value) {
-        static_assert(std::is_base_of_v<BaseIter, std::decay_t<P>>);
-        return heap.gcnew<P>(tp_iterator, std::forward<P>(value));
-    }
-
     PyObject* PyIterNext(PyObject* obj){
-        if(is_non_tagged_type(obj, tp_iterator)){
-            BaseIter* iter = static_cast<BaseIter*>(obj->value());
-            return iter->next();
-        }
+        const PyTypeInfo* ti = _inst_type_info(obj);
+        if(ti->m__next__) return ti->m__next__(this, obj);
         return call_method(obj, __next__);
     }
     
@@ -600,6 +586,7 @@ public:
     void _error(Exception);
     PyObject* _run_top_frame();
     void post_init();
+    PyObject* _py_generator(Frame&& frame, ArgsView buffer);
 };
 
 inline PyObject* NativeFunc::operator()(VM* vm, ArgsView args) const{
@@ -1049,7 +1036,6 @@ inline void VM::init_builtin_types(){
     tp_module = _new_type_object("module");
     tp_function = _new_type_object("function");
     tp_native_func = _new_type_object("native_func");
-    tp_iterator = _new_type_object("iterator");
     tp_bound_method = _new_type_object("bound_method");
     tp_super = _new_type_object("super");
     tp_exception = _new_type_object("Exception");
@@ -1255,12 +1241,10 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
     
     if(co->is_generator){
         s_data.reset(p0);
-        PyObject* ret = PyIter(Generator(
-            this,
+        return _py_generator(
             Frame(&s_data, nullptr, co, fn._module, callable),
             ArgsView(buffer, buffer + co_nlocals)
-        ));
-        return ret;
+        );
     }
 
     // copy buffer back to stack