object.hpp 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. #pragma once
  2. #include "pocketpy/common/str.hpp"
  3. #include "pocketpy/common/config.h"
  4. #include "pocketpy/objects/base.hpp"
  5. namespace pkpy {
  6. struct NameDict;
  7. struct PyObject final {
  8. bool gc_marked; // whether this object is marked
  9. Type type; // we have a duplicated type here for convenience
  10. NameDict* _attr; // gc will delete this on destruction
  11. bool is_attr_valid() const noexcept { return _attr != nullptr; }
  12. void* _value_ptr() noexcept { return (char*)this + 16; }
  13. template <typename T>
  14. T& as() noexcept {
  15. static_assert(std::is_same_v<T, std::decay_t<T>>);
  16. return *reinterpret_cast<T*>(_value_ptr());
  17. }
  18. NameDict& attr() {
  19. assert(is_attr_valid());
  20. return *_attr;
  21. }
  22. PyObject(Type type) : gc_marked(false), type(type), _attr(nullptr) {}
  23. PyVar attr(StrName name) const;
  24. static NameDict* __init_namedict(float lf);
  25. template <typename T, typename... Args>
  26. void placement_new(Args&&... args) {
  27. static_assert(std::is_same_v<T, std::decay_t<T>>);
  28. new (_value_ptr()) T(std::forward<Args>(args)...);
  29. // backdoor for important builtin types
  30. if constexpr(std::is_same_v<T, DummyInstance>) {
  31. _attr = __init_namedict(PK_INST_ATTR_LOAD_FACTOR);
  32. } else if constexpr(std::is_same_v<T, Type>) {
  33. _attr = __init_namedict(PK_TYPE_ATTR_LOAD_FACTOR);
  34. } else if constexpr(std::is_same_v<T, DummyModule>) {
  35. _attr = __init_namedict(PK_TYPE_ATTR_LOAD_FACTOR);
  36. }
  37. }
  38. };
  39. static_assert(sizeof(PyObject) <= 16);
  40. } // namespace pkpy