blueloveTH 3 лет назад
Родитель
Сommit
340f1bb15c
5 измененных файлов с 69 добавлено и 86 удалено
  1. 1 1
      src/codeobject.h
  2. 18 28
      src/obj.h
  3. 10 10
      src/pocketpy.h
  4. 7 10
      src/str.h
  5. 33 37
      src/vm.h

+ 1 - 1
src/codeobject.h

@@ -123,7 +123,7 @@ struct Frame {
     std::stack<std::pair<int, std::vector<PyVar>>> s_try_block;
 
     inline pkpy::NameDict& f_locals() noexcept { return *_locals; }
-    inline pkpy::NameDict& f_globals() noexcept { return _module->attribs; }
+    inline pkpy::NameDict& f_globals() noexcept { return _module->attr(); }
 
     Frame(const CodeObject_ co, PyVar _module, pkpy::shared_ptr<pkpy::NameDict> _locals)
         : co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { }

+ 18 - 28
src/obj.h

@@ -76,49 +76,39 @@ public:
 
 struct PyObject {
     PyVar type;
-    pkpy::NameDict attribs;
-    void* _tid;
+    pkpy::NameDict* _attr;
+    //void* _tid;
+    inline bool is_attr_valid() const noexcept { return _attr != nullptr; }
+    inline pkpy::NameDict& attr() noexcept { return *_attr; }
+    inline PyVar& attr(const Str& name) noexcept { return (*_attr)[name]; }
 
     inline bool is_type(const PyVar& type) const noexcept{ return this->type == type; }
     virtual void* value() = 0;
 
-    PyObject(const PyVar& type, void* _tid) : type(type), _tid(_tid) {}
-    virtual ~PyObject() = default;
+    PyObject(const PyVar& type) : type(type) {}
+    virtual ~PyObject() { delete _attr; }
 };
 
 template <typename T>
 struct Py_ : PyObject {
     T _value;
 
-    Py_(const PyVar& type, T val) : PyObject(type, tid<T>()), _value(val) {}
+    Py_(const PyVar& type, T val) : PyObject(type), _value(val) {
+        if constexpr (std::is_same_v<T, Dummy>
+        || std::is_same_v<T, pkpy::Function_> || std::is_same_v<T, pkpy::NativeFunc>) {
+            _attr = new pkpy::NameDict();
+        }else{
+            _attr = nullptr;
+        }
+    }
     void* value() override { return &_value; }
 };
 
 #define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value)
-#define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attribs[__name__])
-#define OBJ_TP_NAME(obj) OBJ_GET(Str, (obj)->type->attribs[__name__])
+#define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attr(__name__))
+#define OBJ_TP_NAME(obj) OBJ_GET(Str, (obj)->type->attr(__name__))
 
 #define PY_CLASS(mod, name) \
-    inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attribs[#name]; } \
+    inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attr(#name); } \
     inline static const char* _mod() { return #mod; } \
     inline static const char* _name() { return #name; }
-
-// #define PY_BUILTIN_CLASS(name) inline static PyVar _type(VM* vm) { return vm->tp_##name; }
-
-static thread_local emhash8::HashMap<void*, std::vector<int*>> _obj_pool;
-
-namespace pkpy {
-    template<>
-    struct sp_deleter<PyObject> {
-        inline static void call(int* counter) {
-            PyObject* obj = (PyObject*)(counter + 1);
-            std::vector<int*>& pool = _obj_pool[obj->_tid];
-            if(obj->_tid==tid<Dummy>() || pool.size() > 32){
-                obj->~PyObject();
-                free(counter);
-            }else{
-                pool.push_back(counter);
-            }
-        }
-    };
-}

+ 10 - 10
src/pocketpy.h

@@ -122,8 +122,8 @@ void init_builtins(VM* _vm) {
 
     _vm->bind_builtin_func<1>("dir", [](VM* vm, const pkpy::Args& args) {
         std::vector<Str> names;
-        for (auto& [k, _] : args[0]->attribs) names.push_back(k);
-        for (auto& [k, _] : args[0]->type->attribs) {
+        for (auto& [k, _] : args[0]->attr()) names.push_back(k);
+        for (auto& [k, _] : args[0]->type->attr()) {
             if (k.find("__") == 0) continue;
             if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k);
         }
@@ -279,14 +279,14 @@ void init_builtins(VM* _vm) {
     });
 
     _vm->bind_method<0>("str", "__len__", [](VM* vm, const pkpy::Args& args) {
-        const Str& _self = vm->PyStr_AS_C(args[0]);
-        return vm->PyInt(_self.u8_length());
+        const Str& self = vm->PyStr_AS_C(args[0]);
+        return vm->PyInt(self.u8_length());
     });
 
     _vm->bind_method<1>("str", "__contains__", [](VM* vm, const pkpy::Args& args) {
-        const Str& _self = vm->PyStr_AS_C(args[0]);
-        const Str& _other = vm->PyStr_AS_C(args[1]);
-        return vm->PyBool(_self.find(_other) != Str::npos);
+        const Str& self = vm->PyStr_AS_C(args[0]);
+        const Str& other = vm->PyStr_AS_C(args[1]);
+        return vm->PyBool(self.find(other) != Str::npos);
     });
 
     _vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0]));
@@ -476,7 +476,7 @@ void init_builtins(VM* _vm) {
 
     /************ PyTuple ************/
     _vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, const pkpy::Args& args) {
-        pkpy::List _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
+        pkpy::List _list = vm->PyList_AS_C(vm->call(vm->builtins->attr("list"), args));
         return vm->PyTuple(std::move(_list));
     });
 
@@ -763,8 +763,8 @@ extern "C" {
     /// Return `__repr__` of the result.
     /// If the variable is not found, return `nullptr`.
     char* pkpy_vm_get_global(VM* vm, const char* name){
-        auto it = vm->_main->attribs.find(name);
-        if(it == vm->_main->attribs.end()) return nullptr;
+        auto it = vm->_main->attr().find(name);
+        if(it == vm->_main->attr().end()) return nullptr;
         try{
             Str _repr = vm->PyStr_AS_C(vm->asRepr(it->second));
             return strdup(_repr.c_str());

+ 7 - 10
src/str.h

@@ -13,11 +13,10 @@ class Str : public std::string {
         if(_u8_index != nullptr) return;
         _u8_index = new std::vector<uint16_t>();
         _u8_index->reserve(size());
-        if(size() > 65535) throw std::runtime_error("String has more than 65535 bytes.");
+        if(size() > 65535) throw std::runtime_error("str has more than 65535 bytes.");
         for(uint16_t i = 0; i < size(); i++){
             // https://stackoverflow.com/questions/3911536/utf-8-unicode-whats-with-0xc0-and-0x80
-            if((at(i) & 0xC0) != 0x80)
-                _u8_index->push_back(i);
+            if((at(i) & 0xC0) != 0x80) _u8_index->push_back(i);
         }
     }
 public:
@@ -35,7 +34,7 @@ public:
         }
     }
     Str(Str&& s) : std::string(std::move(s)) {
-        if(_u8_index != nullptr) delete _u8_index;
+        delete _u8_index;
         _u8_index = s._u8_index;
         s._u8_index = nullptr;
         if(s.hash_initialized){
@@ -117,8 +116,8 @@ public:
 
     Str& operator=(const Str& s){
         this->std::string::operator=(s);
-        if(_u8_index != nullptr){
-            delete _u8_index;
+        delete _u8_index;
+        if(s._u8_index != nullptr){
             _u8_index = new std::vector<uint16_t>(*s._u8_index);
         }
         this->hash_initialized = s.hash_initialized;
@@ -128,7 +127,7 @@ public:
 
     Str& operator=(Str&& s){
         this->std::string::operator=(std::move(s));
-        if(_u8_index != nullptr) delete _u8_index;
+        delete _u8_index;
         this->_u8_index = s._u8_index;
         s._u8_index = nullptr;
         this->hash_initialized = s.hash_initialized;
@@ -136,9 +135,7 @@ public:
         return *this;
     }
 
-    ~Str(){
-        if(_u8_index != nullptr) delete _u8_index;
-    }
+    ~Str(){ delete _u8_index;}
 };
 
 namespace std {

+ 33 - 37
src/vm.h

@@ -17,7 +17,7 @@
 class VM {
     std::stack< std::unique_ptr<Frame> > callstack;
     PyVar _py_op_call;
-    PyVar _ascii_str_pool[128];
+    // PyVar _ascii_str_pool[128];
 
     PyVar run_frame(Frame* frame){
         while(frame->has_next_bytecode()){
@@ -91,7 +91,7 @@ class VM {
                 frame->push(PyStr(ss.str()));
             } break;
             case OP_LOAD_EVAL_FN: {
-                frame->push(builtins->attribs[m_eval]);
+                frame->push(builtins->attr(m_eval));
             } break;
             case OP_LIST_APPEND: {
                 pkpy::Args args(2);
@@ -206,7 +206,7 @@ class VM {
             case OP_BUILD_MAP:
                 {
                     pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg*2);
-                    PyVar obj = call(builtins->attribs["dict"]);
+                    PyVar obj = call(builtins->attr("dict"));
                     for(int i=0; i<items.size(); i+=2){
                         call(obj, __setitem__, pkpy::two_args(items[i], items[i+1]));
                     }
@@ -217,7 +217,7 @@ class VM {
                     PyVar list = PyList(
                         frame->pop_n_values_reversed(this, byte.arg).to_list()
                     );
-                    PyVar obj = call(builtins->attribs["set"], pkpy::one_arg(list));
+                    PyVar obj = call(builtins->attr("set"), pkpy::one_arg(list));
                     frame->push(obj);
                 } break;
             case OP_DUP_TOP: frame->push(frame->top_value(this)); break;
@@ -363,7 +363,7 @@ public:
         }
 
         init_builtin_types();
-        for(int i=0; i<128; i++) _ascii_str_pool[i] = new_object(tp_str, std::string(1, (char)i));
+        // for(int i=0; i<128; i++) _ascii_str_pool[i] = new_object(tp_str, std::string(1, (char)i));
     }
 
     PyVar asStr(const PyVar& obj){
@@ -378,7 +378,7 @@ public:
     }
 
     PyVar asRepr(const PyVar& obj){
-        if(obj->is_type(tp_type)) return PyStr("<class '" + OBJ_GET(Str, obj->attribs[__name__]) + "'>");
+        if(obj->is_type(tp_type)) return PyStr("<class '" + OBJ_GET(Str, obj->attr(__name__)) + "'>");
         return call(obj, __repr__);
     }
 
@@ -398,9 +398,9 @@ public:
     PyVar fast_call(const Str& name, pkpy::Args&& args){
         PyObject* cls = args[0]->type.get();
         while(cls != None.get()) {
-            PyVar* val = cls->attribs.try_get(name);
+            PyVar* val = cls->attr().try_get(name);
             if(val != nullptr) return call(*val, std::move(args));
-            cls = cls->attribs[__base__].get();
+            cls = cls->attr(__base__).get();
         }
         AttributeError(args[0], name);
         return nullptr;
@@ -428,14 +428,14 @@ public:
 
     PyVar call(const PyVar& _callable, pkpy::Args args, const pkpy::Args& kwargs, bool opCall){
         if(_callable->is_type(tp_type)){
-            auto it = _callable->attribs.find(__new__);
+            PyVar* new_f = _callable->attr().try_get(__new__);
             PyVar obj;
-            if(it != _callable->attribs.end()){
-                obj = call(it->second, args, kwargs, false);
+            if(new_f != nullptr){
+                obj = call(*new_f, args, kwargs, false);
             }else{
                 obj = new_object(_callable, DUMMY_VAL);
-                PyVarOrNull init_fn = getattr(obj, __init__, false);
-                if (init_fn != nullptr) call(init_fn, args, kwargs, false);
+                PyVarOrNull init_f = getattr(obj, __init__, false);
+                if (init_f != nullptr) call(init_f, args, kwargs, false);
             }
             return obj;
         }
@@ -500,7 +500,7 @@ public:
                 locals[key] = val;
             }
 
-            PyVar* it_m = (*callable)->attribs.try_get(__module__);
+            PyVar* it_m = (*callable)->attr().try_get(__module__);
             PyVar _module = it_m != nullptr ? *it_m : top_frame()->_module;
             if(opCall){
                 _new_frame(fn->code, _module, _locals);
@@ -604,15 +604,7 @@ public:
     template<typename T>
     inline PyVar new_object(PyVar type, T _value) {
         if(!type->is_type(tp_type)) UNREACHABLE();
-        if constexpr (std::is_same_v<T, Dummy>) return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
-        std::vector<int*>& pool = _obj_pool[tid<T>()];
-        if(pool.empty()) return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
-        int* counter = pool.back(); pool.pop_back();
-        *counter = 1;
-        Py_<T>* obj = (Py_<T>*)(counter + 1);
-        obj->_value = std::move(_value);
-        obj->attribs.clear();
-        return PyVar(counter);
+        return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
     }
 
     template<typename T, typename... Args>
@@ -640,19 +632,21 @@ public:
                 depth++;
             }
             cls = (*root)->type.get();
-            for(int i=0; i<depth; i++) cls = cls->attribs[__base__].get();
+            for(int i=0; i<depth; i++) cls = cls->attr(__base__).get();
 
-            it = (*root)->attribs.find(name);
-            if(it != (*root)->attribs.end()) return it->second;        
+            it = (*root)->attr().find(name);
+            if(it != (*root)->attr().end()) return it->second;        
         }else{
-            it = obj->attribs.find(name);
-            if(it != obj->attribs.end()) return it->second;
+            if(obj->is_attr_valid()){
+                it = obj->attr().find(name);
+                if(it != obj->attr().end()) return it->second;
+            }
             cls = obj->type.get();
         }
 
         while(cls != None.get()) {
-            it = cls->attribs.find(name);
-            if(it != cls->attribs.end()){
+            it = cls->attr().find(name);
+            if(it != cls->attr().end()){
                 PyVar valueFromCls = it->second;
                 if(valueFromCls->is_type(tp_function) || valueFromCls->is_type(tp_native_function)){
                     return PyBoundMethod({obj, std::move(valueFromCls)});
@@ -660,7 +654,7 @@ public:
                     return valueFromCls;
                 }
             }
-            cls = cls->attribs[__base__].get();
+            cls = cls->attr()[__base__].get();
         }
         if(throw_err) AttributeError(obj, name);
         return nullptr;
@@ -670,7 +664,8 @@ public:
     inline void setattr(PyVar& obj, const Str& name, T&& value) {
         PyObject* p = obj.get();
         while(p->is_type(tp_super)) p = static_cast<PyVar*>(p->value())->get();
-        p->attribs[name] = std::forward<T>(value);
+        if(!p->is_attr_valid()) TypeError("cannot set attribute");
+        p->attr()[name] = std::forward<T>(value);
     }
 
     template<int ARGC>
@@ -819,10 +814,11 @@ public:
         return OBJ_GET(Str, obj);
     }
     inline PyVar PyStr(const Str& value) {
-        if(value.size() == 1){
-            char c = value.c_str()[0];
-            if(c > 0) return _ascii_str_pool[(int)c];
-        }
+        // some BUGs here
+        // if(value.size() == 1){
+        //     char c = value.c_str()[0];
+        //     if(c >= 0) return _ascii_str_pool[(int)c];
+        // }
         return new_object(tp_str, value);
     }
 
@@ -980,7 +976,7 @@ PyVar NameRef::get(VM* vm, Frame* frame) const{
     if(val) return *val;
     val = frame->f_globals().try_get(name());
     if(val) return *val;
-    val = vm->builtins->attribs.try_get(name());
+    val = vm->builtins->attr().try_get(name());
     if(val) return *val;
     vm->NameError(name());
     return nullptr;