diff --git a/src/codeobject.h b/src/codeobject.h index f1f32cdf..5453f33b 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -123,7 +123,7 @@ struct Frame { std::stack>> 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 _locals) : co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { } diff --git a/src/obj.h b/src/obj.h index e70df6d8..ded3a97f 100644 --- a/src/obj.h +++ b/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 struct Py_ : PyObject { T _value; - Py_(const PyVar& type, T val) : PyObject(type, tid()), _value(val) {} + Py_(const PyVar& type, T val) : PyObject(type), _value(val) { + if constexpr (std::is_same_v + || std::is_same_v || std::is_same_v) { + _attr = new pkpy::NameDict(); + }else{ + _attr = nullptr; + } + } void* value() override { return &_value; } }; #define OBJ_GET(T, obj) (((Py_*)((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> _obj_pool; - -namespace pkpy { - template<> - struct sp_deleter { - inline static void call(int* counter) { - PyObject* obj = (PyObject*)(counter + 1); - std::vector& pool = _obj_pool[obj->_tid]; - if(obj->_tid==tid() || pool.size() > 32){ - obj->~PyObject(); - free(counter); - }else{ - pool.push_back(counter); - } - } - }; -} \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index b2e8b09e..70173a53 100644 --- a/src/pocketpy.h +++ b/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 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()); diff --git a/src/str.h b/src/str.h index b4c33e81..bc08eab7 100644 --- a/src/str.h +++ b/src/str.h @@ -13,11 +13,10 @@ class Str : public std::string { if(_u8_index != nullptr) return; _u8_index = new std::vector(); _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(*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 { diff --git a/src/vm.h b/src/vm.h index 2d6b2040..3c74b383 100644 --- a/src/vm.h +++ b/src/vm.h @@ -17,7 +17,7 @@ class VM { std::stack< std::unique_ptr > 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; ipop_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("attribs[__name__]) + "'>"); + if(obj->is_type(tp_type)) return PyStr("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 inline PyVar new_object(PyVar type, T _value) { if(!type->is_type(tp_type)) UNREACHABLE(); - if constexpr (std::is_same_v) return pkpy::make_shared>(type, _value); - std::vector& pool = _obj_pool[tid()]; - if(pool.empty()) return pkpy::make_shared>(type, _value); - int* counter = pool.back(); pool.pop_back(); - *counter = 1; - Py_* obj = (Py_*)(counter + 1); - obj->_value = std::move(_value); - obj->attribs.clear(); - return PyVar(counter); + return pkpy::make_shared>(type, _value); } template @@ -640,19 +632,21 @@ public: depth++; } cls = (*root)->type.get(); - for(int i=0; iattribs[__base__].get(); + for(int i=0; iattr(__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(p->value())->get(); - p->attribs[name] = std::forward(value); + if(!p->is_attr_valid()) TypeError("cannot set attribute"); + p->attr()[name] = std::forward(value); } template @@ -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;