mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 20:10:17 +00:00
Merge branch 'main' into c_binding_api
This commit is contained in:
commit
b4769d77ea
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@ -46,6 +46,8 @@ jobs:
|
|||||||
run: python3 scripts/run_tests.py
|
run: python3 scripts/run_tests.py
|
||||||
- name: Benchmark
|
- name: Benchmark
|
||||||
run: python3 scripts/run_tests.py benchmark
|
run: python3 scripts/run_tests.py benchmark
|
||||||
|
- name: GCC Build Test
|
||||||
|
run: g++ -o pocketpy --std=c++17 src/main.cpp
|
||||||
build_macos:
|
build_macos:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
|
81
src/cffi.h
81
src/cffi.h
@ -5,72 +5,25 @@
|
|||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
// template<typename Ret, typename... Params>
|
#define PY_CLASS(T, mod, name) \
|
||||||
// struct NativeProxyFunc {
|
static Type _type(VM* vm) { \
|
||||||
// static constexpr int N = sizeof...(Params);
|
static const StrName __x0(#mod); \
|
||||||
// using _Fp = Ret(*)(Params...);
|
static const StrName __x1(#name); \
|
||||||
// _Fp func;
|
return OBJ_GET(Type, vm->_modules[__x0]->attr(__x1)); \
|
||||||
// NativeProxyFunc(_Fp func) : func(func) {}
|
} \
|
||||||
|
static PyObject* register_class(VM* vm, PyObject* mod) { \
|
||||||
|
PyObject* type = vm->new_type_object(mod, #name, vm->tp_object); \
|
||||||
|
if(OBJ_NAME(mod) != #mod) { \
|
||||||
|
auto msg = fmt("register_class() failed: ", OBJ_NAME(mod), " != ", #mod); \
|
||||||
|
throw std::runtime_error(msg); \
|
||||||
|
} \
|
||||||
|
T::_register(vm, mod, type); \
|
||||||
|
type->attr()._try_perfect_rehash(); \
|
||||||
|
return type; \
|
||||||
|
}
|
||||||
|
|
||||||
// PyObject* operator()(VM* vm, ArgsView args) {
|
#define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), T(__VA_ARGS__))
|
||||||
// if (args.size() != N) {
|
|
||||||
// vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(args.size()));
|
|
||||||
// }
|
|
||||||
// return call<Ret>(vm, args, std::make_index_sequence<N>());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// template<typename __Ret, size_t... Is>
|
|
||||||
// std::enable_if_t<std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
|
||||||
// func(py_cast<Params>(vm, args[Is])...);
|
|
||||||
// return vm->None;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// template<typename __Ret, size_t... Is>
|
|
||||||
// std::enable_if_t<!std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
|
||||||
// __Ret ret = func(py_cast<Params>(vm, args[Is])...);
|
|
||||||
// return VAR(std::move(ret));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// template<typename Ret, typename T, typename... Params>
|
|
||||||
// struct NativeProxyMethod {
|
|
||||||
// static constexpr int N = sizeof...(Params);
|
|
||||||
// using _Fp = Ret(T::*)(Params...);
|
|
||||||
// _Fp func;
|
|
||||||
// NativeProxyMethod(_Fp func) : func(func) {}
|
|
||||||
|
|
||||||
// PyObject* operator()(VM* vm, ArgsView args) {
|
|
||||||
// int actual_size = args.size() - 1;
|
|
||||||
// if (actual_size != N) {
|
|
||||||
// vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(actual_size));
|
|
||||||
// }
|
|
||||||
// return call<Ret>(vm, args, std::make_index_sequence<N>());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// template<typename __Ret, size_t... Is>
|
|
||||||
// std::enable_if_t<std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
|
||||||
// T& self = py_cast<T&>(vm, args[0]);
|
|
||||||
// (self.*func)(py_cast<Params>(vm, args[Is+1])...);
|
|
||||||
// return vm->None;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// template<typename __Ret, size_t... Is>
|
|
||||||
// std::enable_if_t<!std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
|
||||||
// T& self = py_cast<T&>(vm, args[0]);
|
|
||||||
// __Ret ret = (self.*func)(py_cast<Params>(vm, args[Is+1])...);
|
|
||||||
// return VAR(std::move(ret));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// template<typename Ret, typename... Params>
|
|
||||||
// auto native_proxy_callable(Ret(*func)(Params...)) {
|
|
||||||
// return NativeProxyFunc<Ret, Params...>(func);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// template<typename Ret, typename T, typename... Params>
|
|
||||||
// auto native_proxy_callable(Ret(T::*func)(Params...)) {
|
|
||||||
// return NativeProxyMethod<Ret, T, Params...>(func);
|
|
||||||
// }
|
|
||||||
|
|
||||||
struct VoidP{
|
struct VoidP{
|
||||||
PY_CLASS(VoidP, c, void_p)
|
PY_CLASS(VoidP, c, void_p)
|
||||||
|
46
src/gc.h
46
src/gc.h
@ -116,50 +116,4 @@ inline void FuncDecl::_gc_mark() const{
|
|||||||
for(int i=0; i<kwargs.size(); i++) OBJ_MARK(kwargs[i].value);
|
for(int i=0; i<kwargs.size(); i++) OBJ_MARK(kwargs[i].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline void gc_mark<List>(List& t){
|
|
||||||
for(PyObject* obj: t){
|
|
||||||
OBJ_MARK(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> inline void gc_mark<Tuple>(Tuple& t){
|
|
||||||
for(PyObject* obj: t){
|
|
||||||
OBJ_MARK(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> inline void gc_mark<NameDict>(NameDict& t){
|
|
||||||
if(t.size() == 0) return;
|
|
||||||
for(uint16_t i=0; i<t._capacity; i++){
|
|
||||||
if(t._items[i].first.empty()) continue;
|
|
||||||
OBJ_MARK(t._items[i].second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> inline void gc_mark<MappingProxy>(MappingProxy& t){
|
|
||||||
OBJ_MARK(t.obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> inline void gc_mark<BoundMethod>(BoundMethod& t){
|
|
||||||
OBJ_MARK(t.self);
|
|
||||||
OBJ_MARK(t.func);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> inline void gc_mark<Slice>(Slice& t){
|
|
||||||
OBJ_MARK(t.start);
|
|
||||||
OBJ_MARK(t.stop);
|
|
||||||
OBJ_MARK(t.step);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> inline void gc_mark<Function>(Function& t){
|
|
||||||
t.decl->_gc_mark();
|
|
||||||
if(t._module != nullptr) OBJ_MARK(t._module);
|
|
||||||
if(t._closure != nullptr) gc_mark<NameDict>(*t._closure);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> inline void gc_mark<Super>(Super& t){
|
|
||||||
OBJ_MARK(t.first);
|
|
||||||
}
|
|
||||||
// NOTE: std::function may capture some PyObject*, they can not be marked
|
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
8
src/io.h
8
src/io.h
@ -31,16 +31,16 @@ struct FileIO {
|
|||||||
bool is_text() const { return mode != "rb" && mode != "wb" && mode != "ab"; }
|
bool is_text() const { return mode != "rb" && mode != "wb" && mode != "ab"; }
|
||||||
|
|
||||||
FileIO(VM* vm, Str file, Str mode): file(file), mode(mode) {
|
FileIO(VM* vm, Str file, Str mode): file(file), mode(mode) {
|
||||||
std::ios_base::openmode extra = 0;
|
std::ios_base::openmode extra = static_cast<std::ios_base::openmode>(0);
|
||||||
if(mode == "rb" || mode == "wb" || mode == "ab"){
|
if(mode == "rb" || mode == "wb" || mode == "ab"){
|
||||||
extra |= std::ios::binary;
|
extra |= std::ios::binary;
|
||||||
}
|
}
|
||||||
if(mode == "rt" || mode == "r" || mode == "rb"){
|
if(mode == "rt" || mode == "r" || mode == "rb"){
|
||||||
_fs.open(file.sv(), std::ios::in | extra);
|
_fs.open(file.str(), std::ios::in | extra);
|
||||||
}else if(mode == "wt" || mode == "w" || mode == "wb"){
|
}else if(mode == "wt" || mode == "w" || mode == "wb"){
|
||||||
_fs.open(file.sv(), std::ios::out | extra);
|
_fs.open(file.str(), std::ios::out | extra);
|
||||||
}else if(mode == "at" || mode == "a" || mode == "ab"){
|
}else if(mode == "at" || mode == "a" || mode == "ab"){
|
||||||
_fs.open(file.sv(), std::ios::app | extra);
|
_fs.open(file.str(), std::ios::app | extra);
|
||||||
}else{
|
}else{
|
||||||
vm->ValueError("invalid mode");
|
vm->ValueError("invalid mode");
|
||||||
}
|
}
|
||||||
|
11
src/iter.h
11
src/iter.h
@ -41,7 +41,7 @@ public:
|
|||||||
return array->operator[](index++);
|
return array->operator[](index++);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gc_mark() const override {
|
void _gc_mark() const{
|
||||||
OBJ_MARK(ref);
|
OBJ_MARK(ref);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -60,7 +60,7 @@ public:
|
|||||||
return VAR(str->u8_getitem(index++));
|
return VAR(str->u8_getitem(index++));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gc_mark() const override {
|
void _gc_mark() const{
|
||||||
OBJ_MARK(ref);
|
OBJ_MARK(ref);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -95,11 +95,4 @@ inline void Generator::_gc_mark() const{
|
|||||||
for(PyObject* obj: s_backup) OBJ_MARK(obj);
|
for(PyObject* obj: s_backup) OBJ_MARK(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void gc_mark(T& t) {
|
|
||||||
if constexpr(std::is_base_of_v<BaseIter, T>){
|
|
||||||
t._gc_mark();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
@ -38,7 +38,13 @@ constexpr TokenIndex TK(const char token[]) {
|
|||||||
while(*i && *j && *i == *j) { i++; j++;}
|
while(*i && *j && *i == *j) { i++; j++;}
|
||||||
if(*i == *j) return k;
|
if(*i == *j) return k;
|
||||||
}
|
}
|
||||||
|
#ifdef __GNUC__
|
||||||
|
// for old version of gcc, it is not smart enough to ignore FATAL_ERROR()
|
||||||
|
// so we must do a normal return
|
||||||
|
return 255;
|
||||||
|
#else
|
||||||
FATAL_ERROR();
|
FATAL_ERROR();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TK_STR(t) kTokens[t]
|
#define TK_STR(t) kTokens[t]
|
||||||
|
194
src/obj.h
194
src/obj.h
@ -103,7 +103,6 @@ protected:
|
|||||||
VM* vm;
|
VM* vm;
|
||||||
public:
|
public:
|
||||||
BaseIter(VM* vm) : vm(vm) {}
|
BaseIter(VM* vm) : vm(vm) {}
|
||||||
virtual void _gc_mark() const {}
|
|
||||||
virtual PyObject* next() = 0;
|
virtual PyObject* next() = 0;
|
||||||
virtual ~BaseIter() = default;
|
virtual ~BaseIter() = default;
|
||||||
};
|
};
|
||||||
@ -125,7 +124,8 @@ struct PyObject{
|
|||||||
virtual void* value() = 0;
|
virtual void* value() = 0;
|
||||||
virtual void _obj_gc_mark() = 0;
|
virtual void _obj_gc_mark() = 0;
|
||||||
|
|
||||||
PyObject(Type type) : type(type) {}
|
PyObject(Type type) : type(type), _attr(nullptr) {}
|
||||||
|
|
||||||
virtual ~PyObject() {
|
virtual ~PyObject() {
|
||||||
if(_attr == nullptr) return;
|
if(_attr == nullptr) return;
|
||||||
_attr->~NameDict();
|
_attr->~NameDict();
|
||||||
@ -137,46 +137,45 @@ struct PyObject{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename, typename=void> struct has_gc_marker : std::false_type {};
|
||||||
void gc_mark(T& t);
|
template <typename T> struct has_gc_marker<T, std::void_t<decltype(&T::_gc_mark)>> : std::true_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Py_ final: PyObject {
|
struct Py_ final: PyObject {
|
||||||
T _value;
|
T _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
Py_(Type type, const T& val): PyObject(type), _value(val) { _init(); }
|
void _obj_gc_mark() override {
|
||||||
Py_(Type type, T&& val): PyObject(type), _value(std::move(val)) { _init(); }
|
if constexpr (has_gc_marker<T>::value) {
|
||||||
|
_value._gc_mark();
|
||||||
void _init() noexcept {
|
|
||||||
if constexpr (std::is_same_v<T, Type> || std::is_same_v<T, DummyModule>) {
|
|
||||||
_attr = new(pool64.alloc<NameDict>()) NameDict(kTypeAttrLoadFactor);
|
|
||||||
}else if constexpr(std::is_same_v<T, DummyInstance>){
|
|
||||||
_attr = new(pool64.alloc<NameDict>()) NameDict(kInstAttrLoadFactor);
|
|
||||||
}else if constexpr(std::is_same_v<T, Function> || std::is_same_v<T, NativeFunc>){
|
|
||||||
_attr = new(pool64.alloc<NameDict>()) NameDict(kInstAttrLoadFactor);
|
|
||||||
}else{
|
|
||||||
_attr = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void* value() override { return &_value; }
|
Py_(Type type, const T& value) : PyObject(type), _value(value) {}
|
||||||
|
Py_(Type type, T&& value) : PyObject(type), _value(std::move(value)) {}
|
||||||
void _obj_gc_mark() override {
|
|
||||||
if(gc.marked) return;
|
|
||||||
gc.marked = true;
|
|
||||||
if(_attr != nullptr) pkpy::gc_mark<NameDict>(*_attr);
|
|
||||||
pkpy::gc_mark<T>(_value); // handle PyObject* inside _value `T`
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MappingProxy{
|
struct MappingProxy{
|
||||||
PyObject* obj;
|
PyObject* obj;
|
||||||
MappingProxy(PyObject* obj) : obj(obj) {}
|
MappingProxy(PyObject* obj) : obj(obj) {}
|
||||||
|
|
||||||
NameDict& attr() noexcept { return obj->attr(); }
|
NameDict& attr() noexcept { return obj->attr(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value)
|
#define OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value)
|
||||||
#define OBJ_MARK(obj) if(!is_tagged(obj)) (obj)->_obj_gc_mark()
|
// #define OBJ_GET(T, obj) (*reinterpret_cast<T*>((obj)->value()))
|
||||||
|
|
||||||
|
#define OBJ_MARK(obj) \
|
||||||
|
if(!is_tagged(obj) && !(obj)->gc.marked) { \
|
||||||
|
(obj)->gc.marked = true; \
|
||||||
|
(obj)->_obj_gc_mark(); \
|
||||||
|
if((obj)->is_attr_valid()) gc_mark_namedict((obj)->attr()); \
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void gc_mark_namedict(NameDict& t){
|
||||||
|
if(t.size() == 0) return;
|
||||||
|
for(uint16_t i=0; i<t._capacity; i++){
|
||||||
|
if(t._items[i].first.empty()) continue;
|
||||||
|
OBJ_MARK(t._items[i].second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Str obj_type_name(VM* vm, Type type);
|
Str obj_type_name(VM* vm, Type type);
|
||||||
|
|
||||||
@ -209,23 +208,6 @@ inline bool is_non_tagged_type(PyObject* obj, Type type) {
|
|||||||
return !is_tagged(obj) && obj->type == type;
|
return !is_tagged(obj) && obj->type == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PY_CLASS(T, mod, name) \
|
|
||||||
static Type _type(VM* vm) { \
|
|
||||||
static const StrName __x0(#mod); \
|
|
||||||
static const StrName __x1(#name); \
|
|
||||||
return OBJ_GET(Type, vm->_modules[__x0]->attr(__x1)); \
|
|
||||||
} \
|
|
||||||
static PyObject* register_class(VM* vm, PyObject* mod) { \
|
|
||||||
PyObject* type = vm->new_type_object(mod, #name, vm->tp_object); \
|
|
||||||
if(OBJ_NAME(mod) != #mod) { \
|
|
||||||
auto msg = fmt("register_class() failed: ", OBJ_NAME(mod), " != ", #mod); \
|
|
||||||
throw std::runtime_error(msg); \
|
|
||||||
} \
|
|
||||||
T::_register(vm, mod, type); \
|
|
||||||
type->attr()._try_perfect_rehash(); \
|
|
||||||
return type; \
|
|
||||||
}
|
|
||||||
|
|
||||||
union BitsCvt {
|
union BitsCvt {
|
||||||
i64 _int;
|
i64 _int;
|
||||||
f64 _float;
|
f64 _float;
|
||||||
@ -265,8 +247,130 @@ __T _py_cast(VM* vm, PyObject* obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define VAR(x) py_var(vm, x)
|
#define VAR(x) py_var(vm, x)
|
||||||
#define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), T(__VA_ARGS__))
|
|
||||||
#define CAST(T, x) py_cast<T>(vm, x)
|
#define CAST(T, x) py_cast<T>(vm, x)
|
||||||
#define _CAST(T, x) _py_cast<T>(vm, x)
|
#define _CAST(T, x) _py_cast<T>(vm, x)
|
||||||
|
|
||||||
|
/*****************************************************************/
|
||||||
|
template<>
|
||||||
|
struct Py_<List> final: PyObject {
|
||||||
|
List _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
|
|
||||||
|
Py_(Type type, List&& val): PyObject(type), _value(std::move(val)) {}
|
||||||
|
Py_(Type type, const List& val): PyObject(type), _value(val) {}
|
||||||
|
|
||||||
|
void _obj_gc_mark() override {
|
||||||
|
for(PyObject* obj: _value) OBJ_MARK(obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<Tuple> final: PyObject {
|
||||||
|
Tuple _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
|
|
||||||
|
Py_(Type type, Tuple&& val): PyObject(type), _value(std::move(val)) {}
|
||||||
|
Py_(Type type, const Tuple& val): PyObject(type), _value(val) {}
|
||||||
|
|
||||||
|
void _obj_gc_mark() override {
|
||||||
|
for(PyObject* obj: _value) OBJ_MARK(obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<MappingProxy> final: PyObject {
|
||||||
|
MappingProxy _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
|
Py_(Type type, MappingProxy val): PyObject(type), _value(val) {}
|
||||||
|
void _obj_gc_mark() override {
|
||||||
|
OBJ_MARK(_value.obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<BoundMethod> final: PyObject {
|
||||||
|
BoundMethod _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
|
Py_(Type type, BoundMethod val): PyObject(type), _value(val) {}
|
||||||
|
void _obj_gc_mark() override {
|
||||||
|
OBJ_MARK(_value.self);
|
||||||
|
OBJ_MARK(_value.func);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<Slice> final: PyObject {
|
||||||
|
Slice _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
|
Py_(Type type, Slice val): PyObject(type), _value(val) {}
|
||||||
|
void _obj_gc_mark() override {
|
||||||
|
OBJ_MARK(_value.start);
|
||||||
|
OBJ_MARK(_value.stop);
|
||||||
|
OBJ_MARK(_value.step);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<Function> final: PyObject {
|
||||||
|
Function _value;
|
||||||
|
void* value() override { return &_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) OBJ_MARK(_value._module);
|
||||||
|
if(_value._closure != nullptr) gc_mark_namedict(*_value._closure);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<NativeFunc> final: PyObject {
|
||||||
|
NativeFunc _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
|
Py_(Type type, NativeFunc val): PyObject(type), _value(val) {
|
||||||
|
enable_instance_dict();
|
||||||
|
}
|
||||||
|
void _obj_gc_mark() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<Super> final: PyObject {
|
||||||
|
Super _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
|
Py_(Type type, Super val): PyObject(type), _value(val) {}
|
||||||
|
void _obj_gc_mark() override {
|
||||||
|
OBJ_MARK(_value.first);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<DummyInstance> final: PyObject {
|
||||||
|
void* value() override { return nullptr; }
|
||||||
|
Py_(Type type, DummyInstance val): PyObject(type) {
|
||||||
|
enable_instance_dict();
|
||||||
|
}
|
||||||
|
void _obj_gc_mark() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<Type> final: PyObject {
|
||||||
|
Type _value;
|
||||||
|
void* value() override { return &_value; }
|
||||||
|
Py_(Type type, Type val): PyObject(type), _value(val) {
|
||||||
|
enable_instance_dict(kTypeAttrLoadFactor);
|
||||||
|
}
|
||||||
|
void _obj_gc_mark() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Py_<DummyModule> final: PyObject {
|
||||||
|
void* value() override { return nullptr; }
|
||||||
|
Py_(Type type, DummyModule val): PyObject(type) {
|
||||||
|
enable_instance_dict(kTypeAttrLoadFactor);
|
||||||
|
}
|
||||||
|
void _obj_gc_mark() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
Loading…
x
Reference in New Issue
Block a user