| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- #pragma once
- #include <cmath>
- #include <cstring>
- #include <ctime>
- #include <stdexcept>
- #include <vector>
- #include <string>
- #include <chrono>
- #include <string_view>
- #include <memory>
- #include <iostream>
- #include <map>
- #include <set>
- #include <algorithm>
- #include <variant>
- #include <type_traits>
- #include <deque>
- #include <typeindex>
- #include <initializer_list>
- #define PK_VERSION "2.0.0"
- #define PK_VERSION_MAJOR 2
- #define PK_VERSION_MINOR 0
- #define PK_VERSION_PATCH 0
- #include "config.h"
- #include "export.h"
- #include "_generated.h"
- #ifdef min
- #undef min
- #endif
- #ifdef max
- #undef max
- #endif
- /*******************************************************************************/
- #if PK_ENABLE_THREAD
- #define PK_THREAD_LOCAL thread_local
- #include <mutex>
- struct GIL {
- inline static std::mutex _mutex;
- explicit GIL() { _mutex.lock(); }
- ~GIL() { _mutex.unlock(); }
- };
- #define PK_GLOBAL_SCOPE_LOCK() GIL _lock;
- #else
- #define PK_THREAD_LOCAL
- #define PK_GLOBAL_SCOPE_LOCK()
- #endif
- /*******************************************************************************/
- #define PK_UNUSED(x) (void)(x)
- #define PK_LOCAL_STATIC static
- namespace pkpy{
- namespace std = ::std;
- template <size_t T>
- struct NumberTraits;
- template <>
- struct NumberTraits<4> {
- using int_t = int32_t;
- static constexpr int_t kMaxSmallInt = (1 << 28) - 1;
- static constexpr int_t kMinSmallInt = 0;
- };
- template <>
- struct NumberTraits<8> {
- using int_t = int64_t;
- static constexpr int_t kMaxSmallInt = (1ll << 60) - 1;
- static constexpr int_t kMinSmallInt = 0;
- };
- using Number = NumberTraits<sizeof(void*)>;
- using i64 = int64_t; // always 64-bit
- using f64 = double; // always 64-bit
- static_assert(sizeof(i64) == 8);
- struct Dummy { }; // for special objects: True, False, None, Ellipsis, etc.
- struct DummyInstance { };
- struct DummyModule { };
- struct NoReturn { };
- struct Discarded { };
- struct Type {
- int16_t index;
- constexpr Type(): index(0) {}
- explicit constexpr Type(int index): index(index) {}
- bool operator==(Type other) const { return this->index == other.index; }
- bool operator!=(Type other) const { return this->index != other.index; }
- constexpr operator int() const { return index; }
- };
- #define PK_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; })
- #define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) { return VAR(x); })
- #define PK_ACTION(x) ([](VM* vm, ArgsView args) { x; return vm->None; })
- #define PK_REGION(name) 1
- #ifdef POCKETPY_H
- #define PK_FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!");
- #else
- #define PK_FATAL_ERROR() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " FATAL_ERROR()!");
- #endif
- #define PK_ASSERT(x) if(!(x)) PK_FATAL_ERROR();
- #if PK_DEBUG_EXTRA_CHECK
- #define PK_DEBUG_ASSERT(x) if(!(x)) PK_FATAL_ERROR();
- #else
- #define PK_DEBUG_ASSERT(x)
- #endif
- // is_pod_v<> for c++17 and c++20
- template<typename T>
- inline constexpr bool is_pod_v = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
- #define PK_ALWAYS_PASS_BY_POINTER(T) \
- T(const T&) = delete; \
- T& operator=(const T&) = delete; \
- T(T&&) = delete; \
- T& operator=(T&&) = delete;
- inline const char* kPlatformStrings[] = {
- "win32", // 0
- "emscripten", // 1
- "ios", // 2
- "darwin", // 3
- "android", // 4
- "linux", // 5
- "unknown" // 6
- };
- #define PK_SLICE_LOOP(i, start, stop, step) for(int i=start; step>0?i<stop:i>stop; i+=step)
- template<typename T>
- inline constexpr bool is_integral_v = std::is_same_v<T, char>
- || std::is_same_v<T, short>
- || std::is_same_v<T, int>
- || std::is_same_v<T, long>
- || std::is_same_v<T, long long>
- || std::is_same_v<T, unsigned char>
- || std::is_same_v<T, unsigned short>
- || std::is_same_v<T, unsigned int>
- || std::is_same_v<T, unsigned long>
- || std::is_same_v<T, unsigned long long>
- || std::is_same_v<T, signed char>; // for imgui
- template<typename T>
- inline constexpr bool is_floating_point_v = std::is_same_v<T, float> || std::is_same_v<T, double>;
- inline const char* PK_HEX_TABLE = "0123456789abcdef";
- struct PyObject;
- struct Frame;
- class VM;
- // by default, only `int` and `float` enable SSO
- // users can specialize this template to enable SSO for other types
- // SSO types cannot have instance dict
- template<typename T>
- inline constexpr bool is_sso_v = is_integral_v<T> || is_floating_point_v<T>;
- // make a obj_get_t<T> for a given type T, if is_sso_v<T> is true, return T, else return T&
- template<typename T>
- using obj_get_t = std::conditional_t<is_sso_v<T>, T, T&>;
- struct const_sso_var {};
- struct PyVar final{
- Type type;
- bool is_ptr;
- uint8_t flags;
- // 12 bytes SSO
- int _0; i64 _1;
- // uninitialized
- PyVar() = default;
- /* We must initialize all members to allow == operator to work correctly */
- // constexpr initialized
- constexpr PyVar(const const_sso_var&, Type type, int value): type(type), is_ptr(false), flags(0), _0(value), _1(0) {}
- // zero initialized
- constexpr PyVar(std::nullptr_t): type(0), is_ptr(false), flags(0), _0(0), _1(0) {}
- // PyObject* initialized (is_sso = false)
- PyVar(Type type, PyObject* p): type(type), is_ptr(true), flags(0), _0(0), _1(reinterpret_cast<i64>(p)) {}
- // SSO initialized (is_sso = true)
- template<typename T>
- PyVar(Type type, T value): type(type), is_ptr(false), flags(0), _0(0), _1(0) {
- static_assert(sizeof(T) <= 12, "SSO size exceeded");
- as<T>() = value;
- }
- template<typename T>
- T& as(){
- static_assert(!std::is_reference_v<T>);
- if constexpr(sizeof(T) <= 8){
- return reinterpret_cast<T&>(_1);
- }else{
- return reinterpret_cast<T&>(_0);
- }
- }
- explicit operator bool() const { return (bool)type; }
- void set_null() { _qword(0) = 0; _qword(1) = 0; }
- i64 _qword(int i) const { return ((const i64*)this)[i]; }
- i64& _qword(int i) { return ((i64*)this)[i]; }
- bool operator==(const PyVar& other) const {
- return _qword(0) == other._qword(0) && _qword(1) == other._qword(1);
- }
- bool operator!=(const PyVar& other) const {
- return _qword(0) != other._qword(0) || _qword(1) != other._qword(1);
- }
- bool operator==(std::nullptr_t) const { return !(bool)type; }
- bool operator!=(std::nullptr_t) const { return (bool)type; }
- PyObject* get() const {
- PK_DEBUG_ASSERT(!is_sso)
- return reinterpret_cast<PyObject*>(_1);
- }
- PyObject* operator->() const {
- PK_DEBUG_ASSERT(!is_sso)
- return reinterpret_cast<PyObject*>(_1);
- }
- i64 hash() const { return _1; }
- template<typename T>
- obj_get_t<T> obj_get();
- };
- static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);
- } // namespace pkpy
- // specialize std::less for PyVar
- namespace std {
- template<>
- struct less<pkpy::PyVar> {
- bool operator()(const pkpy::PyVar& lhs, const pkpy::PyVar& rhs) const {
- return memcmp(&lhs, &rhs, sizeof(pkpy::PyVar)) < 0;
- }
- };
- }
|