This commit is contained in:
blueloveTH 2023-07-02 15:50:00 +08:00
parent efb7fce3c1
commit c32be30009
4 changed files with 112 additions and 114 deletions

View File

@ -47,6 +47,10 @@ struct CodeBlock {
type(type), parent(parent), for_loop_depth(for_loop_depth), start(start), end(-1) {} type(type), parent(parent), for_loop_depth(for_loop_depth), start(start), end(-1) {}
}; };
struct CodeObject;
typedef shared_ptr<CodeObject> CodeObject_;
struct FuncDecl;
using FuncDecl_ = shared_ptr<FuncDecl>;
struct CodeObjectSerializer{ struct CodeObjectSerializer{
std::string buffer; std::string buffer;
@ -107,4 +111,98 @@ struct CodeObject {
Str serialize(VM* vm) const; 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<int> args; // indices in co->varnames
pod_vector<KwArg> 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 <typename T>
void set_userdata(T data) {
static_assert(std::is_trivially_copyable_v<T>);
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 <typename T>
T get_userdata() const {
static_assert(std::is_trivially_copyable_v<T>);
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<const T&>(_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_<Function> 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_<NativeFunc> 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<typename T>
T lambda_get_userdata(PyObject** p){
if(p[-1] != PY_NULL) return PK_OBJ_GET(NativeFunc, p[-1]).get_userdata<T>();
else return PK_OBJ_GET(NativeFunc, p[-2]).get_userdata<T>();
}
} // namespace pkpy } // namespace pkpy

View File

@ -6,9 +6,6 @@
namespace pkpy { namespace pkpy {
struct CodeObject;
typedef shared_ptr<CodeObject> CodeObject_;
struct Frame; struct Frame;
class VM; class VM;
@ -18,70 +15,6 @@ using NativeFuncC = std::function<PyObject*(VM*, ArgsView)>;
typedef PyObject* (*NativeFuncC)(VM*, ArgsView); typedef PyObject* (*NativeFuncC)(VM*, ArgsView);
#endif #endif
struct FuncDecl {
struct KwArg {
int key; // index in co->varnames
PyObject* value; // default value
};
CodeObject_ code; // code object of this function
pod_vector<int> args; // indices in co->varnames
pod_vector<KwArg> 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<FuncDecl>;
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 <typename T>
void set_userdata(T data) {
static_assert(std::is_trivially_copyable_v<T>);
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 <typename T>
T get_userdata() const {
static_assert(std::is_trivially_copyable_v<T>);
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<const T&>(_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 { struct BoundMethod {
PyObject* self; PyObject* self;
PyObject* func; PyObject* func;
@ -365,32 +298,6 @@ struct Py_<Slice> final: PyObject {
} }
}; };
template<>
struct Py_<Function> 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_<NativeFunc> 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<> template<>
struct Py_<Super> final: PyObject { struct Py_<Super> final: PyObject {
Super _value; Super _value;
@ -427,10 +334,4 @@ struct Py_<DummyModule> final: PyObject {
void _obj_gc_mark() override {} void _obj_gc_mark() override {}
}; };
template<typename T>
T lambda_get_userdata(PyObject** p){
if(p[-1] != PY_NULL) return PK_OBJ_GET(NativeFunc, p[-1]).get_userdata<T>();
else return PK_OBJ_GET(NativeFunc, p[-2]).get_userdata<T>();
}
} // namespace pkpy } // namespace pkpy

View File

@ -154,4 +154,18 @@ void CodeObjectSerializer::write_code(VM* vm, const CodeObject* co){
buffer += END; 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 } // namespace pkpy

View File

@ -1,21 +1,6 @@
#include "pocketpy/obj.h" #include "pocketpy/obj.h"
namespace pkpy{ 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() { PyObject::~PyObject() {
if(_attr == nullptr) return; if(_attr == nullptr) return;
_attr->~NameDict(); _attr->~NameDict();