Rollback vm.hpp

This commit is contained in:
ykiko 2024-06-04 19:48:38 +08:00
parent 1adbc0d036
commit 8ba1a9d245
2 changed files with 105 additions and 174 deletions

View File

@ -98,6 +98,6 @@ QualifierAlignment: Custom
QualifierOrder: ["constexpr", "const", "inline", "static", "type"] QualifierOrder: ["constexpr", "const", "inline", "static", "type"]
SortIncludes: Never SortIncludes: Never
SortUsingDeclarations: LexicographicNumeric SortUsingDeclarations: LexicographicNumeric
IncludeBlocksStyle: Merge IncludeBlocks: Merge
WhitespaceSensitiveMacros: ["PK_PROTECTED"] WhitespaceSensitiveMacros: ["PK_PROTECTED"]

View File

@ -1,13 +1,13 @@
#pragma once #pragma once
#include "pocketpy/objects/object.hpp" #include "pocketpy/interpreter/frame.hpp"
#include "pocketpy/interpreter/gc.hpp"
#include "pocketpy/interpreter/profiler.hpp"
#include "pocketpy/objects/builtins.hpp"
#include "pocketpy/objects/dict.hpp" #include "pocketpy/objects/dict.hpp"
#include "pocketpy/objects/error.hpp" #include "pocketpy/objects/error.hpp"
#include "pocketpy/objects/object.hpp"
#include "pocketpy/objects/stackmemory.hpp" #include "pocketpy/objects/stackmemory.hpp"
#include "pocketpy/objects/builtins.hpp"
#include "pocketpy/interpreter/gc.hpp"
#include "pocketpy/interpreter/frame.hpp"
#include "pocketpy/interpreter/profiler.hpp"
#include <stdexcept> #include <stdexcept>
@ -226,42 +226,39 @@ public:
const bool enable_os; const bool enable_os;
VM(bool enable_os = true); VM(bool enable_os = true);
// clang-format off // clang-format off
#if PK_REGION("Python Equivalents") #if PK_REGION("Python Equivalents")
Str py_str(PyVar obj); // x -> str(x) Str py_str(PyVar obj); // x -> str(x)
Str py_repr(PyVar obj); // x -> repr(x) Str py_repr(PyVar obj); // x -> repr(x)
Str py_json(PyVar obj); // x -> json.dumps(x) Str py_json(PyVar obj); // x -> json.dumps(x)
PyVar py_iter(PyVar obj); // x -> iter(x) PyVar py_iter(PyVar obj); // x -> iter(x)
PyVar py_next(PyVar); // x -> next(x) PyVar py_next(PyVar); // x -> next(x)
PyVar _py_next(const PyTypeInfo*, PyVar); // x -> next(x) with type info cache PyVar _py_next(const PyTypeInfo*, PyVar); // x -> next(x) with type info cache
PyObject* py_import(Str path, bool throw_err = true); // x -> __import__(x) PyObject* py_import(Str path, bool throw_err=true); // x -> __import__(x)
PyVar py_negate(PyVar obj); // x -> -x PyVar py_negate(PyVar obj); // x -> -x
List py_list(PyVar); // x -> list(x) List py_list(PyVar); // x -> list(x)
bool py_callable(PyVar obj); // x -> callable(x) bool py_callable(PyVar obj); // x -> callable(x)
bool py_bool(PyVar obj){ // x -> bool(x)
bool py_bool(PyVar obj) { // x -> bool(x) if(obj.type == tp_bool) return obj._0;
if(obj.type == tp_bool) { return obj._0; }
return __py_bool_non_trivial(obj); return __py_bool_non_trivial(obj);
} }
i64 py_hash(PyVar obj); // x -> hash(x)
i64 py_hash(PyVar obj); // x -> hash(x) bool py_eq(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs == rhs
bool py_lt(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs < rhs
bool py_eq(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs == rhs bool py_le(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs <= rhs
bool py_lt(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs < rhs bool py_gt(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs > rhs
bool py_le(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs <= rhs bool py_ge(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs >= rhs
bool py_gt(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs > rhs bool py_ne(PyVar lhs, PyVar rhs){ // (lhs, rhs) -> lhs != rhs
bool py_ge(PyVar lhs, PyVar rhs); // (lhs, rhs) -> lhs >= rhs
bool py_ne(PyVar lhs, PyVar rhs) { // (lhs, rhs) -> lhs != rhs
return !py_eq(lhs, rhs); return !py_eq(lhs, rhs);
} }
PyVar py_op(std::string_view name); // (name) -> operator.name PyVar py_op(std::string_view name); // (name) -> operator.name
void py_exec(std::string_view, PyVar, PyVar); // exec(source, globals, locals) void py_exec(std::string_view, PyVar, PyVar); // exec(source, globals, locals)
PyVar py_eval(std::string_view, PyVar, PyVar); // eval(source, globals, locals) PyVar py_eval(std::string_view, PyVar, PyVar); // eval(source, globals, locals)
#endif #endif
#if PK_REGION("Utility Methods") #if PK_REGION("Utility Methods")
@ -270,69 +267,59 @@ public:
i64 normalized_index(i64 index, int size); i64 normalized_index(i64 index, int size);
Str disassemble(CodeObject_ co); Str disassemble(CodeObject_ co);
void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step); void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step);
void obj_gc_mark(PyVar obj) { if(obj.is_ptr) __obj_gc_mark(obj.get()); }
void obj_gc_mark(PyVar obj) { void obj_gc_mark(PyObject* p) { if(p) __obj_gc_mark(p); }
if(obj.is_ptr) { __obj_gc_mark(obj.get()); }
}
void obj_gc_mark(PyObject* p) {
if(p) { __obj_gc_mark(p); }
}
#endif #endif
#if PK_REGION("Name Lookup Methods") #if PK_REGION("Name Lookup Methods")
PyVar* find_name_in_mro(Type cls, StrName name); PyVar* find_name_in_mro(Type cls, StrName name);
PyVar get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_err = true, bool fallback = false); PyVar get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_err=true, bool fallback=false);
PyVar getattr(PyVar obj, StrName name, bool throw_err = true); PyVar getattr(PyVar obj, StrName name, bool throw_err=true);
void delattr(PyVar obj, StrName name); void delattr(PyVar obj, StrName name);
void setattr(PyVar obj, StrName name, PyVar value); void setattr(PyVar obj, StrName name, PyVar value);
#endif #endif
#if PK_REGION("Source Execution Methods") #if PK_REGION("Source Execution Methods")
CodeObject_ CodeObject_ compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false);
compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope = false);
Str precompile(std::string_view source, const Str& filename, CompileMode mode); Str precompile(std::string_view source, const Str& filename, CompileMode mode);
PyVar exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module = nullptr); PyVar exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module=nullptr);
PyVar exec(std::string_view source); PyVar exec(std::string_view source);
PyVar eval(std::string_view source); PyVar eval(std::string_view source);
template <typename... Args> template<typename ...Args>
PyVar _exec(Args&&... args) { PyVar _exec(Args&&... args){
callstack.emplace(s_data._sp, std::forward<Args>(args)...); callstack.emplace(s_data._sp, std::forward<Args>(args)...);
return __run_top_frame(); return __run_top_frame();
} }
#endif #endif
#if PK_REGION("Invocation Methods") #if PK_REGION("Invocation Methods")
PyVar vectorcall(int ARGC, int KWARGC = 0, bool op_call = false); PyVar vectorcall(int ARGC, int KWARGC=0, bool op_call=false);
template <typename... Args> template<typename... Args>
PyVar call(PyVar callable, Args&&... args) { PyVar call(PyVar callable, Args&&... args){
PUSH(callable); PUSH(callable); PUSH(PY_NULL);
PUSH(PY_NULL);
__push_varargs(args...); __push_varargs(args...);
return vectorcall(sizeof...(args)); return vectorcall(sizeof...(args));
} }
template <typename... Args> template<typename... Args>
PyVar call_method(PyVar self, PyVar callable, Args&&... args) { PyVar call_method(PyVar self, PyVar callable, Args&&... args){
PUSH(callable); PUSH(callable); PUSH(self);
PUSH(self);
__push_varargs(args...); __push_varargs(args...);
return vectorcall(sizeof...(args)); return vectorcall(sizeof...(args));
} }
template <typename... Args> template<typename... Args>
PyVar call_method(PyVar self, StrName name, Args&&... args) { PyVar call_method(PyVar self, StrName name, Args&&... args){
PyVar callable = get_unbound_method(self, name, &self); PyVar callable = get_unbound_method(self, name, &self);
return call_method(self, callable, args...); return call_method(self, callable, args...);
} }
#endif #endif
#if PK_REGION("Logging Methods") #if PK_REGION("Logging Methods")
virtual void stdout_write(const Str& s) { _stdout(s.data, s.size); } virtual void stdout_write(const Str& s){ _stdout(s.data, s.size); }
virtual void stderr_write(const Str& s){ _stderr(s.data, s.size); }
virtual void stderr_write(const Str& s) { _stderr(s.data, s.size); }
#endif #endif
#if PK_REGION("Magic Bindings") #if PK_REGION("Magic Bindings")
@ -375,162 +362,106 @@ public:
#endif #endif
#if PK_REGION("General Bindings") #if PK_REGION("General Bindings")
PyObject* bind_func(PyObject* obj, PyObject* bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT);
StrName name, PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT){
int argc,
NativeFuncC fn,
any userdata = {},
BindType bt = BindType::DEFAULT);
PyObject* bind_func(Type type,
StrName name,
int argc,
NativeFuncC fn,
any userdata = {},
BindType bt = BindType::DEFAULT) {
return bind_func(_t(type), name, argc, fn, std::move(userdata), bt); return bind_func(_t(type), name, argc, fn, std::move(userdata), bt);
} }
PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset = nullptr); template<typename T, typename F, bool ReadOnly=false>
template <typename T, typename F, bool ReadOnly = false>
PyObject* bind_field(PyObject*, const char*, F T::*); PyObject* bind_field(PyObject*, const char*, F T::*);
PyObject* bind(PyObject*, const char*, NativeFuncC, any userdata = {}, BindType bt = BindType::DEFAULT); PyObject* bind(PyObject*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
template <typename Ret, typename... Params> template<typename Ret, typename... Params>
PyObject* bind(PyObject*, const char*, Ret (*)(Params...), BindType bt = BindType::DEFAULT); PyObject* bind(PyObject*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
template <typename Ret, typename T, typename... Params> template<typename Ret, typename T, typename... Params>
PyObject* bind(PyObject*, const char*, Ret (T::*)(Params...), BindType bt = BindType::DEFAULT); PyObject* bind(PyObject*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
PyObject* PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
bind(PyObject*, const char*, const char*, NativeFuncC, any userdata = {}, BindType bt = BindType::DEFAULT); template<typename Ret, typename... Params>
template <typename Ret, typename... Params> PyObject* bind(PyObject*, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
PyObject* bind(PyObject*, const char*, const char*, Ret (*)(Params...), BindType bt = BindType::DEFAULT); template<typename Ret, typename T, typename... Params>
template <typename Ret, typename T, typename... Params> PyObject* bind(PyObject*, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
PyObject* bind(PyObject*, const char*, const char*, Ret (T::*)(Params...), BindType bt = BindType::DEFAULT);
#endif #endif
#if PK_REGION("Error Reporting Methods") #if PK_REGION("Error Reporting Methods")
[[noreturn]] void _error(PyVar); [[noreturn]] void _error(PyVar);
[[noreturn]] void StackOverflowError() { __builtin_error("StackOverflowError"); } [[noreturn]] void StackOverflowError() { __builtin_error("StackOverflowError"); }
[[noreturn]] void IOError(const Str& msg) { __builtin_error("IOError", msg); } [[noreturn]] void IOError(const Str& msg) { __builtin_error("IOError", msg); }
[[noreturn]] void NotImplementedError(){ __builtin_error("NotImplementedError"); }
[[noreturn]] void NotImplementedError() { __builtin_error("NotImplementedError"); } [[noreturn]] void TypeError(const Str& msg){ __builtin_error("TypeError", msg); }
[[noreturn]] void TypeError(Type expected, Type actual) { TypeError("expected " + _type_name(vm, expected).escape() + ", got " + _type_name(vm, actual).escape()); }
[[noreturn]] void TypeError(const Str& msg) { __builtin_error("TypeError", msg); } [[noreturn]] void IndexError(const Str& msg){ __builtin_error("IndexError", msg); }
[[noreturn]] void ValueError(const Str& msg){ __builtin_error("ValueError", msg); }
[[noreturn]] void TypeError(Type expected, Type actual) { [[noreturn]] void RuntimeError(const Str& msg){ __builtin_error("RuntimeError", msg); }
TypeError("expected " + _type_name(vm, expected).escape() + ", got " + _type_name(vm, actual).escape()); [[noreturn]] void ZeroDivisionError(const Str& msg){ __builtin_error("ZeroDivisionError", msg); }
} [[noreturn]] void ZeroDivisionError(){ __builtin_error("ZeroDivisionError", "division by zero"); }
[[noreturn]] void NameError(StrName name){ __builtin_error("NameError", _S("name ", name.escape() + " is not defined")); }
[[noreturn]] void IndexError(const Str& msg) { __builtin_error("IndexError", msg); } [[noreturn]] void UnboundLocalError(StrName name){ __builtin_error("UnboundLocalError", _S("local variable ", name.escape() + " referenced before assignment")); }
[[noreturn]] void KeyError(PyVar obj){ __builtin_error("KeyError", obj); }
[[noreturn]] void ValueError(const Str& msg) { __builtin_error("ValueError", msg); } [[noreturn]] void ImportError(const Str& msg){ __builtin_error("ImportError", msg); }
[[noreturn]] void AssertionError(const Str& msg){ __builtin_error("AssertionError", msg); }
[[noreturn]] void RuntimeError(const Str& msg) { __builtin_error("RuntimeError", msg); } [[noreturn]] void AssertionError(){ __builtin_error("AssertionError"); }
[[noreturn]] void ZeroDivisionError(const Str& msg) { __builtin_error("ZeroDivisionError", msg); }
[[noreturn]] void ZeroDivisionError() { __builtin_error("ZeroDivisionError", "division by zero"); }
[[noreturn]] void NameError(StrName name) {
__builtin_error("NameError", _S("name ", name.escape() + " is not defined"));
}
[[noreturn]] void UnboundLocalError(StrName name) {
__builtin_error("UnboundLocalError", _S("local variable ", name.escape() + " referenced before assignment"));
}
[[noreturn]] void KeyError(PyVar obj) { __builtin_error("KeyError", obj); }
[[noreturn]] void ImportError(const Str& msg) { __builtin_error("ImportError", msg); }
[[noreturn]] void AssertionError(const Str& msg) { __builtin_error("AssertionError", msg); }
[[noreturn]] void AssertionError() { __builtin_error("AssertionError"); }
[[noreturn]] void BinaryOptError(const char* op, PyVar _0, PyVar _1); [[noreturn]] void BinaryOptError(const char* op, PyVar _0, PyVar _1);
[[noreturn]] void AttributeError(PyVar obj, StrName name); [[noreturn]] void AttributeError(PyVar obj, StrName name);
[[noreturn]] void AttributeError(const Str& msg){ __builtin_error("AttributeError", msg); }
[[noreturn]] void AttributeError(const Str& msg) { __builtin_error("AttributeError", msg); }
#endif #endif
#if PK_REGION("Type Checking Methods") #if PK_REGION("Type Checking Methods")
bool isinstance(PyVar obj, Type base); bool isinstance(PyVar obj, Type base);
bool issubclass(Type cls, Type base); bool issubclass(Type cls, Type base);
void check_type(PyVar obj, Type type){ if(!is_type(obj, type)) TypeError(type, _tp(obj)); }
void check_compatible_type(PyVar obj, Type type){ if(!isinstance(obj, type)) TypeError(type, _tp(obj)); }
void check_type(PyVar obj, Type type) { Type _tp(PyVar obj){ return obj.type; }
if(!is_type(obj, type)) { TypeError(type, _tp(obj)); }
}
void check_compatible_type(PyVar obj, Type type) {
if(!isinstance(obj, type)) { TypeError(type, _tp(obj)); }
}
Type _tp(PyVar obj) { return obj.type; }
const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; } const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; }
const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; } const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; }
PyObject* _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
PyObject* _t(PyVar obj) { return _all_types[_tp(obj)].obj; } PyObject* _t(Type type){ return _all_types[type].obj; }
PyObject* _t(Type type) { return _all_types[type].obj; }
// equivalent to `obj == NotImplemented` but faster // equivalent to `obj == NotImplemented` but faster
static bool is_not_implemented(PyVar obj) { return obj.type == tp_not_implemented; } static bool is_not_implemented(PyVar obj){ return obj.type == tp_not_implemented; }
#endif #endif
#if PK_REGION("User Type Registration") #if PK_REGION("User Type Registration")
PyObject* new_module(Str name, Str package = ""); PyObject* new_module(Str name, Str package="");
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt = {}); PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt={});
template <typename T> template<typename T>
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled) { PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled){
return new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>()); return new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
} }
template <typename T> template<typename T>
Type _tp_user() { Type _tp_user(){ return _find_type_in_cxx_typeid_map<T>(); }
return _find_type_in_cxx_typeid_map<T>(); template<typename T>
} bool is_user_type(PyVar obj){ return _tp(obj) == _tp_user<T>(); }
template <typename T> template<typename T>
bool is_user_type(PyVar obj) { PyObject* register_user_class(PyObject*, StrName, RegisterFunc, Type base=tp_object, bool subclass_enabled=false);
return _tp(obj) == _tp_user<T>(); template<typename T>
} PyObject* register_user_class(PyObject*, StrName, Type base=tp_object, bool subclass_enabled=false);
template <typename T> template<typename T, typename ...Args>
PyObject* PyVar new_user_object(Args&&... args){
register_user_class(PyObject*, StrName, RegisterFunc, Type base = tp_object, bool subclass_enabled = false);
template <typename T>
PyObject* register_user_class(PyObject*, StrName, Type base = tp_object, bool subclass_enabled = false);
template <typename T, typename... Args>
PyVar new_user_object(Args&&... args) {
return new_object<T>(_tp_user<T>(), std::forward<Args>(args)...); return new_object<T>(_tp_user<T>(), std::forward<Args>(args)...);
} }
template <typename T, typename... Args> template<typename T, typename ...Args>
PyVar new_object(Type type, Args&&... args) { PyVar new_object(Type type, Args&&... args){
if constexpr(is_sso_v<T>) { if constexpr(is_sso_v<T>) return PyVar(type, T(std::forward<Args>(args)...));
return PyVar(type, T(std::forward<Args>(args)...)); else return heap.gcnew<T>(type, std::forward<Args>(args)...);
} else {
return heap.gcnew<T>(type, std::forward<Args>(args)...);
}
} }
template <typename T, typename... Args> template<typename T, typename ...Args>
void new_stack_object(Type type, Args&&... args) { void new_stack_object(Type type, Args&&... args){
static_assert(std::is_same_v<T, std::decay_t<T>>); static_assert(std::is_same_v<T, std::decay_t<T>>);
static_assert(std::is_trivially_destructible_v<T>); static_assert(std::is_trivially_destructible_v<T>);
PyObject* p = new (__stack_alloc(py_sizeof<T>)) PyObject(type); PyObject* p = new(__stack_alloc(py_sizeof<T>)) PyObject(type);
p->placement_new<T>(std::forward<Args>(args)...); p->placement_new<T>(std::forward<Args>(args)...);
vm->s_data.emplace(p->type, p); vm->s_data.emplace(p->type, p);
} }
#endif #endif
// clang-format on // clang-format on
template <typename T> template <typename T>
Type _find_type_in_cxx_typeid_map() { Type _find_type_in_cxx_typeid_map() {