vm.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. #pragma once
  2. #include "pocketpy/objects/object.hpp"
  3. #include "pocketpy/objects/dict.hpp"
  4. #include "pocketpy/objects/error.hpp"
  5. #include "pocketpy/objects/stackmemory.hpp"
  6. #include "pocketpy/objects/builtins.hpp"
  7. #include "pocketpy/interpreter/gc.hpp"
  8. #include "pocketpy/interpreter/frame.hpp"
  9. #include "pocketpy/interpreter/profiler.hpp"
  10. #include <stdexcept>
  11. namespace pkpy {
  12. /* Stack manipulation macros */
  13. // https://github.com/python/cpython/blob/3.9/Python/ceval.c#L1123
  14. #define TOP() (s_data.top())
  15. #define SECOND() (s_data.second())
  16. #define THIRD() (s_data.third())
  17. #define STACK_SHRINK(n) (s_data.shrink(n))
  18. #define PUSH(v) (s_data.push(v))
  19. #define POP() (s_data.pop())
  20. #define POPX() (s_data.popx())
  21. #define STACK_VIEW(n) (s_data.view(n))
  22. typedef PyVar (*BinaryFuncC)(VM*, PyVar, PyVar);
  23. typedef void (*RegisterFunc)(VM*, PyObject*, PyObject*);
  24. #if PK_ENABLE_PROFILER
  25. struct NextBreakpoint {
  26. int callstack_size;
  27. int lineno;
  28. bool should_step_into;
  29. NextBreakpoint() : callstack_size(0) {}
  30. NextBreakpoint(int callstack_size, int lineno, bool should_step_into) :
  31. callstack_size(callstack_size), lineno(lineno), should_step_into(should_step_into) {}
  32. void _step(VM* vm);
  33. bool empty() const { return callstack_size == 0; }
  34. };
  35. #endif
  36. struct PyTypeInfo {
  37. struct Vt {
  38. void (*_dtor)(void*);
  39. void (*_gc_mark)(void*, VM*);
  40. Vt() : _dtor(nullptr), _gc_mark(nullptr) {}
  41. operator bool () const { return _dtor || _gc_mark; }
  42. template <typename T>
  43. inline static Vt get() {
  44. static_assert(std::is_same_v<T, std::decay_t<T>>);
  45. Vt vt;
  46. if constexpr(!std::is_trivially_destructible_v<T>) {
  47. vt._dtor = [](void* p) {
  48. ((T*)p)->~T();
  49. };
  50. }
  51. if constexpr(has_gc_marker<T>::value) {
  52. vt._gc_mark = [](void* p, VM* vm) {
  53. ((T*)p)->_gc_mark(vm);
  54. };
  55. }
  56. return vt;
  57. }
  58. };
  59. PyObject* obj; // never be garbage collected
  60. Type base;
  61. PyObject* mod; // never be garbage collected
  62. StrName name;
  63. bool subclass_enabled;
  64. Vt vt;
  65. PyTypeInfo(PyObject* obj, Type base, PyObject* mod, StrName name, bool subclass_enabled, Vt vt = {}) :
  66. obj(obj), base(base), mod(mod), name(name), subclass_enabled(subclass_enabled), vt(vt) {}
  67. vector<StrName> annotated_fields = {};
  68. // unary operators
  69. Str (*m__repr__)(VM* vm, PyVar) = nullptr;
  70. Str (*m__str__)(VM* vm, PyVar) = nullptr;
  71. i64 (*m__hash__)(VM* vm, PyVar) = nullptr;
  72. i64 (*m__len__)(VM* vm, PyVar) = nullptr;
  73. PyVar (*m__iter__)(VM* vm, PyVar) = nullptr;
  74. void (*op__iter__)(VM* vm, PyVar) = nullptr;
  75. unsigned (*op__next__)(VM* vm, PyVar) = nullptr;
  76. PyVar (*m__neg__)(VM* vm, PyVar) = nullptr;
  77. PyVar (*m__invert__)(VM* vm, PyVar) = nullptr;
  78. BinaryFuncC m__eq__ = nullptr;
  79. BinaryFuncC m__lt__ = nullptr;
  80. BinaryFuncC m__le__ = nullptr;
  81. BinaryFuncC m__gt__ = nullptr;
  82. BinaryFuncC m__ge__ = nullptr;
  83. BinaryFuncC m__contains__ = nullptr;
  84. // binary operators
  85. BinaryFuncC m__add__ = nullptr;
  86. BinaryFuncC m__sub__ = nullptr;
  87. BinaryFuncC m__mul__ = nullptr;
  88. BinaryFuncC m__truediv__ = nullptr;
  89. BinaryFuncC m__floordiv__ = nullptr;
  90. BinaryFuncC m__mod__ = nullptr;
  91. BinaryFuncC m__pow__ = nullptr;
  92. BinaryFuncC m__matmul__ = nullptr;
  93. BinaryFuncC m__lshift__ = nullptr;
  94. BinaryFuncC m__rshift__ = nullptr;
  95. BinaryFuncC m__and__ = nullptr;
  96. BinaryFuncC m__or__ = nullptr;
  97. BinaryFuncC m__xor__ = nullptr;
  98. // indexer
  99. PyVar (*m__getitem__)(VM* vm, PyVar, PyVar) = nullptr;
  100. void (*m__setitem__)(VM* vm, PyVar, PyVar, PyVar) = nullptr;
  101. void (*m__delitem__)(VM* vm, PyVar, PyVar) = nullptr;
  102. // attributes
  103. void (*m__setattr__)(VM* vm, PyVar, StrName, PyVar) = nullptr;
  104. PyVar (*m__getattr__)(VM* vm, PyVar, StrName) = nullptr;
  105. bool (*m__delattr__)(VM* vm, PyVar, StrName) = nullptr;
  106. // backdoors
  107. void (*on_end_subclass)(VM* vm, PyTypeInfo*) = nullptr;
  108. };
  109. struct ImportContext {
  110. PK_ALWAYS_PASS_BY_POINTER(ImportContext)
  111. vector<Str> pending;
  112. vector<bool> pending_is_init; // a.k.a __init__.py
  113. ImportContext() {}
  114. struct Temp {
  115. PK_ALWAYS_PASS_BY_POINTER(Temp)
  116. ImportContext* ctx;
  117. Temp(ImportContext* ctx, Str name, bool is_init) : ctx(ctx) {
  118. ctx->pending.push_back(name);
  119. ctx->pending_is_init.push_back(is_init);
  120. }
  121. ~Temp() {
  122. ctx->pending.pop_back();
  123. ctx->pending_is_init.pop_back();
  124. }
  125. };
  126. Temp scope(Str name, bool is_init) { return {this, name, is_init}; }
  127. };
  128. class VM {
  129. PK_ALWAYS_PASS_BY_POINTER(VM)
  130. VM* vm; // self reference to simplify code
  131. public:
  132. ManagedHeap heap;
  133. ValueStack s_data;
  134. CallStack callstack;
  135. vector<PyTypeInfo> _all_types;
  136. NameDict _modules; // loaded modules
  137. std::map<StrName, Str> _lazy_modules; // lazy loaded modules
  138. struct {
  139. PyObject* error;
  140. vector<ArgsView> s_view;
  141. } __c;
  142. PyVar StopIteration; // a special Exception class
  143. PyObject* builtins;
  144. PyObject* _main;
  145. // typeid -> Type
  146. std::map<const std::type_index, Type> _cxx_typeid_map;
  147. // this is for repr() recursion detection (no need to mark)
  148. vector<PyVar> _repr_recursion_set;
  149. ImportContext __import_context;
  150. PyObject* __last_exception;
  151. PyObject* __curr_class;
  152. PyVar __cached_object_new;
  153. std::map<std::string_view, CodeObject_> __cached_codes;
  154. std::map<std::string_view, PyVar> __cached_op_funcs;
  155. FuncDecl_ __dynamic_func_decl;
  156. PyVar __vectorcall_buffer[PK_MAX_CO_VARNAMES];
  157. #if PK_ENABLE_PROFILER
  158. LineProfiler* _profiler = nullptr;
  159. NextBreakpoint _next_breakpoint;
  160. #endif
  161. void (*_ceval_on_step)(VM*, Frame*, Bytecode bc);
  162. void (*_stdout)(const char*, int);
  163. void (*_stderr)(const char*, int);
  164. unsigned char* (*_import_handler)(const char*, int*);
  165. // function<void(const char*, int)> _stdout;
  166. // function<void(const char*, int)> _stderr;
  167. // function<unsigned char*(const char*, int*)> _import_handler;
  168. // for quick access
  169. constexpr static Type tp_object = Type(1), tp_type = Type(2);
  170. constexpr static Type tp_int = Type(kTpIntIndex), tp_float = Type(kTpFloatIndex), tp_bool = Type(5),
  171. tp_str = Type(6);
  172. constexpr static Type tp_list = Type(7), tp_tuple = Type(8);
  173. constexpr static Type tp_slice = Type(9), tp_range = Type(10), tp_module = Type(11);
  174. constexpr static Type tp_function = Type(12), tp_native_func = Type(13), tp_bound_method = Type(14);
  175. constexpr static Type tp_super = Type(15), tp_exception = Type(16), tp_bytes = Type(17), tp_mappingproxy = Type(18);
  176. constexpr static Type tp_dict = Type(19), tp_property = Type(20), tp_star_wrapper = Type(21);
  177. constexpr static Type tp_staticmethod = Type(22), tp_classmethod = Type(23);
  178. constexpr static Type tp_none_type = Type(24), tp_not_implemented = Type(25), tp_ellipsis = Type(26);
  179. constexpr static Type tp_stack_memory = Type(kTpStackMemoryIndex);
  180. constexpr static PyVar True{const_sso_var(), tp_bool, 1};
  181. constexpr static PyVar False{const_sso_var(), tp_bool, 0};
  182. constexpr static PyVar None{const_sso_var(), tp_none_type, 0};
  183. constexpr static PyVar NotImplemented{const_sso_var(), tp_not_implemented, 0};
  184. constexpr static PyVar Ellipsis{const_sso_var(), tp_ellipsis, 0};
  185. const bool enable_os;
  186. VM(bool enable_os = true);
  187. // clang-format off
  188. #if PK_REGION("Python Equivalents")
  189. Str py_str(PyVar obj); // x -> str(x)
  190. Str py_repr(PyVar obj); // x -> repr(x)
  191. Str py_json(PyVar obj); // x -> json.dumps(x)
  192. PyVar py_iter(PyVar obj); // x -> iter(x)
  193. PyVar py_next(PyVar); // x -> next(x)
  194. PyVar _py_next(const PyTypeInfo*, PyVar); // x -> next(x) with type info cache
  195. PyObject* py_import(Str path, bool throw_err=true); // x -> __import__(x)
  196. PyVar py_negate(PyVar obj); // x -> -x
  197. List py_list(PyVar); // x -> list(x)
  198. bool py_callable(PyVar obj); // x -> callable(x)
  199. bool py_bool(PyVar obj){ // x -> bool(x)
  200. if(obj.type == tp_bool) return obj._0;
  201. return __py_bool_non_trivial(obj);
  202. }
  203. i64 py_hash(PyVar obj); // x -> hash(x)
  204. bool py_eq(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs == rhs
  205. bool py_lt(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs < rhs
  206. bool py_le(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs <= rhs
  207. bool py_gt(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs > rhs
  208. bool py_ge(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs >= rhs
  209. bool py_ne(PyVar lhs, PyVar rhs){ // (lhs, rhs) -> lhs != rhs
  210. return !py_eq(lhs, rhs);
  211. }
  212. PyVar py_op(std::string_view name); // (name) -> operator.name
  213. void py_exec(std::string_view, PyVar, PyVar); // exec(source, globals, locals)
  214. PyVar py_eval(std::string_view, PyVar, PyVar); // eval(source, globals, locals)
  215. #endif
  216. #if PK_REGION("Utility Methods")
  217. ArgsView cast_array_view(PyVar obj);
  218. void set_main_argv(int argc, char** argv);
  219. i64 normalized_index(i64 index, int size);
  220. Str disassemble(CodeObject_ co);
  221. void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step);
  222. void obj_gc_mark(PyVar obj) { if(obj.is_ptr) __obj_gc_mark(obj.get()); }
  223. void obj_gc_mark(PyObject* p) { if(p) __obj_gc_mark(p); }
  224. #endif
  225. #if PK_REGION("Name Lookup Methods")
  226. PyVar* find_name_in_mro(Type cls, StrName name);
  227. PyVar get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_err=true, bool fallback=false);
  228. PyVar getattr(PyVar obj, StrName name, bool throw_err=true);
  229. void delattr(PyVar obj, StrName name);
  230. void setattr(PyVar obj, StrName name, PyVar value);
  231. #endif
  232. #if PK_REGION("Source Execution Methods")
  233. CodeObject_ compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false);
  234. Str precompile(std::string_view source, const Str& filename, CompileMode mode);
  235. PyVar exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module=nullptr);
  236. PyVar exec(std::string_view source);
  237. PyVar eval(std::string_view source);
  238. template<typename ...Args>
  239. PyVar _exec(Args&&... args){
  240. callstack.emplace(s_data._sp, std::forward<Args>(args)...);
  241. return __run_top_frame();
  242. }
  243. #endif
  244. #if PK_REGION("Invocation Methods")
  245. PyVar vectorcall(int ARGC, int KWARGC=0, bool op_call=false);
  246. template<typename... Args>
  247. PyVar call(PyVar callable, Args&&... args){
  248. PUSH(callable); PUSH(PY_NULL);
  249. __push_varargs(args...);
  250. return vectorcall(sizeof...(args));
  251. }
  252. template<typename... Args>
  253. PyVar call_method(PyVar self, PyVar callable, Args&&... args){
  254. PUSH(callable); PUSH(self);
  255. __push_varargs(args...);
  256. return vectorcall(sizeof...(args));
  257. }
  258. template<typename... Args>
  259. PyVar call_method(PyVar self, StrName name, Args&&... args){
  260. PyVar callable = get_unbound_method(self, name, &self);
  261. return call_method(self, callable, args...);
  262. }
  263. #endif
  264. #if PK_REGION("Logging Methods")
  265. virtual void stdout_write(const Str& s){ _stdout(s.data, s.size); }
  266. virtual void stderr_write(const Str& s){ _stderr(s.data, s.size); }
  267. #endif
  268. #if PK_REGION("Magic Bindings")
  269. void bind__repr__(Type type, Str (*f)(VM*, PyVar));
  270. void bind__str__(Type type, Str (*f)(VM*, PyVar));
  271. void bind__iter__(Type type, PyVar (*f)(VM*, PyVar));
  272. void bind__next__(Type type, unsigned (*f)(VM*, PyVar));
  273. [[deprecated]] void bind__next__(Type type, PyVar (*f)(VM*, PyVar));
  274. void bind__neg__(Type type, PyVar (*f)(VM*, PyVar));
  275. void bind__invert__(Type type, PyVar (*f)(VM*, PyVar));
  276. void bind__hash__(Type type, i64 (*f)(VM* vm, PyVar));
  277. void bind__len__(Type type, i64 (*f)(VM* vm, PyVar));
  278. void bind__eq__(Type type, BinaryFuncC f);
  279. void bind__lt__(Type type, BinaryFuncC f);
  280. void bind__le__(Type type, BinaryFuncC f);
  281. void bind__gt__(Type type, BinaryFuncC f);
  282. void bind__ge__(Type type, BinaryFuncC f);
  283. void bind__contains__(Type type, BinaryFuncC f);
  284. void bind__add__(Type type, BinaryFuncC f);
  285. void bind__sub__(Type type, BinaryFuncC f);
  286. void bind__mul__(Type type, BinaryFuncC f);
  287. void bind__truediv__(Type type, BinaryFuncC f);
  288. void bind__floordiv__(Type type, BinaryFuncC f);
  289. void bind__mod__(Type type, BinaryFuncC f);
  290. void bind__pow__(Type type, BinaryFuncC f);
  291. void bind__matmul__(Type type, BinaryFuncC f);
  292. void bind__lshift__(Type type, BinaryFuncC f);
  293. void bind__rshift__(Type type, BinaryFuncC f);
  294. void bind__and__(Type type, BinaryFuncC f);
  295. void bind__or__(Type type, BinaryFuncC f);
  296. void bind__xor__(Type type, BinaryFuncC f);
  297. void bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar));
  298. void bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar));
  299. void bind__delitem__(Type type, void (*f)(VM*, PyVar, PyVar));
  300. #endif
  301. #if PK_REGION("General Bindings")
  302. PyObject* bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT);
  303. PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT){
  304. return bind_func(_t(type), name, argc, fn, std::move(userdata), bt);
  305. }
  306. PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
  307. template<typename T, typename F, bool ReadOnly=false>
  308. PyObject* bind_field(PyObject*, const char*, F T::*);
  309. PyObject* bind(PyObject*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
  310. template<typename Ret, typename... Params>
  311. PyObject* bind(PyObject*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
  312. template<typename Ret, typename T, typename... Params>
  313. PyObject* bind(PyObject*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
  314. PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
  315. template<typename Ret, typename... Params>
  316. PyObject* bind(PyObject*, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
  317. template<typename Ret, typename T, typename... Params>
  318. PyObject* bind(PyObject*, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
  319. #endif
  320. #if PK_REGION("Error Reporting Methods")
  321. [[noreturn]] void _error(PyVar);
  322. [[noreturn]] void StackOverflowError() { __builtin_error("StackOverflowError"); }
  323. [[noreturn]] void IOError(const Str& msg) { __builtin_error("IOError", msg); }
  324. [[noreturn]] void NotImplementedError(){ __builtin_error("NotImplementedError"); }
  325. [[noreturn]] void TypeError(const Str& msg){ __builtin_error("TypeError", msg); }
  326. [[noreturn]] void TypeError(Type expected, Type actual) { TypeError("expected " + _type_name(vm, expected).escape() + ", got " + _type_name(vm, actual).escape()); }
  327. [[noreturn]] void IndexError(const Str& msg){ __builtin_error("IndexError", msg); }
  328. [[noreturn]] void ValueError(const Str& msg){ __builtin_error("ValueError", msg); }
  329. [[noreturn]] void RuntimeError(const Str& msg){ __builtin_error("RuntimeError", msg); }
  330. [[noreturn]] void ZeroDivisionError(const Str& msg){ __builtin_error("ZeroDivisionError", msg); }
  331. [[noreturn]] void ZeroDivisionError(){ __builtin_error("ZeroDivisionError", "division by zero"); }
  332. [[noreturn]] void NameError(StrName name){ __builtin_error("NameError", _S("name ", name.escape() + " is not defined")); }
  333. [[noreturn]] void UnboundLocalError(StrName name){ __builtin_error("UnboundLocalError", _S("local variable ", name.escape() + " referenced before assignment")); }
  334. [[noreturn]] void KeyError(PyVar obj){ __builtin_error("KeyError", obj); }
  335. [[noreturn]] void ImportError(const Str& msg){ __builtin_error("ImportError", msg); }
  336. [[noreturn]] void AssertionError(const Str& msg){ __builtin_error("AssertionError", msg); }
  337. [[noreturn]] void AssertionError(){ __builtin_error("AssertionError"); }
  338. [[noreturn]] void BinaryOptError(const char* op, PyVar _0, PyVar _1);
  339. [[noreturn]] void AttributeError(PyVar obj, StrName name);
  340. [[noreturn]] void AttributeError(const Str& msg){ __builtin_error("AttributeError", msg); }
  341. #endif
  342. #if PK_REGION("Type Checking Methods")
  343. bool isinstance(PyVar obj, Type base);
  344. bool issubclass(Type cls, Type base);
  345. void check_type(PyVar obj, Type type){ if(!is_type(obj, type)) TypeError(type, _tp(obj)); }
  346. void check_compatible_type(PyVar obj, Type type){ if(!isinstance(obj, type)) TypeError(type, _tp(obj)); }
  347. Type _tp(PyVar obj){ return obj.type; }
  348. const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; }
  349. const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; }
  350. PyObject* _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
  351. PyObject* _t(Type type){ return _all_types[type].obj; }
  352. // equivalent to `obj == NotImplemented` but faster
  353. static bool is_not_implemented(PyVar obj){ return obj.type == tp_not_implemented; }
  354. #endif
  355. #if PK_REGION("User Type Registration")
  356. PyObject* new_module(Str name, Str package="");
  357. PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt={});
  358. template<typename T>
  359. PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled){
  360. return new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
  361. }
  362. template<typename T>
  363. Type _tp_user(){ return _find_type_in_cxx_typeid_map<T>(); }
  364. template<typename T>
  365. bool is_user_type(PyVar obj){ return _tp(obj) == _tp_user<T>(); }
  366. template<typename T>
  367. PyObject* register_user_class(PyObject*, StrName, RegisterFunc, Type base=tp_object, bool subclass_enabled=false);
  368. template<typename T>
  369. PyObject* register_user_class(PyObject*, StrName, Type base=tp_object, bool subclass_enabled=false);
  370. template<typename T, typename ...Args>
  371. PyVar new_user_object(Args&&... args){
  372. return new_object<T>(_tp_user<T>(), std::forward<Args>(args)...);
  373. }
  374. template<typename T, typename ...Args>
  375. PyVar new_object(Type type, Args&&... args){
  376. if constexpr(is_sso_v<T>) return PyVar(type, T(std::forward<Args>(args)...));
  377. else return heap.gcnew<T>(type, std::forward<Args>(args)...);
  378. }
  379. template<typename T, typename ...Args>
  380. void new_stack_object(Type type, Args&&... args){
  381. static_assert(std::is_same_v<T, std::decay_t<T>>);
  382. static_assert(std::is_trivially_destructible_v<T>);
  383. PyObject* p = new(__stack_alloc(py_sizeof<T>)) PyObject(type);
  384. p->placement_new<T>(std::forward<Args>(args)...);
  385. vm->s_data.emplace(p->type, p);
  386. }
  387. #endif
  388. // clang-format on
  389. template <typename T>
  390. Type _find_type_in_cxx_typeid_map() {
  391. auto it = _cxx_typeid_map.find(typeid(T));
  392. if(it == _cxx_typeid_map.end()) {
  393. #if __GNUC__ || __clang__
  394. throw std::runtime_error(__PRETTY_FUNCTION__ + std::string(" failed: T not found"));
  395. #elif _MSC_VER
  396. throw std::runtime_error(__FUNCSIG__ + std::string(" failed: T not found"));
  397. #else
  398. throw std::runtime_error("_find_type_in_cxx_typeid_map() failed: T not found");
  399. #endif
  400. }
  401. return it->second;
  402. }
  403. /********** private **********/
  404. virtual ~VM();
  405. #if PK_DEBUG_CEVAL_STEP
  406. void __log_s_data(const char* title = nullptr);
  407. #endif
  408. PyVar __py_exec_internal(const CodeObject_& code, PyVar globals, PyVar locals);
  409. void __breakpoint();
  410. PyVar __format_object(PyVar, Str);
  411. PyVar __run_top_frame();
  412. void __pop_frame();
  413. PyVar __py_generator(LinkedFrame* frame, ArgsView buffer);
  414. void __op_unpack_sequence(uint16_t arg);
  415. void __prepare_py_call(PyVar*, ArgsView, ArgsView, const FuncDecl_&);
  416. void __unpack_as_list(ArgsView args, List& list);
  417. void __unpack_as_dict(ArgsView args, Dict& dict);
  418. [[noreturn]] void __raise_exc(bool re_raise = false);
  419. [[noreturn]] void __builtin_error(StrName type);
  420. [[noreturn]] void __builtin_error(StrName type, PyVar arg);
  421. [[noreturn]] void __builtin_error(StrName type, const Str& msg);
  422. void __init_builtin_types();
  423. void __post_init_builtin_types();
  424. void __push_varargs() {}
  425. void __push_varargs(PyVar _0) { PUSH(_0); }
  426. void __push_varargs(PyVar _0, PyVar _1) {
  427. PUSH(_0);
  428. PUSH(_1);
  429. }
  430. void __push_varargs(PyVar _0, PyVar _1, PyVar _2) {
  431. PUSH(_0);
  432. PUSH(_1);
  433. PUSH(_2);
  434. }
  435. void __push_varargs(PyVar _0, PyVar _1, PyVar _2, PyVar _3) {
  436. PUSH(_0);
  437. PUSH(_1);
  438. PUSH(_2);
  439. PUSH(_3);
  440. }
  441. PyVar __pack_next_retval(unsigned);
  442. PyVar __minmax_reduce(bool (VM::*op)(PyVar, PyVar), PyVar args, PyVar key);
  443. bool __py_bool_non_trivial(PyVar);
  444. void __obj_gc_mark(PyObject*);
  445. void __stack_gc_mark(PyVar* begin, PyVar* end);
  446. void* __stack_alloc(int size);
  447. };
  448. template <typename T>
  449. constexpr inline bool is_immutable_v =
  450. is_integral_v<T> || is_floating_point_v<T> || std::is_same_v<T, Str> || std::is_same_v<T, Tuple> ||
  451. std::is_same_v<T, Bytes> || std::is_same_v<T, bool> || std::is_same_v<T, Range> || std::is_same_v<T, Slice> ||
  452. std::is_pointer_v<T> || std::is_enum_v<T>;
  453. template <typename T>
  454. constexpr Type _find_type_in_const_cxx_typeid_map() {
  455. return Type();
  456. }
  457. template <>
  458. constexpr Type _find_type_in_const_cxx_typeid_map<Str>() {
  459. return VM::tp_str;
  460. }
  461. template <>
  462. constexpr Type _find_type_in_const_cxx_typeid_map<List>() {
  463. return VM::tp_list;
  464. }
  465. template <>
  466. constexpr Type _find_type_in_const_cxx_typeid_map<Tuple>() {
  467. return VM::tp_tuple;
  468. }
  469. template <>
  470. constexpr Type _find_type_in_const_cxx_typeid_map<Function>() {
  471. return VM::tp_function;
  472. }
  473. template <>
  474. constexpr Type _find_type_in_const_cxx_typeid_map<NativeFunc>() {
  475. return VM::tp_native_func;
  476. }
  477. template <>
  478. constexpr Type _find_type_in_const_cxx_typeid_map<BoundMethod>() {
  479. return VM::tp_bound_method;
  480. }
  481. template <>
  482. constexpr Type _find_type_in_const_cxx_typeid_map<Range>() {
  483. return VM::tp_range;
  484. }
  485. template <>
  486. constexpr Type _find_type_in_const_cxx_typeid_map<Slice>() {
  487. return VM::tp_slice;
  488. }
  489. template <>
  490. constexpr Type _find_type_in_const_cxx_typeid_map<Exception>() {
  491. return VM::tp_exception;
  492. }
  493. template <>
  494. constexpr Type _find_type_in_const_cxx_typeid_map<Bytes>() {
  495. return VM::tp_bytes;
  496. }
  497. template <>
  498. constexpr Type _find_type_in_const_cxx_typeid_map<MappingProxy>() {
  499. return VM::tp_mappingproxy;
  500. }
  501. template <>
  502. constexpr Type _find_type_in_const_cxx_typeid_map<Dict>() {
  503. return VM::tp_dict;
  504. }
  505. template <>
  506. constexpr Type _find_type_in_const_cxx_typeid_map<Property>() {
  507. return VM::tp_property;
  508. }
  509. template <>
  510. constexpr Type _find_type_in_const_cxx_typeid_map<StarWrapper>() {
  511. return VM::tp_star_wrapper;
  512. }
  513. template <>
  514. constexpr Type _find_type_in_const_cxx_typeid_map<StaticMethod>() {
  515. return VM::tp_staticmethod;
  516. }
  517. template <>
  518. constexpr Type _find_type_in_const_cxx_typeid_map<ClassMethod>() {
  519. return VM::tp_classmethod;
  520. }
  521. template <>
  522. constexpr Type _find_type_in_const_cxx_typeid_map<StackMemory>() {
  523. return VM::tp_stack_memory;
  524. }
  525. template <typename __T>
  526. PyVar py_var(VM* vm, __T&& value) {
  527. using T = std::decay_t<__T>;
  528. static_assert(!std::is_same_v<T, PyVar>, "py_var(VM*, PyVar) is not allowed");
  529. if constexpr(std::is_same_v<T, const char*> || std::is_same_v<T, std::string> ||
  530. std::is_same_v<T, std::string_view>) {
  531. // str (shortcuts)
  532. return VAR(Str(std::forward<__T>(value)));
  533. } else if constexpr(std::is_same_v<T, NoReturn>) {
  534. // NoneType
  535. return vm->None;
  536. } else if constexpr(std::is_same_v<T, bool>) {
  537. // bool
  538. return value ? vm->True : vm->False;
  539. } else if constexpr(is_integral_v<T>) {
  540. // int
  541. return PyVar(VM::tp_int, static_cast<i64>(value));
  542. } else if constexpr(is_floating_point_v<T>) {
  543. // float
  544. return PyVar(VM::tp_float, static_cast<f64>(value));
  545. } else if constexpr(std::is_pointer_v<T>) {
  546. return from_void_p(vm, (void*)value);
  547. } else {
  548. constexpr Type const_type = _find_type_in_const_cxx_typeid_map<T>();
  549. if constexpr((bool)const_type) {
  550. if constexpr(is_sso_v<T>)
  551. return PyVar(const_type, value);
  552. else
  553. return vm->heap.gcnew<T>(const_type, std::forward<__T>(value));
  554. } else {
  555. Type type = vm->_find_type_in_cxx_typeid_map<T>();
  556. if constexpr(is_sso_v<T>)
  557. return PyVar(type, value);
  558. else
  559. return vm->heap.gcnew<T>(type, std::forward<__T>(value));
  560. }
  561. }
  562. }
  563. // fast path for bool if py_var<> cannot be inlined
  564. inline PyVar py_var(VM* vm, bool value) { return value ? vm->True : vm->False; }
  565. template <typename __T, bool with_check>
  566. __T _py_cast__internal(VM* vm, PyVar obj) {
  567. static_assert(!std::is_rvalue_reference_v<__T>, "rvalue reference is not allowed");
  568. using T = std::decay_t<__T>;
  569. static_assert(!(is_sso_v<T> && std::is_reference_v<__T>), "SSO types cannot be reference");
  570. if constexpr(std::is_same_v<T, const char*> || std::is_same_v<T, CString>) {
  571. static_assert(!std::is_reference_v<__T>);
  572. // str (shortcuts)
  573. if(obj == vm->None) return nullptr;
  574. if constexpr(with_check) vm->check_type(obj, vm->tp_str);
  575. return PK_OBJ_GET(Str, obj).c_str();
  576. } else if constexpr(std::is_same_v<T, bool>) {
  577. static_assert(!std::is_reference_v<__T>);
  578. // bool
  579. if constexpr(with_check) {
  580. if(obj == vm->True) return true;
  581. if(obj == vm->False) return false;
  582. vm->TypeError("expected 'bool', got " + _type_name(vm, vm->_tp(obj)).escape());
  583. }
  584. return obj == vm->True;
  585. } else if constexpr(is_integral_v<T>) {
  586. static_assert(!std::is_reference_v<__T>);
  587. // int
  588. if constexpr(with_check) {
  589. if(is_int(obj)) return (T)obj.as<i64>();
  590. vm->TypeError("expected 'int', got " + _type_name(vm, vm->_tp(obj)).escape());
  591. }
  592. return (T)obj.as<i64>();
  593. } else if constexpr(is_floating_point_v<T>) {
  594. static_assert(!std::is_reference_v<__T>);
  595. if(is_float(obj)) return (T)obj.as<f64>();
  596. if(is_int(obj)) return (T)obj.as<i64>();
  597. vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape());
  598. return 0.0f;
  599. } else if constexpr(std::is_enum_v<T>) {
  600. static_assert(!std::is_reference_v<__T>);
  601. return (__T)_py_cast__internal<i64, with_check>(vm, obj);
  602. } else if constexpr(std::is_pointer_v<T>) {
  603. static_assert(!std::is_reference_v<__T>);
  604. return to_void_p<T>(vm, obj);
  605. } else {
  606. constexpr Type const_type = _find_type_in_const_cxx_typeid_map<T>();
  607. if constexpr((bool)const_type) {
  608. if constexpr(with_check) {
  609. if constexpr(std::is_same_v<T, Exception>) {
  610. // Exception is `subclass_enabled`
  611. vm->check_compatible_type(obj, const_type);
  612. } else {
  613. vm->check_type(obj, const_type);
  614. }
  615. }
  616. return PK_OBJ_GET(T, obj);
  617. } else {
  618. if constexpr(with_check) {
  619. Type type = vm->_find_type_in_cxx_typeid_map<T>();
  620. vm->check_compatible_type(obj, type);
  621. }
  622. return PK_OBJ_GET(T, obj);
  623. }
  624. }
  625. }
  626. template <typename __T>
  627. __T py_cast(VM* vm, PyVar obj) {
  628. return _py_cast__internal<__T, true>(vm, obj);
  629. }
  630. template <typename __T>
  631. __T _py_cast(VM* vm, PyVar obj) {
  632. return _py_cast__internal<__T, false>(vm, obj);
  633. }
  634. template <typename T>
  635. PyObject*
  636. VM::register_user_class(PyObject* mod, StrName name, RegisterFunc _register, Type base, bool subclass_enabled) {
  637. PyObject* type = new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
  638. mod->attr().set(name, type);
  639. _cxx_typeid_map[typeid(T)] = type->as<Type>();
  640. _register(this, mod, type);
  641. if(!type->attr().contains(__new__)) {
  642. if constexpr(std::is_default_constructible_v<T>) {
  643. bind_func(type, __new__, -1, [](VM* vm, ArgsView args) {
  644. Type cls_t = args[0]->as<Type>();
  645. return vm->new_object<T>(cls_t);
  646. });
  647. } else {
  648. bind_func(type, __new__, -1, [](VM* vm, ArgsView args) {
  649. vm->NotImplementedError();
  650. return vm->None;
  651. });
  652. }
  653. }
  654. return type;
  655. }
  656. template <typename T>
  657. PyObject* VM::register_user_class(PyObject* mod, StrName name, Type base, bool subclass_enabled) {
  658. return register_user_class<T>(mod, name, &T::_register, base, subclass_enabled);
  659. }
  660. } // namespace pkpy