common.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #pragma once
  2. #include <cmath>
  3. #include <cstring>
  4. #include <ctime>
  5. #include <stdexcept>
  6. #include <vector>
  7. #include <string>
  8. #include <chrono>
  9. #include <string_view>
  10. #include <memory>
  11. #include <iostream>
  12. #include <map>
  13. #include <set>
  14. #include <algorithm>
  15. #include <variant>
  16. #include <type_traits>
  17. #include <deque>
  18. #include <typeindex>
  19. #include <initializer_list>
  20. #define PK_VERSION "2.0.0"
  21. #define PK_VERSION_MAJOR 2
  22. #define PK_VERSION_MINOR 0
  23. #define PK_VERSION_PATCH 0
  24. #include "config.h"
  25. #include "export.h"
  26. #include "_generated.h"
  27. #ifdef min
  28. #undef min
  29. #endif
  30. #ifdef max
  31. #undef max
  32. #endif
  33. /*******************************************************************************/
  34. #if PK_ENABLE_THREAD
  35. #define PK_THREAD_LOCAL thread_local
  36. #include <mutex>
  37. struct GIL {
  38. inline static std::mutex _mutex;
  39. explicit GIL() { _mutex.lock(); }
  40. ~GIL() { _mutex.unlock(); }
  41. };
  42. #define PK_GLOBAL_SCOPE_LOCK() GIL _lock;
  43. #else
  44. #define PK_THREAD_LOCAL
  45. #define PK_GLOBAL_SCOPE_LOCK()
  46. #endif
  47. /*******************************************************************************/
  48. #define PK_UNUSED(x) (void)(x)
  49. #define PK_LOCAL_STATIC static
  50. namespace pkpy{
  51. namespace std = ::std;
  52. template <size_t T>
  53. struct NumberTraits;
  54. template <>
  55. struct NumberTraits<4> {
  56. using int_t = int32_t;
  57. static constexpr int_t kMaxSmallInt = (1 << 28) - 1;
  58. static constexpr int_t kMinSmallInt = 0;
  59. };
  60. template <>
  61. struct NumberTraits<8> {
  62. using int_t = int64_t;
  63. static constexpr int_t kMaxSmallInt = (1ll << 60) - 1;
  64. static constexpr int_t kMinSmallInt = 0;
  65. };
  66. using Number = NumberTraits<sizeof(void*)>;
  67. using i64 = int64_t; // always 64-bit
  68. using f64 = double; // always 64-bit
  69. static_assert(sizeof(i64) == 8);
  70. struct Dummy { }; // for special objects: True, False, None, Ellipsis, etc.
  71. struct DummyInstance { };
  72. struct DummyModule { };
  73. struct NoReturn { };
  74. struct Discarded { };
  75. struct Type {
  76. int16_t index;
  77. constexpr Type(): index(0) {}
  78. explicit constexpr Type(int index): index(index) {}
  79. bool operator==(Type other) const { return this->index == other.index; }
  80. bool operator!=(Type other) const { return this->index != other.index; }
  81. constexpr operator int() const { return index; }
  82. };
  83. #define PK_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; })
  84. #define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) { return VAR(x); })
  85. #define PK_ACTION(x) ([](VM* vm, ArgsView args) { x; return vm->None; })
  86. #define PK_REGION(name) 1
  87. #ifdef POCKETPY_H
  88. #define PK_FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!");
  89. #else
  90. #define PK_FATAL_ERROR() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " FATAL_ERROR()!");
  91. #endif
  92. #define PK_ASSERT(x) if(!(x)) PK_FATAL_ERROR();
  93. #if PK_DEBUG_EXTRA_CHECK
  94. #define PK_DEBUG_ASSERT(x) if(!(x)) PK_FATAL_ERROR();
  95. #else
  96. #define PK_DEBUG_ASSERT(x)
  97. #endif
  98. // is_pod_v<> for c++17 and c++20
  99. template<typename T>
  100. inline constexpr bool is_pod_v = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
  101. #define PK_ALWAYS_PASS_BY_POINTER(T) \
  102. T(const T&) = delete; \
  103. T& operator=(const T&) = delete; \
  104. T(T&&) = delete; \
  105. T& operator=(T&&) = delete;
  106. inline const char* kPlatformStrings[] = {
  107. "win32", // 0
  108. "emscripten", // 1
  109. "ios", // 2
  110. "darwin", // 3
  111. "android", // 4
  112. "linux", // 5
  113. "unknown" // 6
  114. };
  115. #define PK_SLICE_LOOP(i, start, stop, step) for(int i=start; step>0?i<stop:i>stop; i+=step)
  116. template<typename T>
  117. inline constexpr bool is_integral_v = std::is_same_v<T, char>
  118. || std::is_same_v<T, short>
  119. || std::is_same_v<T, int>
  120. || std::is_same_v<T, long>
  121. || std::is_same_v<T, long long>
  122. || std::is_same_v<T, unsigned char>
  123. || std::is_same_v<T, unsigned short>
  124. || std::is_same_v<T, unsigned int>
  125. || std::is_same_v<T, unsigned long>
  126. || std::is_same_v<T, unsigned long long>
  127. || std::is_same_v<T, signed char>; // for imgui
  128. template<typename T>
  129. inline constexpr bool is_floating_point_v = std::is_same_v<T, float> || std::is_same_v<T, double>;
  130. inline const char* PK_HEX_TABLE = "0123456789abcdef";
  131. struct PyObject;
  132. struct Frame;
  133. class VM;
  134. // by default, only `int` and `float` enable SSO
  135. // users can specialize this template to enable SSO for other types
  136. // SSO types cannot have instance dict
  137. template<typename T>
  138. inline constexpr bool is_sso_v = is_integral_v<T> || is_floating_point_v<T>;
  139. // make a obj_get_t<T> for a given type T, if is_sso_v<T> is true, return T, else return T&
  140. template<typename T>
  141. using obj_get_t = std::conditional_t<is_sso_v<T>, T, T&>;
  142. struct const_sso_var {};
  143. struct PyVar final{
  144. Type type;
  145. bool is_ptr;
  146. uint8_t flags;
  147. // 12 bytes SSO
  148. int _0; i64 _1;
  149. // uninitialized
  150. PyVar() = default;
  151. /* We must initialize all members to allow == operator to work correctly */
  152. // constexpr initialized
  153. constexpr PyVar(const const_sso_var&, Type type, int value): type(type), is_ptr(false), flags(0), _0(value), _1(0) {}
  154. // zero initialized
  155. constexpr PyVar(std::nullptr_t): type(0), is_ptr(false), flags(0), _0(0), _1(0) {}
  156. // PyObject* initialized (is_sso = false)
  157. PyVar(Type type, PyObject* p): type(type), is_ptr(true), flags(0), _0(0), _1(reinterpret_cast<i64>(p)) {}
  158. // SSO initialized (is_sso = true)
  159. template<typename T>
  160. PyVar(Type type, T value): type(type), is_ptr(false), flags(0), _0(0), _1(0) {
  161. static_assert(sizeof(T) <= 12, "SSO size exceeded");
  162. as<T>() = value;
  163. }
  164. template<typename T>
  165. T& as(){
  166. static_assert(!std::is_reference_v<T>);
  167. if constexpr(sizeof(T) <= 8){
  168. return reinterpret_cast<T&>(_1);
  169. }else{
  170. return reinterpret_cast<T&>(_0);
  171. }
  172. }
  173. explicit operator bool() const { return (bool)type; }
  174. void set_null() { _qword(0) = 0; _qword(1) = 0; }
  175. i64 _qword(int i) const { return ((const i64*)this)[i]; }
  176. i64& _qword(int i) { return ((i64*)this)[i]; }
  177. bool operator==(const PyVar& other) const {
  178. return _qword(0) == other._qword(0) && _qword(1) == other._qword(1);
  179. }
  180. bool operator!=(const PyVar& other) const {
  181. return _qword(0) != other._qword(0) || _qword(1) != other._qword(1);
  182. }
  183. bool operator==(std::nullptr_t) const { return !(bool)type; }
  184. bool operator!=(std::nullptr_t) const { return (bool)type; }
  185. PyObject* get() const {
  186. PK_DEBUG_ASSERT(!is_sso)
  187. return reinterpret_cast<PyObject*>(_1);
  188. }
  189. PyObject* operator->() const {
  190. PK_DEBUG_ASSERT(!is_sso)
  191. return reinterpret_cast<PyObject*>(_1);
  192. }
  193. i64 hash() const { return _1; }
  194. template<typename T>
  195. obj_get_t<T> obj_get();
  196. };
  197. static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);
  198. } // namespace pkpy
  199. // specialize std::less for PyVar
  200. namespace std {
  201. template<>
  202. struct less<pkpy::PyVar> {
  203. bool operator()(const pkpy::PyVar& lhs, const pkpy::PyVar& rhs) const {
  204. return memcmp(&lhs, &rhs, sizeof(pkpy::PyVar)) < 0;
  205. }
  206. };
  207. }