diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index 4b175114..5d782c46 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -47,6 +47,10 @@ struct CodeBlock { type(type), parent(parent), for_loop_depth(for_loop_depth), start(start), end(-1) {} }; +struct CodeObject; +typedef shared_ptr CodeObject_; +struct FuncDecl; +using FuncDecl_ = shared_ptr; struct CodeObjectSerializer{ std::string buffer; @@ -107,4 +111,98 @@ struct CodeObject { Str serialize(VM* vm) const; }; +struct FuncDecl { + struct KwArg { + int key; // index in co->varnames + PyObject* value; // default value + }; + CodeObject_ code; // code object of this function + pod_vector args; // indices in co->varnames + pod_vector kwargs; // indices in co->varnames + int starred_arg = -1; // index in co->varnames, -1 if no *arg + int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg + bool nested = false; // whether this function is nested + + Str signature; // signature of this function + Str docstring; // docstring of this function + void _gc_mark() const; +}; + +struct NativeFunc { + NativeFuncC f; + + // old style argc-based call + int argc; + + // new style decl-based call + FuncDecl_ decl; + + using UserData = char[32]; + UserData _userdata; + bool _has_userdata; + + template + void set_userdata(T data) { + static_assert(std::is_trivially_copyable_v); + static_assert(sizeof(T) <= sizeof(UserData)); + if(_has_userdata) throw std::runtime_error("userdata already set"); + _has_userdata = true; + memcpy(_userdata, &data, sizeof(T)); + } + + template + T get_userdata() const { + static_assert(std::is_trivially_copyable_v); + static_assert(sizeof(T) <= sizeof(UserData)); +#if PK_DEBUG_EXTRA_CHECK + if(!_has_userdata) throw std::runtime_error("userdata not set"); +#endif + return reinterpret_cast(_userdata); + } + + NativeFunc(NativeFuncC f, int argc, bool method); + NativeFunc(NativeFuncC f, FuncDecl_ decl); + + void check_size(VM* vm, ArgsView args) const; + PyObject* call(VM* vm, ArgsView args) const; +}; + +struct Function{ + FuncDecl_ decl; + PyObject* _module; + NameDict_ _closure; +}; + +template<> +struct Py_ final: PyObject { + Function _value; + Py_(Type type, Function val): PyObject(type), _value(val) { + enable_instance_dict(); + } + void _obj_gc_mark() override { + _value.decl->_gc_mark(); + if(_value._module != nullptr) PK_OBJ_MARK(_value._module); + if(_value._closure != nullptr) gc_mark_namedict(*_value._closure); + } +}; + +template<> +struct Py_ final: PyObject { + NativeFunc _value; + Py_(Type type, NativeFunc val): PyObject(type), _value(val) { + enable_instance_dict(); + } + void _obj_gc_mark() override { + if(_value.decl != nullptr){ + _value.decl->_gc_mark(); + } + } +}; + +template +T lambda_get_userdata(PyObject** p){ + if(p[-1] != PY_NULL) return PK_OBJ_GET(NativeFunc, p[-1]).get_userdata(); + else return PK_OBJ_GET(NativeFunc, p[-2]).get_userdata(); +} + } // namespace pkpy \ No newline at end of file diff --git a/include/pocketpy/obj.h b/include/pocketpy/obj.h index 391a4e88..00dc362f 100644 --- a/include/pocketpy/obj.h +++ b/include/pocketpy/obj.h @@ -6,9 +6,6 @@ namespace pkpy { -struct CodeObject; -typedef shared_ptr CodeObject_; - struct Frame; class VM; @@ -18,70 +15,6 @@ using NativeFuncC = std::function; typedef PyObject* (*NativeFuncC)(VM*, ArgsView); #endif -struct FuncDecl { - struct KwArg { - int key; // index in co->varnames - PyObject* value; // default value - }; - CodeObject_ code; // code object of this function - pod_vector args; // indices in co->varnames - pod_vector kwargs; // indices in co->varnames - int starred_arg = -1; // index in co->varnames, -1 if no *arg - int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg - bool nested = false; // whether this function is nested - - Str signature; // signature of this function - Str docstring; // docstring of this function - void _gc_mark() const; -}; - -using FuncDecl_ = shared_ptr; - -struct NativeFunc { - NativeFuncC f; - - // old style argc-based call - int argc; - - // new style decl-based call - FuncDecl_ decl; - - using UserData = char[32]; - UserData _userdata; - bool _has_userdata; - - template - void set_userdata(T data) { - static_assert(std::is_trivially_copyable_v); - static_assert(sizeof(T) <= sizeof(UserData)); - if(_has_userdata) throw std::runtime_error("userdata already set"); - _has_userdata = true; - memcpy(_userdata, &data, sizeof(T)); - } - - template - T get_userdata() const { - static_assert(std::is_trivially_copyable_v); - static_assert(sizeof(T) <= sizeof(UserData)); -#if PK_DEBUG_EXTRA_CHECK - if(!_has_userdata) throw std::runtime_error("userdata not set"); -#endif - return reinterpret_cast(_userdata); - } - - NativeFunc(NativeFuncC f, int argc, bool method); - NativeFunc(NativeFuncC f, FuncDecl_ decl); - - void check_size(VM* vm, ArgsView args) const; - PyObject* call(VM* vm, ArgsView args) const; -}; - -struct Function{ - FuncDecl_ decl; - PyObject* _module; - NameDict_ _closure; -}; - struct BoundMethod { PyObject* self; PyObject* func; @@ -365,32 +298,6 @@ struct Py_ final: PyObject { } }; -template<> -struct Py_ final: PyObject { - Function _value; - Py_(Type type, Function val): PyObject(type), _value(val) { - enable_instance_dict(); - } - void _obj_gc_mark() override { - _value.decl->_gc_mark(); - if(_value._module != nullptr) PK_OBJ_MARK(_value._module); - if(_value._closure != nullptr) gc_mark_namedict(*_value._closure); - } -}; - -template<> -struct Py_ final: PyObject { - NativeFunc _value; - Py_(Type type, NativeFunc val): PyObject(type), _value(val) { - enable_instance_dict(); - } - void _obj_gc_mark() override { - if(_value.decl != nullptr){ - _value.decl->_gc_mark(); - } - } -}; - template<> struct Py_ final: PyObject { Super _value; @@ -427,10 +334,4 @@ struct Py_ final: PyObject { void _obj_gc_mark() override {} }; -template -T lambda_get_userdata(PyObject** p){ - if(p[-1] != PY_NULL) return PK_OBJ_GET(NativeFunc, p[-1]).get_userdata(); - else return PK_OBJ_GET(NativeFunc, p[-2]).get_userdata(); -} - } // namespace pkpy \ No newline at end of file diff --git a/src/codeobject.cpp b/src/codeobject.cpp index 2d7c03dd..95a8f3d4 100644 --- a/src/codeobject.cpp +++ b/src/codeobject.cpp @@ -154,4 +154,18 @@ void CodeObjectSerializer::write_code(VM* vm, const CodeObject* co){ buffer += END; } + NativeFunc::NativeFunc(NativeFuncC f, int argc, bool method){ + this->f = f; + this->argc = argc; + if(argc != -1) this->argc += (int)method; + _has_userdata = false; + } + + NativeFunc::NativeFunc(NativeFuncC f, FuncDecl_ decl){ + this->f = f; + this->argc = -1; + this->decl = decl; + _has_userdata = false; + } + } // namespace pkpy \ No newline at end of file diff --git a/src/obj.cpp b/src/obj.cpp index a2d0eba7..8cb04ab1 100644 --- a/src/obj.cpp +++ b/src/obj.cpp @@ -1,21 +1,6 @@ #include "pocketpy/obj.h" namespace pkpy{ - - NativeFunc::NativeFunc(NativeFuncC f, int argc, bool method){ - this->f = f; - this->argc = argc; - if(argc != -1) this->argc += (int)method; - _has_userdata = false; - } - - NativeFunc::NativeFunc(NativeFuncC f, FuncDecl_ decl){ - this->f = f; - this->argc = -1; - this->decl = decl; - _has_userdata = false; - } - PyObject::~PyObject() { if(_attr == nullptr) return; _attr->~NameDict();