more move

This commit is contained in:
blueloveTH 2024-06-16 19:56:33 +08:00
parent d21a9cffab
commit 175c571fbb
18 changed files with 154 additions and 160 deletions

View File

@ -21,9 +21,8 @@ constexpr inline bool is_floating_point_v = std::is_same_v<T, float> || std::is_
template <typename T>
constexpr inline bool is_sso_v = is_integral_v<T> || is_floating_point_v<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&>;
using obj_get_t = T&;
template <typename T>
constexpr inline bool is_trivially_relocatable_v =

View File

@ -69,7 +69,6 @@ struct CodeEmitContext{
int curr_iblock = 0;
bool is_compiling_class = false;
small_map<PyVar, int> _co_consts_nonstring_dedup_map;
small_map<std::string_view, int> _co_consts_string_dedup_map;
int get_loop() const noexcept;

View File

@ -175,14 +175,14 @@ public:
vector<ArgsView> s_view;
} __c;
PyVar StopIteration; // a special Exception class
PyObject* StopIteration; // a special Exception class
PyObject* builtins;
PyObject* _main;
// typeid -> Type
small_map<std::type_index, Type> _cxx_typeid_map;
// this is for repr() recursion detection (no need to mark)
vector<PyVar> _repr_recursion_set;
vector<PyObject*> _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<T>) {
// int
return PyVar(VM::tp_int, static_cast<i64>(value));
::PyVar retval;
retval.type = tp_int;
retval.is_ptr = false;
retval._i64 = (i64)value;
return retval;
} else if constexpr(is_floating_point_v<T>) {
// float
return PyVar(VM::tp_float, static_cast<f64>(value));
::PyVar retval;
retval.type = tp_float;
retval.is_ptr = false;
retval._f64 = (f64)value;
return retval;
} else if constexpr(std::is_pointer_v<T>) {
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;
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<T>) {
static_assert(!std::is_reference_v<__T>);
// int
if constexpr(with_check) {
if(is_int(obj)) return (T)obj.as<i64>();
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<i64>();
return (T)obj._i64;
} else if constexpr(is_floating_point_v<T>) {
static_assert(!std::is_reference_v<__T>);
if(is_float(obj)) return (T)obj.as<f64>();
if(is_int(obj)) return (T)obj.as<i64>();
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<T>) {

View File

@ -207,9 +207,9 @@ static_assert(is_pod_v<Vec3>);
static_assert(is_pod_v<Vec4>);
static_assert(is_pod_v<Mat3x3>);
template <>
constexpr inline bool is_sso_v<Vec2> = true;
template <>
constexpr inline bool is_sso_v<Vec3> = true;
// template <>
// constexpr inline bool is_sso_v<Vec2> = true;
// template <>
// constexpr inline bool is_sso_v<Vec3> = true;
} // namespace pkpy

View File

@ -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
/*
SSO types:
1. int64_t
2. double
3. bool (dummy)
4. tuple (extra + void*)
5. string (extra + void* or buf)
*/

View File

@ -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 <typename T>
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<T>() = value;
}
template <typename T>
T& as() {
static_assert(!std::is_reference_v<T>);
if constexpr(sizeof(T) <= 8) {
return reinterpret_cast<T&>(_i64);
} else {
return reinterpret_cast<T&>(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 <typename T>
obj_get_t<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));

View File

@ -116,15 +116,12 @@ T to_void_p(VM*, PyVar);
PyVar from_void_p(VM*, void*);
template <typename T>
obj_get_t<T> PyVar::obj_get() {
if constexpr(is_sso_v<T>) {
return as<T>();
} else {
T& PyVar::obj_get() {
static_assert(!is_sso_v<T>, "unsupported");
assert(is_ptr);
void* v = PyObject__value_ptr(_obj);
return *reinterpret_cast<T*>(v);
}
}
#define PK_OBJ_GET(T, obj) ((obj).obj_get<T>())
@ -140,7 +137,5 @@ obj_get_t<T> PyVar::obj_get() {
/*****************************************************************/
#define PY_NULL nullptr
extern PyVar PY_OP_CALL;
extern PyVar PY_OP_YIELD;
} // namespace pkpy

View File

@ -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;
}

View File

@ -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){

View File

@ -137,17 +137,10 @@ 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;
}
}
int CodeEmitContext::add_func_decl(FuncDecl_ decl) noexcept{
co->func_decls.push_back(decl);

View File

@ -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<i64>() op _1.as<i64>()); \
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>(); \
i64 divisor = _1._i64; \
if(divisor == 0) ZeroDivisionError(); \
TOP() = VAR(_0.as<i64>() 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: {

View File

@ -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();

View File

@ -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<i64>() == rhs.as<i64>();
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<Type>(), 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<DummyInstance>(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()));

View File

@ -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>();
i64 row = xy[1].as<i64>();
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>();
i64 row = xy[1].as<i64>();
i64 col = xy[0]._i64;
i64 row = xy[1]._i64;
self.check_valid(vm, col, row);
self._set(col, row, _2);
return;

View File

@ -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};
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};

View File

@ -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

View File

@ -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;
}

View File

@ -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 <iostream>
#include <algorithm>
@ -26,7 +27,7 @@ PyVar PyArrayGetItem(VM* vm, PyVar _0, PyVar _1) {
static_assert(std::is_same_v<T, List> || std::is_same_v<T, Tuple>);
const T& self = _CAST(T&, _0);
if(is_int(_1)) {
i64 index = _1.as<i64>();
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) {