From 3c098e638ffc36c8a19ee05402a63abef48b6214 Mon Sep 17 00:00:00 2001 From: BLUELOVETH Date: Sat, 11 Feb 2023 22:07:56 +0000 Subject: [PATCH] up --- src/codeobject.h | 20 ++++++------ src/common.h | 14 ++++++++- src/obj.h | 13 ++++---- src/pocketpy.h | 12 +++---- src/vm.h | 81 ++++++++++++++++++++++++++++++------------------ 5 files changed, 85 insertions(+), 55 deletions(-) diff --git a/src/codeobject.h b/src/codeobject.h index 5453f33b..6f30c038 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -138,16 +138,16 @@ struct Frame { return co->src->snapshot(line); } - Str stack_info(){ - StrStream ss; - ss << "["; - for(int i=0; i<_data.size(); i++){ - ss << OBJ_TP_NAME(_data[i]); - if(i != _data.size()-1) ss << ", "; - } - ss << "]"; - return ss.str(); - } + // Str stack_info(){ + // StrStream ss; + // ss << "["; + // for(int i=0; i<_data.size(); i++){ + // ss << OBJ_TP_NAME(_data[i]); + // if(i != _data.size()-1) ss << ", "; + // } + // ss << "]"; + // return ss.str(); + // } inline bool has_next_bytecode() const { return _next_ip < co->codes.size(); diff --git a/src/common.h b/src/common.h index dbf88cff..90e916df 100644 --- a/src/common.h +++ b/src/common.h @@ -32,7 +32,7 @@ #define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!"); #endif -#define PK_VERSION "0.8.5" +#define PK_VERSION "0.8.6" typedef int64_t i64; typedef double f64; @@ -40,6 +40,18 @@ typedef double f64; struct Dummy { char _; }; #define DUMMY_VAL Dummy() +struct Type { + int index; + Type(): index(-1) {} + Type(int index): index(index) {} + inline bool operator==(Type other) const noexcept { + return this->index == other.index; + } + inline bool operator!=(Type other) const noexcept { + return this->index != other.index; + } +}; + template void* tid() { static volatile int8_t _x; diff --git a/src/obj.h b/src/obj.h index ded3a97f..37b48915 100644 --- a/src/obj.h +++ b/src/obj.h @@ -75,17 +75,17 @@ public: }; struct PyObject { - PyVar type; + Type type; 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; } + inline bool is_type(Type type) const noexcept{ return this->type == type; } virtual void* value() = 0; - PyObject(const PyVar& type) : type(type) {} + PyObject(Type type) : type(type) {} virtual ~PyObject() { delete _attr; } }; @@ -93,8 +93,8 @@ template struct Py_ : PyObject { T _value; - Py_(const PyVar& type, T val) : PyObject(type), _value(val) { - if constexpr (std::is_same_v + Py_(Type type, T val) : PyObject(type), _value(val) { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v) { _attr = new pkpy::NameDict(); }else{ @@ -106,9 +106,8 @@ struct Py_ : PyObject { #define OBJ_GET(T, obj) (((Py_*)((obj).get()))->_value) #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]->attr(#name); } \ + inline static Type _type(VM* vm) { return OBJ_GET(Type, vm->_modules[#mod]->attr(#name)); } \ inline static const char* _mod() { return #mod; } \ inline static const char* _name() { return #name; } diff --git a/src/pocketpy.h b/src/pocketpy.h index 70173a53..937a6395 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -123,7 +123,7 @@ 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]->attr()) names.push_back(k); - for (auto& [k, _] : args[0]->type->attr()) { + for (auto& [k, _] : vm->_t(args[0])->attr()) { if (k.find("__") == 0) continue; if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k); } @@ -136,17 +136,17 @@ void init_builtins(VM* _vm) { }); _vm->bind_method<0>("object", "__repr__", [](VM* vm, const pkpy::Args& args) { - PyVar _self = args[0]; - std::stringstream ss; - ss << std::hex << (uintptr_t)_self.get(); - Str s = "<" + OBJ_TP_NAME(_self) + " object at 0x" + ss.str() + ">"; + PyVar self = args[0]; + StrStream ss; + ss << std::hex << (uintptr_t)self.get(); + Str s = "<" + OBJ_NAME(vm->_t(self)) + " object at 0x" + ss.str() + ">"; return vm->PyStr(s); }); _vm->bind_method<1>("object", "__eq__", CPP_LAMBDA(vm->PyBool(args[0] == args[1]))); _vm->bind_method<1>("object", "__ne__", CPP_LAMBDA(vm->PyBool(args[0] != args[1]))); - _vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(args[0]->type)); + _vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(vm->_t(args[0]))); _vm->bind_static_method<-1>("range", "__new__", [](VM* vm, const pkpy::Args& args) { pkpy::Range r; diff --git a/src/vm.h b/src/vm.h index 4bca3d73..d1aa9ed2 100644 --- a/src/vm.h +++ b/src/vm.h @@ -110,7 +110,7 @@ class VM { { const Str& clsName = frame->co->names[byte.arg].first; PyVar clsBase = frame->pop_value(this); - if(clsBase == None) clsBase = tp_object; + if(clsBase == None) clsBase = _t(tp_object); check_type(clsBase, tp_type); PyVar cls = new_type_object(frame->_module, clsName, clsBase); while(true){ @@ -254,7 +254,7 @@ class VM { PyIter_AS_C(tmp)->var = var; frame->push(std::move(tmp)); }else{ - TypeError(OBJ_TP_NAME(obj).escape(true) + " object is not iterable"); + TypeError(OBJ_NAME(_t(obj)).escape(true) + " object is not iterable"); } } break; case OP_FOR_ITER: @@ -398,7 +398,7 @@ public: } PyVar fast_call(const Str& name, pkpy::Args&& args){ - PyObject* cls = args[0]->type.get(); + PyObject* cls = _t(args[0]).get(); while(cls != None.get()) { PyVar* val = cls->attr().try_get(name); if(val != nullptr) return call(*val, std::move(args)); @@ -510,7 +510,7 @@ public: } return _exec(fn->code, _module, _locals); } - TypeError("'" + OBJ_TP_NAME(*callable) + "' object is not callable"); + TypeError("'" + OBJ_NAME(_t(*callable)) + "' object is not callable"); return None; } @@ -584,28 +584,37 @@ public: } } + std::vector _all_types; + PyVar new_type_object(PyVar mod, Str name, PyVar base){ if(!base->is_type(tp_type)) UNREACHABLE(); - PyVar obj = pkpy::make_shared>(tp_type, DUMMY_VAL); + PyVar obj = pkpy::make_shared>(tp_type, _all_types.size()); setattr(obj, __base__, base); Str fullName = name; if(mod != builtins) fullName = OBJ_NAME(mod) + "." + name; setattr(obj, __name__, PyStr(fullName)); setattr(mod, name, obj); + _all_types.push_back(obj); return obj; } - PyVar _new_type_object(Str name, PyVar base=nullptr) { - if(base == nullptr) base = tp_object; - PyVar obj = pkpy::make_shared>(tp_type, DUMMY_VAL); - setattr(obj, __base__, base); + Type _new_type_object(Str name, Type base=0) { + PyVar obj = pkpy::make_shared>(tp_type, _all_types.size()); + setattr(obj, __base__, _t(base)); _types[name] = obj; - return obj; + _all_types.push_back(obj); + return OBJ_GET(Type, obj); } template inline PyVar new_object(PyVar type, T _value) { if(!type->is_type(tp_type)) UNREACHABLE(); + return pkpy::make_shared>( + OBJ_GET(Type, type), _value); + } + + template + inline PyVar new_object(Type type, T _value) { return pkpy::make_shared>(type, _value); } @@ -633,7 +642,7 @@ public: if(!(*root)->is_type(tp_super)) break; depth++; } - cls = (*root)->type.get(); + cls = _t(*root).get(); for(int i=0; iattr(__base__).get(); it = (*root)->attr().find(name); @@ -643,7 +652,7 @@ public: it = obj->attr().find(name); if(it != obj->attr().end()) return it->second; } - cls = obj->type.get(); + cls = _t(obj).get(); } while(cls != None.get()) { @@ -707,7 +716,7 @@ public: }else if(obj->is_type(tp_float)){ return PyFloat_AS_C(obj); } - TypeError("expected 'int' or 'float', got " + OBJ_TP_NAME(obj).escape(true)); + TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape(true)); return 0; } @@ -793,11 +802,11 @@ public: } // for quick access - PyVar tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str; - PyVar tp_list, tp_tuple; - PyVar tp_function, tp_native_function, tp_native_iterator, tp_bound_method; - PyVar tp_slice, tp_range, tp_module, tp_ref; - PyVar tp_super, tp_exception; + Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str; + Type tp_list, tp_tuple; + Type tp_function, tp_native_function, tp_native_iterator, tp_bound_method; + Type tp_slice, tp_range, tp_module, tp_ref; + Type tp_super, tp_exception; template inline PyVarRef PyRef(P&& value) { @@ -841,10 +850,14 @@ public: inline const PyVar& PyBool(bool value){return value ? True : False;} void init_builtin_types(){ - tp_object = pkpy::make_shared>(nullptr, DUMMY_VAL); - tp_type = pkpy::make_shared>(nullptr, DUMMY_VAL); - _types["object"] = tp_object; - _types["type"] = tp_type; + PyVar _tp_object = pkpy::make_shared>(1, 0); + PyVar _tp_type = pkpy::make_shared>(1, 1); + _all_types.push_back(_tp_object); + _all_types.push_back(_tp_type); + tp_object = 0; tp_type = 1; + + _types["object"] = _tp_object; + _types["type"] = _tp_type; tp_bool = _new_type_object("bool"); tp_int = _new_type_object("int"); @@ -872,10 +885,8 @@ public: this->_main = new_module("__main__"); this->_py_op_call = new_object(_new_type_object("_internal"), DUMMY_VAL); - setattr(tp_type, __base__, tp_object); - tp_type->type = tp_type; - setattr(tp_object, __base__, None); - tp_object->type = tp_type; + setattr(_t(tp_type), __base__, _t(tp_object)); + setattr(_t(tp_object), __base__, None); for (auto& [name, type] : _types) { setattr(type, __name__, PyStr(name)); @@ -905,7 +916,7 @@ public: } return x; } - TypeError("unhashable type: " + OBJ_TP_NAME(obj).escape(true)); + TypeError("unhashable type: " + OBJ_NAME(_t(obj)).escape(true)); return 0; } @@ -939,17 +950,25 @@ public: void NameError(const Str& name){ _error("NameError", "name " + name.escape(true) + " is not defined"); } void AttributeError(PyVar obj, const Str& name){ - _error("AttributeError", "type " + OBJ_TP_NAME(obj).escape(true) + " has no attribute " + name.escape(true)); + _error("AttributeError", "type " + OBJ_NAME(_t(obj)).escape(true) + " has no attribute " + name.escape(true)); } - inline void check_type(const PyVar& obj, const PyVar& type){ + inline void check_type(const PyVar& obj, Type type){ if(obj->is_type(type)) return; - TypeError("expected " + OBJ_NAME(type).escape(true) + ", but got " + OBJ_TP_NAME(obj).escape(true)); + TypeError("expected " + OBJ_NAME(_t(type)).escape(true) + ", but got " + OBJ_NAME(_t(obj)).escape(true)); + } + + inline PyVar& _t(Type t){ + return _all_types[t.index]; + } + + inline PyVar& _t(const PyVar& obj){ + return _all_types[OBJ_GET(Type, _t(obj->type)).index]; } template PyVar register_class(PyVar mod){ - PyVar type = new_type_object(mod, T::_name(), tp_object); + PyVar type = new_type_object(mod, T::_name(), _t(tp_object)); if(OBJ_NAME(mod) != T::_mod()) UNREACHABLE(); T::_register(this, mod, type); return type;