From 175c571fbb04826898a2bdeb4d96e683255df1be Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 16 Jun 2024 19:56:33 +0800 Subject: [PATCH] more move --- include/pocketpy/common/traits.hpp | 3 +- include/pocketpy/compiler/expr.hpp | 1 - include/pocketpy/interpreter/vm.hpp | 33 +++++++----- include/pocketpy/modules/linalg.hpp | 8 +-- include/pocketpy/objects/base.h | 75 ++++++++++++++++----------- include/pocketpy/objects/base.hpp | 37 ++++--------- include/pocketpy/objects/builtins.hpp | 15 ++---- include/pocketpy/objects/object.hpp | 3 +- src/common/sstream.c | 2 +- src/compiler/expr.cpp | 13 ++--- src/interpreter/ceval.cpp | 37 +++++++------ src/interpreter/iter.cpp | 3 +- src/interpreter/vm.cpp | 24 +++++---- src/modules/array2d.cpp | 8 +-- src/objects/base.c | 15 +++--- src/objects/builtins.cpp | 6 --- src/objects/object.c | 4 +- src/pocketpy.cpp | 27 +++++----- 18 files changed, 154 insertions(+), 160 deletions(-) delete mode 100644 src/objects/builtins.cpp diff --git a/include/pocketpy/common/traits.hpp b/include/pocketpy/common/traits.hpp index 4aa1c789..0110a4ff 100644 --- a/include/pocketpy/common/traits.hpp +++ b/include/pocketpy/common/traits.hpp @@ -21,9 +21,8 @@ constexpr inline bool is_floating_point_v = std::is_same_v || std::is_ template constexpr inline bool is_sso_v = is_integral_v || is_floating_point_v; -// if is_sso_v is true, return T, else return T& template -using obj_get_t = std::conditional_t, T, T&>; +using obj_get_t = T&; template constexpr inline bool is_trivially_relocatable_v = diff --git a/include/pocketpy/compiler/expr.hpp b/include/pocketpy/compiler/expr.hpp index 8834f4a5..bfb0d1e5 100644 --- a/include/pocketpy/compiler/expr.hpp +++ b/include/pocketpy/compiler/expr.hpp @@ -69,7 +69,6 @@ struct CodeEmitContext{ int curr_iblock = 0; bool is_compiling_class = false; - small_map _co_consts_nonstring_dedup_map; small_map _co_consts_string_dedup_map; int get_loop() const noexcept; diff --git a/include/pocketpy/interpreter/vm.hpp b/include/pocketpy/interpreter/vm.hpp index fc1dc8b5..d1d16da6 100644 --- a/include/pocketpy/interpreter/vm.hpp +++ b/include/pocketpy/interpreter/vm.hpp @@ -175,14 +175,14 @@ public: vector s_view; } __c; - PyVar StopIteration; // a special Exception class + PyObject* StopIteration; // a special Exception class PyObject* builtins; PyObject* _main; // typeid -> Type small_map _cxx_typeid_map; // this is for repr() recursion detection (no need to mark) - vector _repr_recursion_set; + vector _repr_recursion_set; ImportContext __import_context; PyObject* __last_exception; @@ -550,10 +550,18 @@ PyVar py_var(VM* vm, __T&& value) { return value ? vm->True : vm->False; } else if constexpr(is_integral_v) { // int - return PyVar(VM::tp_int, static_cast(value)); + ::PyVar retval; + retval.type = tp_int; + retval.is_ptr = false; + retval._i64 = (i64)value; + return retval; } else if constexpr(is_floating_point_v) { // float - return PyVar(VM::tp_float, static_cast(value)); + ::PyVar retval; + retval.type = tp_float; + retval.is_ptr = false; + retval._f64 = (f64)value; + return retval; } else if constexpr(std::is_pointer_v) { return from_void_p(vm, (void*)value); } else { @@ -592,23 +600,22 @@ __T _py_cast__internal(VM* vm, PyVar obj) { static_assert(!std::is_reference_v<__T>); // bool if constexpr(with_check) { - if(obj == vm->True) return true; - if(obj == vm->False) return false; - vm->TypeError("expected 'bool', got " + _type_name(vm, vm->_tp(obj)).escape()); + if(obj.type != tp_bool){ + vm->TypeError("expected 'bool', got " + _type_name(vm, vm->_tp(obj)).escape()); + } } - return obj == vm->True; + return obj._bool; } else if constexpr(is_integral_v) { static_assert(!std::is_reference_v<__T>); // int if constexpr(with_check) { - if(is_int(obj)) return (T)obj.as(); - vm->TypeError("expected 'int', got " + _type_name(vm, vm->_tp(obj)).escape()); + if(!is_int(obj)) vm->TypeError("expected 'int', got " + _type_name(vm, vm->_tp(obj)).escape()); } - return (T)obj.as(); + return (T)obj._i64; } else if constexpr(is_floating_point_v) { static_assert(!std::is_reference_v<__T>); - if(is_float(obj)) return (T)obj.as(); - if(is_int(obj)) return (T)obj.as(); + if(is_float(obj)) return (T)obj._f64; + if(is_int(obj)) return (T)obj._i64; vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape()); return 0.0f; } else if constexpr(std::is_enum_v) { diff --git a/include/pocketpy/modules/linalg.hpp b/include/pocketpy/modules/linalg.hpp index 21c386ed..630eb572 100644 --- a/include/pocketpy/modules/linalg.hpp +++ b/include/pocketpy/modules/linalg.hpp @@ -207,9 +207,9 @@ static_assert(is_pod_v); static_assert(is_pod_v); static_assert(is_pod_v); -template <> -constexpr inline bool is_sso_v = true; -template <> -constexpr inline bool is_sso_v = true; +// template <> +// constexpr inline bool is_sso_v = true; +// template <> +// constexpr inline bool is_sso_v = true; } // namespace pkpy diff --git a/include/pocketpy/objects/base.h b/include/pocketpy/objects/base.h index 4e006323..07d7640c 100644 --- a/include/pocketpy/objects/base.h +++ b/include/pocketpy/objects/base.h @@ -19,8 +19,7 @@ typedef struct PyObject PyObject; typedef struct PyVar{ pkpy_Type type; bool is_ptr; - uint8_t flags; - int flags_ex; + int extra; union { int64_t _i64; double _f64; @@ -31,33 +30,17 @@ typedef struct PyVar{ }; } PyVar; + +#define PyVar__as(T, self) _Generic((T), \ + int64_t: self->_i64, \ + double: self->_f64, \ + bool: self->_bool, \ + PyObject*: self->_obj, \ + void*: self->_ptr, \ +) + static_assert(sizeof(PyVar) == 16, "sizeof(PyVar) != 16"); -PK_INLINE bool PyVar__is_null(const PyVar* self) { return self->type == 0; } -PK_INLINE int64_t PyVar__hash(const PyVar* self) { return self->flags_ex + self->_i64; } - -PK_INLINE bool PyVar__less(const PyVar* self, const PyVar* other){ - return memcmp(self, other, sizeof(PyVar)) < 0; -} -PK_INLINE bool PyVar__equal(const PyVar* self, const PyVar* other){ - return memcmp(self, other, sizeof(PyVar)) == 0; -} - -PK_INLINE void PyVar__ctor(PyVar* self, pkpy_Type type, PyObject* obj){ - self->type = type; - self->is_ptr = true; - self->flags = 0; - self->flags_ex = 0; - self->_obj = obj; -} - -void PyVar__ctor2(PyVar* self, PyObject* existing); - -#define pkpy_Var__is_null(self) ((self)->type == 0) -#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0) -bool pkpy_Var__eq__(void *vm, PyVar a, PyVar b); -int64_t pkpy_Var__hash__(void *vm, PyVar a); - extern const pkpy_Type tp_object, tp_type; extern const pkpy_Type tp_int, tp_float, tp_bool, tp_str; extern const pkpy_Type tp_list, tp_tuple; @@ -68,11 +51,41 @@ extern const pkpy_Type tp_dict, tp_property, tp_star_wrapper; extern const pkpy_Type tp_staticmethod, tp_classmethod; extern const pkpy_Type tp_none_type, tp_not_implemented_type; extern const pkpy_Type tp_ellipsis; +extern const pkpy_Type tp_op_call, tp_op_yield; -extern const PyVar pkpy_True, pkpy_False, pkpy_None; -extern const PyVar pkpy_NotImplemented, pkpy_Ellipsis; -extern const PyVar pkpy_NULL; +PK_INLINE bool PyVar__is_null(const PyVar* self) { return self->type == 0; } +PK_INLINE int64_t PyVar__hash(const PyVar* self) { return self->extra + self->_i64; } + +PK_INLINE void PyVar__ctor(PyVar* self, pkpy_Type type, PyObject* obj){ + self->type = type; + self->is_ptr = true; + self->_obj = obj; +} + +void PyVar__ctor3(PyVar* self, PyObject* existing); + +PK_INLINE bool PyVar__IS_OP(const PyVar* a, const PyVar* b){ + return a->is_ptr && b->is_ptr && a->_obj == b->_obj; +} + +#define pkpy_Var__is_null(self) ((self)->type == 0) +#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0) +bool pkpy_Var__eq__(void *vm, PyVar a, PyVar b); +int64_t pkpy_Var__hash__(void *vm, PyVar a); + +extern PyVar pkpy_True, pkpy_False, pkpy_None; +extern PyVar pkpy_NotImplemented, pkpy_Ellipsis; +extern PyVar pkpy_NULL, pkpy_OP_CALL, pkpy_OP_YIELD; #ifdef __cplusplus } -#endif \ No newline at end of file +#endif + +/* +SSO types: +1. int64_t +2. double +3. bool (dummy) +4. tuple (extra + void*) +5. string (extra + void* or buf) +*/ \ No newline at end of file diff --git a/include/pocketpy/objects/base.hpp b/include/pocketpy/objects/base.hpp index 5fec9237..a34eb5f6 100644 --- a/include/pocketpy/objects/base.hpp +++ b/include/pocketpy/objects/base.hpp @@ -26,7 +26,7 @@ struct PyVar final: ::PyVar { // implict conversion PyVar(PyObject* existing){ - PyVar__ctor2(this, (::PyObject*)existing); + PyVar__ctor3(this, (::PyObject*)existing); } /* We must initialize all members to allow == operator to work correctly */ @@ -40,26 +40,10 @@ struct PyVar final: ::PyVar { PyVar__ctor(this, type, (::PyObject*)p); } - // SSO initialized (is_sso = true) - template - PyVar(Type type, T value){ - static_assert(sizeof(T) <= 12, "SSO size exceeded"); + PyVar(Type type, i64 value){ this->type = type; this->is_ptr = false; - this->flags = 0; - this->flags_ex = 0; - this->_i64 = 0; - as() = value; - } - - template - T& as() { - static_assert(!std::is_reference_v); - if constexpr(sizeof(T) <= 8) { - return reinterpret_cast(_i64); - } else { - return reinterpret_cast(flags_ex); - } + this->_i64 = value; } explicit operator bool () const { return (bool)type; } @@ -68,10 +52,12 @@ struct PyVar final: ::PyVar { memset(this, 0, sizeof(PyVar)); } - bool operator== (const PyVar& other) const { return PyVar__equal(this, &other); } - bool operator!= (const PyVar& other) const { return !PyVar__equal(this, &other); } - bool operator== (std::nullptr_t) const { return !(bool)type; } - bool operator!= (std::nullptr_t) const { return (bool)type; } + bool operator==(PyObject* other){ + return is_ptr && (PyObject*)_obj == other; + } + bool operator!=(PyObject* other){ + return !is_ptr || (PyObject*)_obj != other; + } PyObject* get() const { assert(is_ptr); @@ -88,11 +74,6 @@ struct PyVar final: ::PyVar { template obj_get_t obj_get(); - // std::less<> for map-like containers - bool operator< (const PyVar& other) const { - return PyVar__less(this, &other); - } - // implicit convert from ::PyVar PyVar(const ::PyVar& var) { memcpy(this, &var, sizeof(var)); diff --git a/include/pocketpy/objects/builtins.hpp b/include/pocketpy/objects/builtins.hpp index 5e84cbbf..a80b9240 100644 --- a/include/pocketpy/objects/builtins.hpp +++ b/include/pocketpy/objects/builtins.hpp @@ -116,14 +116,11 @@ T to_void_p(VM*, PyVar); PyVar from_void_p(VM*, void*); template -obj_get_t PyVar::obj_get() { - if constexpr(is_sso_v) { - return as(); - } else { - assert(is_ptr); - void* v = PyObject__value_ptr(_obj); - return *reinterpret_cast(v); - } +T& PyVar::obj_get() { + static_assert(!is_sso_v, "unsupported"); + assert(is_ptr); + void* v = PyObject__value_ptr(_obj); + return *reinterpret_cast(v); } #define PK_OBJ_GET(T, obj) ((obj).obj_get()) @@ -140,7 +137,5 @@ obj_get_t PyVar::obj_get() { /*****************************************************************/ #define PY_NULL nullptr -extern PyVar PY_OP_CALL; -extern PyVar PY_OP_YIELD; } // namespace pkpy diff --git a/include/pocketpy/objects/object.hpp b/include/pocketpy/objects/object.hpp index 4e957a91..b55a81ba 100644 --- a/include/pocketpy/objects/object.hpp +++ b/include/pocketpy/objects/object.hpp @@ -12,9 +12,10 @@ struct NameDict; struct PyObject final: ::PyObject { bool is_attr_valid() const noexcept { return _attr != nullptr; } - void* _value_ptr() noexcept { return (char*)this + 16; } + void* _value_ptr() noexcept { return PyObject__value_ptr(this); } NameDict& attr() const{ + assert(is_attr_valid()); return *(NameDict*)_attr; } diff --git a/src/common/sstream.c b/src/common/sstream.c index 5b9b513f..727d766f 100644 --- a/src/common/sstream.c +++ b/src/common/sstream.c @@ -51,7 +51,7 @@ void pkpy_SStream__write_i64(pkpy_SStream* self, int64_t val) { } void pkpy_SStream__write_float(pkpy_SStream* self, float val, int precision){ - return pkpy_SStream__write_double(self, val, precision); + pkpy_SStream__write_double(self, val, precision); } void pkpy_SStream__write_double(pkpy_SStream* self, double val, int precision){ diff --git a/src/compiler/expr.cpp b/src/compiler/expr.cpp index ebccda71..b4bc8af2 100644 --- a/src/compiler/expr.cpp +++ b/src/compiler/expr.cpp @@ -137,16 +137,9 @@ int CodeEmitContext::add_const_string(std::string_view key) noexcept{ int CodeEmitContext::add_const(PyVar v) noexcept{ assert(!is_type(v, VM::tp_str)); - // non-string deduplication - int* val = _co_consts_nonstring_dedup_map.try_get(v); - if(val) { - return *val; - } else { - co->consts.push_back(v); - int index = co->consts.size() - 1; - _co_consts_nonstring_dedup_map.insert(v, index); - return index; - } + co->consts.push_back(v); + int index = co->consts.size() - 1; + return index; } int CodeEmitContext::add_func_decl(FuncDecl_ decl) noexcept{ diff --git a/src/interpreter/ceval.cpp b/src/interpreter/ceval.cpp index 48cef820..e1c9bdac 100644 --- a/src/interpreter/ceval.cpp +++ b/src/interpreter/ceval.cpp @@ -1,18 +1,19 @@ #include "pocketpy/interpreter/ceval.hpp" +#include "pocketpy/objects/base.h" namespace pkpy { #define PREDICT_INT_OP(op) \ if(is_int(_0) && is_int(_1)) { \ - TOP() = VAR(_0.as() op _1.as()); \ + TOP() = VAR(_0._i64 op _1._i64); \ DISPATCH() \ } #define PREDICT_INT_DIV_OP(op) \ if(is_int(_0) && is_int(_1)) { \ - i64 divisor = _1.as(); \ + i64 divisor = _1._i64; \ if(divisor == 0) ZeroDivisionError(); \ - TOP() = VAR(_0.as() op divisor); \ + TOP() = VAR(_0._i64 op divisor); \ DISPATCH() \ } @@ -24,7 +25,7 @@ namespace pkpy { } else { \ PyVar self; \ PyVar _2 = get_unbound_method(_0, func, &self, false); \ - if(_2 != nullptr) \ + if(_2) \ ret = call_method(self, _2, _1); \ else \ ret = NotImplemented; \ @@ -32,7 +33,7 @@ namespace pkpy { if(is_not_implemented(ret)) { \ PyVar self; \ PyVar _2 = get_unbound_method(_1, rfunc, &self, false); \ - if(_2 != nullptr) \ + if(_2) \ ret = call_method(self, _2, _0); \ else \ BinaryOptError(op, _0, _1); \ @@ -65,22 +66,26 @@ void VM::__op_unpack_sequence(uint16_t arg) { bool VM::py_lt(PyVar _0, PyVar _1) { BINARY_F_COMPARE(__lt__, "<", __gt__); - return ret == True; + assert(ret.type == tp_bool); + return ret._bool; } bool VM::py_le(PyVar _0, PyVar _1) { BINARY_F_COMPARE(__le__, "<=", __ge__); - return ret == True; + assert(ret.type == tp_bool); + return ret._bool; } bool VM::py_gt(PyVar _0, PyVar _1) { BINARY_F_COMPARE(__gt__, ">", __lt__); - return ret == True; + assert(ret.type == tp_bool); + return ret._bool; } bool VM::py_ge(PyVar _0, PyVar _1) { BINARY_F_COMPARE(__ge__, ">=", __le__); - return ret == True; + assert(ret.type == tp_bool); + return ret._bool; } #undef BINARY_F_COMPARE @@ -167,7 +172,7 @@ PyVar VM::__run_top_frame() { } DISPATCH() case OP_PRINT_EXPR: - if(TOP() != None) stdout_write(py_repr(TOP()) + "\n"); + if(!is_none(TOP())) stdout_write(py_repr(TOP()) + "\n"); POP(); DISPATCH() /*****************************************/ @@ -717,13 +722,13 @@ PyVar VM::__run_top_frame() { case OP_IS_OP: { PyVar _1 = POPX(); // rhs PyVar _0 = TOP(); // lhs - TOP() = _0 == _1 ? True : False; + TOP() = PyVar__IS_OP(&_0, &_1) ? True : False; } DISPATCH() case OP_IS_NOT_OP: { PyVar _1 = POPX(); // rhs PyVar _0 = TOP(); // lhs - TOP() = _0 != _1 ? True : False; + TOP() = PyVar__IS_OP(&_0, &_1) ? False : True; } DISPATCH() case OP_CONTAINS_OP: { @@ -801,7 +806,7 @@ PyVar VM::__run_top_frame() { PyVar _0 = vectorcall(byte.arg & 0xFF, // ARGC (byte.arg >> 8) & 0xFF, // KWARGC true); - if(_0 == PY_OP_CALL) { + if(_0.type == tp_op_call) { frame = &callstack.top(); goto __NEXT_FRAME; } @@ -835,7 +840,7 @@ PyVar VM::__run_top_frame() { 0, // KWARGC true); } - if(_0 == PY_OP_CALL) { + if(_0.type == tp_op_call) { frame = &callstack.top(); goto __NEXT_FRAME; } @@ -854,7 +859,7 @@ PyVar VM::__run_top_frame() { } } DISPATCH() - case OP_YIELD_VALUE: return PY_OP_YIELD; + case OP_YIELD_VALUE: return pkpy_OP_YIELD; /*****************************************/ case OP_LIST_APPEND: { PyVar _0 = POPX(); @@ -926,7 +931,7 @@ PyVar VM::__run_top_frame() { DISPATCH_JUMP_ABSOLUTE(target) } else { PUSH(_0); - return PY_OP_YIELD; + return pkpy_OP_YIELD; } } case OP_FOR_ITER_UNPACK: { diff --git a/src/interpreter/iter.cpp b/src/interpreter/iter.cpp index 25901a61..cac1db54 100644 --- a/src/interpreter/iter.cpp +++ b/src/interpreter/iter.cpp @@ -1,4 +1,5 @@ #include "pocketpy/interpreter/iter.hpp" +#include "pocketpy/objects/base.h" namespace pkpy { @@ -76,7 +77,7 @@ PyVar Generator::next(VM* vm) { throw; } - if(ret == PY_OP_YIELD) { + if(ret->type == tp_op_yield) { // backup the context lf = vm->callstack.popx(); ret = vm->s_data.popx(); diff --git a/src/interpreter/vm.cpp b/src/interpreter/vm.cpp index 6f595aad..cd19c645 100644 --- a/src/interpreter/vm.cpp +++ b/src/interpreter/vm.cpp @@ -60,7 +60,7 @@ struct JsonSerializer { if(std::isinf(val) || std::isnan(val)) vm->ValueError("cannot jsonify 'nan' or 'inf'"); ss << val; } else if(obj_t == vm->tp_bool) { - ss << (obj == vm->True ? "true" : "false"); + ss << (obj._bool ? "true" : "false"); } else if(obj_t == vm->tp_str) { ss << _CAST(Str&, obj).escape('"'); } else if(obj_t == vm->tp_list) { @@ -230,23 +230,23 @@ PyObject* VM::new_type_object(PyObject* mod, StrName name, Type base, bool subcl } bool VM::py_eq(PyVar lhs, PyVar rhs) { - if(is_int(lhs) && is_int(rhs)) return lhs.as() == rhs.as(); + if(is_int(lhs) && is_int(rhs)) return lhs._i64 == rhs._i64; const PyTypeInfo* ti = _tp_info(lhs); PyVar res; if(ti->m__eq__) { res = ti->m__eq__(this, lhs, rhs); - if(!is_not_implemented(res)) return res == vm->True; + if(!is_not_implemented(res)) return res._bool; } res = call_method(lhs, __eq__, rhs); - if(!is_not_implemented(res)) return res == vm->True; + if(!is_not_implemented(res)) return res._bool; ti = _tp_info(rhs); if(ti->m__eq__) { res = ti->m__eq__(this, rhs, lhs); - if(!is_not_implemented(res)) return res == vm->True; + if(!is_not_implemented(res)) return res._bool; } res = call_method(rhs, __eq__, lhs); - if(!is_not_implemented(res)) return res == vm->True; + if(!is_not_implemented(res)) return res._bool; return false; } @@ -538,7 +538,8 @@ i64 VM::py_hash(PyVar obj) { has_custom_eq = true; else { f = get_unbound_method(obj, __eq__, &self, false); - has_custom_eq = f != _t(tp_object)->attr()[__eq__]; + PyVar base_eq = _t(tp_object)->attr()[__eq__]; + has_custom_eq = !PyVar__IS_OP(&f, &base_eq); } if(has_custom_eq) { TypeError(_S("unhashable type: ", ti->name.escape())); @@ -901,6 +902,9 @@ void VM::__init_builtin_types() { validate(tp_not_implemented_type, new_type_object(nullptr, "NotImplementedType", tp_object, false)); validate(tp_ellipsis, new_type_object(nullptr, "ellipsis", tp_object, false)); + validate(::tp_op_call, new_type_object(nullptr, "__op_call", tp_object, false)); + validate(::tp_op_yield, new_type_object(nullptr, "__op_yield", tp_object, false)); + // SyntaxError and IndentationError must be created here PyObject* SyntaxError = new_type_object(nullptr, "SyntaxError", tp_exception, true); PyObject* IndentationError = new_type_object(nullptr, "IndentationError", SyntaxError->as(), true); @@ -1103,7 +1107,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call) { // simple or normal callstack.emplace(p0, co, fn._module, callable.get(), args.begin()); - if(op_call) return PY_OP_CALL; + if(op_call) return pkpy_OP_CALL; return __run_top_frame(); /*****************_py_call*****************/ } @@ -1137,7 +1141,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call) { PyVar new_f = *find_name_in_mro(PK_OBJ_GET(Type, callable), __new__); PyVar obj; assert(new_f != nullptr && p0[1] == PY_NULL); - if(new_f == __cached_object_new) { + if(PyVar__IS_OP(&new_f, &__cached_object_new)) { // fast path for object.__new__ obj = vm->new_object(PK_OBJ_GET(Type, callable)); } else { @@ -1326,7 +1330,7 @@ void VM::setattr(PyVar obj, StrName name, PyVar value) { // handle descriptor if(is_type(*cls_var, tp_property)) { const Property& prop = _CAST(Property&, *cls_var); - if(prop.setter != vm->None) { + if(!is_none(prop.setter)) { call(prop.setter, obj, value); } else { TypeError(_S("readonly attribute: ", name.escape())); diff --git a/src/modules/array2d.cpp b/src/modules/array2d.cpp index b2a1b9b0..12e833a8 100644 --- a/src/modules/array2d.cpp +++ b/src/modules/array2d.cpp @@ -113,8 +113,8 @@ struct Array2d { const Tuple& xy = CAST(Tuple&, _1); if(is_int(xy[0]) && is_int(xy[1])) { - i64 col = xy[0].as(); - i64 row = xy[1].as(); + i64 col = xy[0]._i64; + i64 row = xy[1]._i64; self.check_valid(vm, col, row); return self._get(col, row); } @@ -138,8 +138,8 @@ struct Array2d { Array2d& self = PK_OBJ_GET(Array2d, _0); const Tuple& xy = CAST(Tuple&, _1); if(is_int(xy[0]) && is_int(xy[1])) { - i64 col = xy[0].as(); - i64 row = xy[1].as(); + i64 col = xy[0]._i64; + i64 row = xy[1]._i64; self.check_valid(vm, col, row); self._set(col, row, _2); return; diff --git a/src/objects/base.c b/src/objects/base.c index 3c584efa..21dc4956 100644 --- a/src/objects/base.c +++ b/src/objects/base.c @@ -11,10 +11,13 @@ const pkpy_Type tp_dict = 19, tp_property = 20, tp_star_wrapper = 21; const pkpy_Type tp_staticmethod = 22, tp_classmethod = 23; const pkpy_Type tp_none_type = 24, tp_not_implemented_type = 25; const pkpy_Type tp_ellipsis = 26; +const pkpy_Type tp_op_call = 27, tp_op_yield = 28; -const PyVar pkpy_True = {.type=tp_bool, .is_ptr=false, .flags=0, .flags_ex=0, ._bool=true}; -const PyVar pkpy_False = {.type=tp_bool, .is_ptr=false, .flags=0, .flags_ex=0, ._bool=false}; -const PyVar pkpy_None = {.type=tp_none_type, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0}; -const PyVar pkpy_NotImplemented = {.type=tp_not_implemented_type, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0}; -const PyVar pkpy_Ellipsis = {.type=tp_ellipsis, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0}; -const PyVar pkpy_NULL = {.type=0, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0}; \ No newline at end of file +PyVar pkpy_True = {.type=tp_bool, .is_ptr=false, ._bool=true}; +PyVar pkpy_False = {.type=tp_bool, .is_ptr=false, ._bool=false}; +PyVar pkpy_None = {.type=tp_none_type, .is_ptr=false}; +PyVar pkpy_NotImplemented = {.type=tp_not_implemented_type, .is_ptr=false}; +PyVar pkpy_Ellipsis = {.type=tp_ellipsis, .is_ptr=false}; +PyVar pkpy_NULL = {.type=0, .is_ptr=false}; +PyVar pkpy_OP_CALL = {.type=tp_op_call, .is_ptr=false}; +PyVar pkpy_OP_YIELD = {.type=tp_op_yield, .is_ptr=false}; diff --git a/src/objects/builtins.cpp b/src/objects/builtins.cpp deleted file mode 100644 index c6e174f1..00000000 --- a/src/objects/builtins.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "pocketpy/objects/builtins.hpp" - -namespace pkpy { -PyVar PY_OP_CALL(Type(), new PyObject(Type(), true)); -PyVar PY_OP_YIELD(Type(), new PyObject(Type(), true)); -} // namespace pkpy diff --git a/src/objects/object.c b/src/objects/object.c index 49ae1bb2..c6e8f25e 100644 --- a/src/objects/object.c +++ b/src/objects/object.c @@ -1,10 +1,8 @@ #include "pocketpy/objects/object.h" -void PyVar__ctor2(PyVar* self, PyObject* existing){ +void PyVar__ctor3(PyVar* self, PyObject* existing){ assert(existing); self->type = existing->type; self->is_ptr = true; - self->flags = 0; - self->flags_ex = 0; self->_obj = existing; } diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 796dc040..bb35e4ab 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -11,6 +11,7 @@ #include "pocketpy/modules/linalg.hpp" #include "pocketpy/modules/random.hpp" #include "pocketpy/modules/modules.hpp" +#include "pocketpy/objects/base.h" #include #include @@ -26,7 +27,7 @@ PyVar PyArrayGetItem(VM* vm, PyVar _0, PyVar _1) { static_assert(std::is_same_v || std::is_same_v); const T& self = _CAST(T&, _0); if(is_int(_1)) { - i64 index = _1.as(); + i64 index = _1._i64; index = vm->normalized_index(index, self.size()); return self[index]; } @@ -374,7 +375,7 @@ void __init_builtins(VM* _vm) { }); _vm->bind__eq__(VM::tp_object, [](VM* vm, PyVar _0, PyVar _1) { - return VAR(_0 == _1); + return PyVar__IS_OP(&_0, &_1) ? vm->True : vm->False; }); _vm->__cached_object_new = _vm->bind_func(VM::tp_object, __new__, 1, [](VM* vm, ArgsView args) { @@ -461,7 +462,7 @@ void __init_builtins(VM* _vm) { switch(vm->_tp(args[1])) { case VM::tp_float: return VAR((i64)_CAST(f64, args[1])); case VM::tp_int: return args[1]; - case VM::tp_bool: return VAR(args[1] == vm->True ? 1 : 0); + case VM::tp_bool: return VAR(args[1]._bool ? 1 : 0); case VM::tp_str: break; default: vm->TypeError("invalid arguments for int()"); } @@ -542,7 +543,7 @@ void __init_builtins(VM* _vm) { switch(vm->_tp(args[1])) { case VM::tp_int: return VAR((f64)CAST(i64, args[1])); case VM::tp_float: return args[1]; - case VM::tp_bool: return VAR(args[1] == vm->True ? 1.0 : 0.0); + case VM::tp_bool: return VAR(args[1]._bool ? 1.0 : 0.0); case VM::tp_str: break; default: vm->TypeError("invalid arguments for float()"); } @@ -847,11 +848,11 @@ void __init_builtins(VM* _vm) { }); _vm->bind__repr__(VM::tp_list, [](VM* vm, PyVar _0) -> Str { - if(vm->_repr_recursion_set.contains(_0)) return "[...]"; + if(vm->_repr_recursion_set.contains(_0.get())) return "[...]"; List& iterable = _CAST(List&, _0); SStream ss; ss << '['; - vm->_repr_recursion_set.push_back(_0); + vm->_repr_recursion_set.push_back(_0.get()); for(int i = 0; i < iterable.size(); i++) { ss << vm->py_repr(iterable[i]); if(i != iterable.size() - 1) ss << ", "; @@ -1150,7 +1151,7 @@ void __init_builtins(VM* _vm) { return VAR(_CAST(bool, _0) != CAST(bool, _1)); }); _vm->bind__eq__(VM::tp_bool, [](VM* vm, PyVar _0, PyVar _1) { - if(is_type(_1, vm->tp_bool)) return VAR(_0 == _1); + if(is_type(_1, vm->tp_bool)) return VAR(_0._bool == _1._bool); if(is_int(_1)) return VAR(_CAST(bool, _0) == (bool)CAST(i64, _1)); return vm->NotImplemented; }); @@ -1316,12 +1317,12 @@ void __init_builtins(VM* _vm) { }); _vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyVar _0) -> Str { - if(vm->_repr_recursion_set.contains(_0)) return "{...}"; + if(vm->_repr_recursion_set.contains(_0.get())) return "{...}"; MappingProxy& self = _CAST(MappingProxy&, _0); SStream ss; ss << "mappingproxy({"; bool first = true; - vm->_repr_recursion_set.push_back(_0); + vm->_repr_recursion_set.push_back(_0.get()); for(auto [k, v]: self.attr().items()) { if(!first) ss << ", "; first = false; @@ -1472,12 +1473,12 @@ void __init_builtins(VM* _vm) { }); _vm->bind__repr__(VM::tp_dict, [](VM* vm, PyVar _0) -> Str { - if(vm->_repr_recursion_set.contains(_0)) return "{...}"; + if(vm->_repr_recursion_set.contains(_0.get())) return "{...}"; Dict& self = _CAST(Dict&, _0); SStream ss; ss << "{"; bool first = true; - vm->_repr_recursion_set.push_back(_0); + vm->_repr_recursion_set.push_back(_0.get()); self.apply([&](PyVar k, PyVar v) { if(!first) ss << ", "; first = false; @@ -1544,7 +1545,7 @@ void __init_builtins(VM* _vm) { _vm->bind(_vm->_t(VM::tp_exception), "__init__(self, msg=...)", [](VM* vm, ArgsView args) { Exception& self = _CAST(Exception&, args[0]); - if(args[1] == vm->Ellipsis) { + if(args[1].type == tp_ellipsis) { self.msg = ""; } else { self.msg = CAST(Str, args[1]); @@ -1627,7 +1628,7 @@ void VM::__post_init_builtin_types() { if(!is_type(rhs, vm->tp_bound_method)) return vm->NotImplemented; const BoundMethod& _0 = PK_OBJ_GET(BoundMethod, lhs); const BoundMethod& _1 = PK_OBJ_GET(BoundMethod, rhs); - return VAR(_0.self == _1.self && _0.func == _1.func); + return VAR(PyVar__IS_OP(&_0.self, &_1.self) && PyVar__IS_OP(&_0.func, &_1.func)); }); bind_property(_t(tp_slice), "start", [](VM* vm, ArgsView args) {