obj.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #pragma once
  2. #include "common.h"
  3. #include "namedict.h"
  4. #include "tuplelist.h"
  5. namespace pkpy {
  6. struct CodeObject;
  7. struct Frame;
  8. struct Function;
  9. class VM;
  10. typedef std::function<PyObject*(VM*, ArgsView)> NativeFuncRaw;
  11. typedef shared_ptr<CodeObject> CodeObject_;
  12. struct NativeFunc {
  13. NativeFuncRaw f;
  14. int argc; // DONOT include self
  15. bool method;
  16. NativeFunc(NativeFuncRaw f, int argc, bool method) : f(f), argc(argc), method(method) {}
  17. PyObject* operator()(VM* vm, ArgsView args) const;
  18. };
  19. struct FuncDecl {
  20. struct KwArg {
  21. int key; // index in co->varnames
  22. PyObject* value; // default value
  23. };
  24. CodeObject_ code; // code object of this function
  25. pod_vector<int> args; // indices in co->varnames
  26. int starred_arg = -1; // index in co->varnames, -1 if no *arg
  27. pod_vector<KwArg> kwargs; // indices in co->varnames
  28. bool nested = false; // whether this function is nested
  29. void _gc_mark() const;
  30. };
  31. using FuncDecl_ = shared_ptr<FuncDecl>;
  32. struct BoundMethod {
  33. PyObject* obj;
  34. PyObject* method;
  35. BoundMethod(PyObject* obj, PyObject* method) : obj(obj), method(method) {}
  36. };
  37. struct Range {
  38. i64 start = 0;
  39. i64 stop = -1;
  40. i64 step = 1;
  41. };
  42. struct StarWrapper {
  43. PyObject* obj;
  44. StarWrapper(PyObject* obj): obj(obj) {}
  45. };
  46. using Super = std::pair<PyObject*, Type>;
  47. // TODO: re-examine the design of Slice
  48. struct Slice {
  49. int start = 0;
  50. int stop = 0x7fffffff;
  51. int step = 1;
  52. void normalize(int len){
  53. if(start < 0) start += len;
  54. if(stop < 0) stop += len;
  55. if(start < 0) start = 0;
  56. if(stop > len) stop = len;
  57. if(stop < start) stop = start;
  58. }
  59. };
  60. class BaseIter {
  61. protected:
  62. VM* vm;
  63. public:
  64. BaseIter(VM* vm) : vm(vm) {}
  65. virtual void _gc_mark() const {}
  66. virtual PyObject* next() = 0;
  67. virtual ~BaseIter() = default;
  68. };
  69. struct GCHeader {
  70. bool enabled; // whether this object is managed by GC
  71. bool marked; // whether this object is marked
  72. GCHeader() : enabled(true), marked(false) {}
  73. };
  74. struct PyObject{
  75. GCHeader gc;
  76. Type type;
  77. NameDict* _attr;
  78. bool is_attr_valid() const noexcept { return _attr != nullptr; }
  79. NameDict& attr() noexcept { return *_attr; }
  80. PyObject* attr(StrName name) const noexcept { return (*_attr)[name]; }
  81. virtual void* value() = 0;
  82. virtual void _obj_gc_mark() = 0;
  83. PyObject(Type type) : type(type) {}
  84. virtual ~PyObject() {
  85. if(_attr == nullptr) return;
  86. _attr->~NameDict();
  87. pool64.dealloc(_attr);
  88. }
  89. void enable_instance_dict(float lf=kInstAttrLoadFactor) noexcept {
  90. _attr = new(pool64.alloc<NameDict>()) NameDict(lf);
  91. }
  92. };
  93. template<typename T>
  94. void gc_mark(T& t);
  95. template <typename T>
  96. struct Py_ final: PyObject {
  97. T _value;
  98. Py_(Type type, const T& val): PyObject(type), _value(val) { _init(); }
  99. Py_(Type type, T&& val): PyObject(type), _value(std::move(val)) { _init(); }
  100. void _init() noexcept {
  101. if constexpr (std::is_same_v<T, Type> || std::is_same_v<T, DummyModule>) {
  102. _attr = new(pool64.alloc<NameDict>()) NameDict(kTypeAttrLoadFactor);
  103. }else if constexpr(std::is_same_v<T, DummyInstance>){
  104. _attr = new(pool64.alloc<NameDict>()) NameDict(kInstAttrLoadFactor);
  105. }else if constexpr(std::is_same_v<T, Function> || std::is_same_v<T, NativeFunc>){
  106. _attr = new(pool64.alloc<NameDict>()) NameDict(kInstAttrLoadFactor);
  107. }else{
  108. _attr = nullptr;
  109. }
  110. }
  111. void* value() override { return &_value; }
  112. void _obj_gc_mark() override {
  113. if(gc.marked) return;
  114. gc.marked = true;
  115. if(_attr != nullptr) pkpy::gc_mark<NameDict>(*_attr);
  116. pkpy::gc_mark<T>(_value); // handle PyObject* inside _value `T`
  117. }
  118. };
  119. #define OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value)
  120. #define OBJ_MARK(obj) if(!is_tagged(obj)) (obj)->_obj_gc_mark()
  121. Str obj_type_name(VM* vm, Type type);
  122. #if DEBUG_NO_BUILTIN_MODULES
  123. #define OBJ_NAME(obj) Str("<?>")
  124. #else
  125. #define OBJ_NAME(obj) OBJ_GET(Str, vm->getattr(obj, __name__))
  126. #endif
  127. const int kTpIntIndex = 2;
  128. const int kTpFloatIndex = 3;
  129. inline bool is_type(PyObject* obj, Type type) {
  130. #if DEBUG_EXTRA_CHECK
  131. if(obj == nullptr) throw std::runtime_error("is_type() called with nullptr");
  132. #endif
  133. switch(type.index){
  134. case kTpIntIndex: return is_int(obj);
  135. case kTpFloatIndex: return is_float(obj);
  136. default: return !is_tagged(obj) && obj->type == type;
  137. }
  138. }
  139. inline bool is_non_tagged_type(PyObject* obj, Type type) {
  140. #if DEBUG_EXTRA_CHECK
  141. if(obj == nullptr) throw std::runtime_error("is_non_tagged_type() called with nullptr");
  142. #endif
  143. return !is_tagged(obj) && obj->type == type;
  144. }
  145. #define PY_CLASS(T, mod, name) \
  146. static Type _type(VM* vm) { \
  147. static const StrName __x0(#mod); \
  148. static const StrName __x1(#name); \
  149. return OBJ_GET(Type, vm->_modules[__x0]->attr(__x1)); \
  150. } \
  151. static PyObject* register_class(VM* vm, PyObject* mod) { \
  152. PyObject* type = vm->new_type_object(mod, #name, vm->tp_object); \
  153. if(OBJ_NAME(mod) != #mod) { \
  154. auto msg = fmt("register_class() failed: ", OBJ_NAME(mod), " != ", #mod); \
  155. throw std::runtime_error(msg); \
  156. } \
  157. T::_register(vm, mod, type); \
  158. type->attr()._try_perfect_rehash(); \
  159. return type; \
  160. }
  161. union BitsCvt {
  162. i64 _int;
  163. f64 _float;
  164. BitsCvt(i64 val) : _int(val) {}
  165. BitsCvt(f64 val) : _float(val) {}
  166. };
  167. template <typename, typename=void> struct is_py_class : std::false_type {};
  168. template <typename T> struct is_py_class<T, std::void_t<decltype(T::_type)>> : std::true_type {};
  169. template<typename T> void _check_py_class(VM*, PyObject*);
  170. template<typename T> T py_pointer_cast(VM*, PyObject*);
  171. template<typename T> T py_value_cast(VM*, PyObject*);
  172. template<typename __T>
  173. __T py_cast(VM* vm, PyObject* obj) {
  174. using T = std::decay_t<__T>;
  175. if constexpr(std::is_pointer_v<T>){
  176. return py_pointer_cast<T>(vm, obj);
  177. }else if constexpr(is_py_class<T>::value){
  178. _check_py_class<T>(vm, obj);
  179. return OBJ_GET(T, obj);
  180. }else if constexpr(std::is_pod_v<T>){
  181. return py_value_cast<T>(vm, obj);
  182. }else{
  183. return Discarded();
  184. }
  185. }
  186. template<typename __T>
  187. __T _py_cast(VM* vm, PyObject* obj) {
  188. using T = std::decay_t<__T>;
  189. if constexpr(std::is_pointer_v<__T>){
  190. return py_pointer_cast<__T>(vm, obj);
  191. }else if constexpr(is_py_class<T>::value){
  192. return OBJ_GET(T, obj);
  193. }else{
  194. return Discarded();
  195. }
  196. }
  197. #define VAR(x) py_var(vm, x)
  198. #define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), T(__VA_ARGS__))
  199. #define CAST(T, x) py_cast<T>(vm, x)
  200. #define _CAST(T, x) _py_cast<T>(vm, x)
  201. } // namespace pkpy