mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
more move
This commit is contained in:
parent
d21a9cffab
commit
175c571fbb
@ -21,9 +21,8 @@ constexpr inline bool is_floating_point_v = std::is_same_v<T, float> || std::is_
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr inline bool is_sso_v = is_integral_v<T> || is_floating_point_v<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>
|
template <typename T>
|
||||||
using obj_get_t = std::conditional_t<is_sso_v<T>, T, T&>;
|
using obj_get_t = T&;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr inline bool is_trivially_relocatable_v =
|
constexpr inline bool is_trivially_relocatable_v =
|
||||||
|
@ -69,7 +69,6 @@ struct CodeEmitContext{
|
|||||||
int curr_iblock = 0;
|
int curr_iblock = 0;
|
||||||
bool is_compiling_class = false;
|
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;
|
small_map<std::string_view, int> _co_consts_string_dedup_map;
|
||||||
|
|
||||||
int get_loop() const noexcept;
|
int get_loop() const noexcept;
|
||||||
|
@ -175,14 +175,14 @@ public:
|
|||||||
vector<ArgsView> s_view;
|
vector<ArgsView> s_view;
|
||||||
} __c;
|
} __c;
|
||||||
|
|
||||||
PyVar StopIteration; // a special Exception class
|
PyObject* StopIteration; // a special Exception class
|
||||||
PyObject* builtins;
|
PyObject* builtins;
|
||||||
PyObject* _main;
|
PyObject* _main;
|
||||||
|
|
||||||
// typeid -> Type
|
// typeid -> Type
|
||||||
small_map<std::type_index, Type> _cxx_typeid_map;
|
small_map<std::type_index, Type> _cxx_typeid_map;
|
||||||
// this is for repr() recursion detection (no need to mark)
|
// this is for repr() recursion detection (no need to mark)
|
||||||
vector<PyVar> _repr_recursion_set;
|
vector<PyObject*> _repr_recursion_set;
|
||||||
|
|
||||||
ImportContext __import_context;
|
ImportContext __import_context;
|
||||||
PyObject* __last_exception;
|
PyObject* __last_exception;
|
||||||
@ -550,10 +550,18 @@ PyVar py_var(VM* vm, __T&& value) {
|
|||||||
return value ? vm->True : vm->False;
|
return value ? vm->True : vm->False;
|
||||||
} else if constexpr(is_integral_v<T>) {
|
} else if constexpr(is_integral_v<T>) {
|
||||||
// int
|
// 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>) {
|
} else if constexpr(is_floating_point_v<T>) {
|
||||||
// float
|
// 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>) {
|
} else if constexpr(std::is_pointer_v<T>) {
|
||||||
return from_void_p(vm, (void*)value);
|
return from_void_p(vm, (void*)value);
|
||||||
} else {
|
} else {
|
||||||
@ -592,23 +600,22 @@ __T _py_cast__internal(VM* vm, PyVar obj) {
|
|||||||
static_assert(!std::is_reference_v<__T>);
|
static_assert(!std::is_reference_v<__T>);
|
||||||
// bool
|
// bool
|
||||||
if constexpr(with_check) {
|
if constexpr(with_check) {
|
||||||
if(obj == vm->True) return true;
|
if(obj.type != tp_bool){
|
||||||
if(obj == vm->False) return false;
|
vm->TypeError("expected 'bool', got " + _type_name(vm, vm->_tp(obj)).escape());
|
||||||
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>) {
|
} else if constexpr(is_integral_v<T>) {
|
||||||
static_assert(!std::is_reference_v<__T>);
|
static_assert(!std::is_reference_v<__T>);
|
||||||
// int
|
// int
|
||||||
if constexpr(with_check) {
|
if constexpr(with_check) {
|
||||||
if(is_int(obj)) return (T)obj.as<i64>();
|
if(!is_int(obj)) vm->TypeError("expected 'int', got " + _type_name(vm, vm->_tp(obj)).escape());
|
||||||
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>) {
|
} else if constexpr(is_floating_point_v<T>) {
|
||||||
static_assert(!std::is_reference_v<__T>);
|
static_assert(!std::is_reference_v<__T>);
|
||||||
if(is_float(obj)) return (T)obj.as<f64>();
|
if(is_float(obj)) return (T)obj._f64;
|
||||||
if(is_int(obj)) return (T)obj.as<i64>();
|
if(is_int(obj)) return (T)obj._i64;
|
||||||
vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape());
|
vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape());
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
} else if constexpr(std::is_enum_v<T>) {
|
} else if constexpr(std::is_enum_v<T>) {
|
||||||
|
@ -207,9 +207,9 @@ static_assert(is_pod_v<Vec3>);
|
|||||||
static_assert(is_pod_v<Vec4>);
|
static_assert(is_pod_v<Vec4>);
|
||||||
static_assert(is_pod_v<Mat3x3>);
|
static_assert(is_pod_v<Mat3x3>);
|
||||||
|
|
||||||
template <>
|
// template <>
|
||||||
constexpr inline bool is_sso_v<Vec2> = true;
|
// constexpr inline bool is_sso_v<Vec2> = true;
|
||||||
template <>
|
// template <>
|
||||||
constexpr inline bool is_sso_v<Vec3> = true;
|
// constexpr inline bool is_sso_v<Vec3> = true;
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
@ -19,8 +19,7 @@ typedef struct PyObject PyObject;
|
|||||||
typedef struct PyVar{
|
typedef struct PyVar{
|
||||||
pkpy_Type type;
|
pkpy_Type type;
|
||||||
bool is_ptr;
|
bool is_ptr;
|
||||||
uint8_t flags;
|
int extra;
|
||||||
int flags_ex;
|
|
||||||
union {
|
union {
|
||||||
int64_t _i64;
|
int64_t _i64;
|
||||||
double _f64;
|
double _f64;
|
||||||
@ -31,33 +30,17 @@ typedef struct PyVar{
|
|||||||
};
|
};
|
||||||
} 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");
|
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_object, tp_type;
|
||||||
extern const pkpy_Type tp_int, tp_float, tp_bool, tp_str;
|
extern const pkpy_Type tp_int, tp_float, tp_bool, tp_str;
|
||||||
extern const pkpy_Type tp_list, tp_tuple;
|
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_staticmethod, tp_classmethod;
|
||||||
extern const pkpy_Type tp_none_type, tp_not_implemented_type;
|
extern const pkpy_Type tp_none_type, tp_not_implemented_type;
|
||||||
extern const pkpy_Type tp_ellipsis;
|
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;
|
PK_INLINE bool PyVar__is_null(const PyVar* self) { return self->type == 0; }
|
||||||
extern const PyVar pkpy_NotImplemented, pkpy_Ellipsis;
|
PK_INLINE int64_t PyVar__hash(const PyVar* self) { return self->extra + self->_i64; }
|
||||||
extern const PyVar pkpy_NULL;
|
|
||||||
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
SSO types:
|
||||||
|
1. int64_t
|
||||||
|
2. double
|
||||||
|
3. bool (dummy)
|
||||||
|
4. tuple (extra + void*)
|
||||||
|
5. string (extra + void* or buf)
|
||||||
|
*/
|
@ -26,7 +26,7 @@ struct PyVar final: ::PyVar {
|
|||||||
|
|
||||||
// implict conversion
|
// implict conversion
|
||||||
PyVar(PyObject* existing){
|
PyVar(PyObject* existing){
|
||||||
PyVar__ctor2(this, (::PyObject*)existing);
|
PyVar__ctor3(this, (::PyObject*)existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We must initialize all members to allow == operator to work correctly */
|
/* 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);
|
PyVar__ctor(this, type, (::PyObject*)p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSO initialized (is_sso = true)
|
PyVar(Type type, i64 value){
|
||||||
template <typename T>
|
|
||||||
PyVar(Type type, T value){
|
|
||||||
static_assert(sizeof(T) <= 12, "SSO size exceeded");
|
|
||||||
this->type = type;
|
this->type = type;
|
||||||
this->is_ptr = false;
|
this->is_ptr = false;
|
||||||
this->flags = 0;
|
this->_i64 = value;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit operator bool () const { return (bool)type; }
|
explicit operator bool () const { return (bool)type; }
|
||||||
@ -68,10 +52,12 @@ struct PyVar final: ::PyVar {
|
|||||||
memset(this, 0, sizeof(PyVar));
|
memset(this, 0, sizeof(PyVar));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator== (const PyVar& other) const { return PyVar__equal(this, &other); }
|
bool operator==(PyObject* other){
|
||||||
bool operator!= (const PyVar& other) const { return !PyVar__equal(this, &other); }
|
return is_ptr && (PyObject*)_obj == 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;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject* get() const {
|
PyObject* get() const {
|
||||||
assert(is_ptr);
|
assert(is_ptr);
|
||||||
@ -88,11 +74,6 @@ struct PyVar final: ::PyVar {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
obj_get_t<T> obj_get();
|
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
|
// implicit convert from ::PyVar
|
||||||
PyVar(const ::PyVar& var) {
|
PyVar(const ::PyVar& var) {
|
||||||
memcpy(this, &var, sizeof(var));
|
memcpy(this, &var, sizeof(var));
|
||||||
|
@ -116,14 +116,11 @@ T to_void_p(VM*, PyVar);
|
|||||||
PyVar from_void_p(VM*, void*);
|
PyVar from_void_p(VM*, void*);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
obj_get_t<T> PyVar::obj_get() {
|
T& PyVar::obj_get() {
|
||||||
if constexpr(is_sso_v<T>) {
|
static_assert(!is_sso_v<T>, "unsupported");
|
||||||
return as<T>();
|
assert(is_ptr);
|
||||||
} else {
|
void* v = PyObject__value_ptr(_obj);
|
||||||
assert(is_ptr);
|
return *reinterpret_cast<T*>(v);
|
||||||
void* v = PyObject__value_ptr(_obj);
|
|
||||||
return *reinterpret_cast<T*>(v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PK_OBJ_GET(T, obj) ((obj).obj_get<T>())
|
#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
|
#define PY_NULL nullptr
|
||||||
extern PyVar PY_OP_CALL;
|
|
||||||
extern PyVar PY_OP_YIELD;
|
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
@ -12,9 +12,10 @@ struct NameDict;
|
|||||||
struct PyObject final: ::PyObject {
|
struct PyObject final: ::PyObject {
|
||||||
bool is_attr_valid() const noexcept { return _attr != nullptr; }
|
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{
|
NameDict& attr() const{
|
||||||
|
assert(is_attr_valid());
|
||||||
return *(NameDict*)_attr;
|
return *(NameDict*)_attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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){
|
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){
|
void pkpy_SStream__write_double(pkpy_SStream* self, double val, int precision){
|
||||||
|
@ -137,16 +137,9 @@ int CodeEmitContext::add_const_string(std::string_view key) noexcept{
|
|||||||
|
|
||||||
int CodeEmitContext::add_const(PyVar v) noexcept{
|
int CodeEmitContext::add_const(PyVar v) noexcept{
|
||||||
assert(!is_type(v, VM::tp_str));
|
assert(!is_type(v, VM::tp_str));
|
||||||
// non-string deduplication
|
co->consts.push_back(v);
|
||||||
int* val = _co_consts_nonstring_dedup_map.try_get(v);
|
int index = co->consts.size() - 1;
|
||||||
if(val) {
|
return index;
|
||||||
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{
|
int CodeEmitContext::add_func_decl(FuncDecl_ decl) noexcept{
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
#include "pocketpy/interpreter/ceval.hpp"
|
#include "pocketpy/interpreter/ceval.hpp"
|
||||||
|
#include "pocketpy/objects/base.h"
|
||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
#define PREDICT_INT_OP(op) \
|
#define PREDICT_INT_OP(op) \
|
||||||
if(is_int(_0) && is_int(_1)) { \
|
if(is_int(_0) && is_int(_1)) { \
|
||||||
TOP() = VAR(_0.as<i64>() op _1.as<i64>()); \
|
TOP() = VAR(_0._i64 op _1._i64); \
|
||||||
DISPATCH() \
|
DISPATCH() \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PREDICT_INT_DIV_OP(op) \
|
#define PREDICT_INT_DIV_OP(op) \
|
||||||
if(is_int(_0) && is_int(_1)) { \
|
if(is_int(_0) && is_int(_1)) { \
|
||||||
i64 divisor = _1.as<i64>(); \
|
i64 divisor = _1._i64; \
|
||||||
if(divisor == 0) ZeroDivisionError(); \
|
if(divisor == 0) ZeroDivisionError(); \
|
||||||
TOP() = VAR(_0.as<i64>() op divisor); \
|
TOP() = VAR(_0._i64 op divisor); \
|
||||||
DISPATCH() \
|
DISPATCH() \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ namespace pkpy {
|
|||||||
} else { \
|
} else { \
|
||||||
PyVar self; \
|
PyVar self; \
|
||||||
PyVar _2 = get_unbound_method(_0, func, &self, false); \
|
PyVar _2 = get_unbound_method(_0, func, &self, false); \
|
||||||
if(_2 != nullptr) \
|
if(_2) \
|
||||||
ret = call_method(self, _2, _1); \
|
ret = call_method(self, _2, _1); \
|
||||||
else \
|
else \
|
||||||
ret = NotImplemented; \
|
ret = NotImplemented; \
|
||||||
@ -32,7 +33,7 @@ namespace pkpy {
|
|||||||
if(is_not_implemented(ret)) { \
|
if(is_not_implemented(ret)) { \
|
||||||
PyVar self; \
|
PyVar self; \
|
||||||
PyVar _2 = get_unbound_method(_1, rfunc, &self, false); \
|
PyVar _2 = get_unbound_method(_1, rfunc, &self, false); \
|
||||||
if(_2 != nullptr) \
|
if(_2) \
|
||||||
ret = call_method(self, _2, _0); \
|
ret = call_method(self, _2, _0); \
|
||||||
else \
|
else \
|
||||||
BinaryOptError(op, _0, _1); \
|
BinaryOptError(op, _0, _1); \
|
||||||
@ -65,22 +66,26 @@ void VM::__op_unpack_sequence(uint16_t arg) {
|
|||||||
|
|
||||||
bool VM::py_lt(PyVar _0, PyVar _1) {
|
bool VM::py_lt(PyVar _0, PyVar _1) {
|
||||||
BINARY_F_COMPARE(__lt__, "<", __gt__);
|
BINARY_F_COMPARE(__lt__, "<", __gt__);
|
||||||
return ret == True;
|
assert(ret.type == tp_bool);
|
||||||
|
return ret._bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM::py_le(PyVar _0, PyVar _1) {
|
bool VM::py_le(PyVar _0, PyVar _1) {
|
||||||
BINARY_F_COMPARE(__le__, "<=", __ge__);
|
BINARY_F_COMPARE(__le__, "<=", __ge__);
|
||||||
return ret == True;
|
assert(ret.type == tp_bool);
|
||||||
|
return ret._bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM::py_gt(PyVar _0, PyVar _1) {
|
bool VM::py_gt(PyVar _0, PyVar _1) {
|
||||||
BINARY_F_COMPARE(__gt__, ">", __lt__);
|
BINARY_F_COMPARE(__gt__, ">", __lt__);
|
||||||
return ret == True;
|
assert(ret.type == tp_bool);
|
||||||
|
return ret._bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM::py_ge(PyVar _0, PyVar _1) {
|
bool VM::py_ge(PyVar _0, PyVar _1) {
|
||||||
BINARY_F_COMPARE(__ge__, ">=", __le__);
|
BINARY_F_COMPARE(__ge__, ">=", __le__);
|
||||||
return ret == True;
|
assert(ret.type == tp_bool);
|
||||||
|
return ret._bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef BINARY_F_COMPARE
|
#undef BINARY_F_COMPARE
|
||||||
@ -167,7 +172,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_PRINT_EXPR:
|
case OP_PRINT_EXPR:
|
||||||
if(TOP() != None) stdout_write(py_repr(TOP()) + "\n");
|
if(!is_none(TOP())) stdout_write(py_repr(TOP()) + "\n");
|
||||||
POP();
|
POP();
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
@ -717,13 +722,13 @@ PyVar VM::__run_top_frame() {
|
|||||||
case OP_IS_OP: {
|
case OP_IS_OP: {
|
||||||
PyVar _1 = POPX(); // rhs
|
PyVar _1 = POPX(); // rhs
|
||||||
PyVar _0 = TOP(); // lhs
|
PyVar _0 = TOP(); // lhs
|
||||||
TOP() = _0 == _1 ? True : False;
|
TOP() = PyVar__IS_OP(&_0, &_1) ? True : False;
|
||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_IS_NOT_OP: {
|
case OP_IS_NOT_OP: {
|
||||||
PyVar _1 = POPX(); // rhs
|
PyVar _1 = POPX(); // rhs
|
||||||
PyVar _0 = TOP(); // lhs
|
PyVar _0 = TOP(); // lhs
|
||||||
TOP() = _0 != _1 ? True : False;
|
TOP() = PyVar__IS_OP(&_0, &_1) ? False : True;
|
||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_CONTAINS_OP: {
|
case OP_CONTAINS_OP: {
|
||||||
@ -801,7 +806,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
PyVar _0 = vectorcall(byte.arg & 0xFF, // ARGC
|
PyVar _0 = vectorcall(byte.arg & 0xFF, // ARGC
|
||||||
(byte.arg >> 8) & 0xFF, // KWARGC
|
(byte.arg >> 8) & 0xFF, // KWARGC
|
||||||
true);
|
true);
|
||||||
if(_0 == PY_OP_CALL) {
|
if(_0.type == tp_op_call) {
|
||||||
frame = &callstack.top();
|
frame = &callstack.top();
|
||||||
goto __NEXT_FRAME;
|
goto __NEXT_FRAME;
|
||||||
}
|
}
|
||||||
@ -835,7 +840,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
0, // KWARGC
|
0, // KWARGC
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
if(_0 == PY_OP_CALL) {
|
if(_0.type == tp_op_call) {
|
||||||
frame = &callstack.top();
|
frame = &callstack.top();
|
||||||
goto __NEXT_FRAME;
|
goto __NEXT_FRAME;
|
||||||
}
|
}
|
||||||
@ -854,7 +859,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_YIELD_VALUE: return PY_OP_YIELD;
|
case OP_YIELD_VALUE: return pkpy_OP_YIELD;
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LIST_APPEND: {
|
case OP_LIST_APPEND: {
|
||||||
PyVar _0 = POPX();
|
PyVar _0 = POPX();
|
||||||
@ -926,7 +931,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
DISPATCH_JUMP_ABSOLUTE(target)
|
DISPATCH_JUMP_ABSOLUTE(target)
|
||||||
} else {
|
} else {
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
return PY_OP_YIELD;
|
return pkpy_OP_YIELD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case OP_FOR_ITER_UNPACK: {
|
case OP_FOR_ITER_UNPACK: {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "pocketpy/interpreter/iter.hpp"
|
#include "pocketpy/interpreter/iter.hpp"
|
||||||
|
#include "pocketpy/objects/base.h"
|
||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ PyVar Generator::next(VM* vm) {
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ret == PY_OP_YIELD) {
|
if(ret->type == tp_op_yield) {
|
||||||
// backup the context
|
// backup the context
|
||||||
lf = vm->callstack.popx();
|
lf = vm->callstack.popx();
|
||||||
ret = vm->s_data.popx();
|
ret = vm->s_data.popx();
|
||||||
|
@ -60,7 +60,7 @@ struct JsonSerializer {
|
|||||||
if(std::isinf(val) || std::isnan(val)) vm->ValueError("cannot jsonify 'nan' or 'inf'");
|
if(std::isinf(val) || std::isnan(val)) vm->ValueError("cannot jsonify 'nan' or 'inf'");
|
||||||
ss << val;
|
ss << val;
|
||||||
} else if(obj_t == vm->tp_bool) {
|
} 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) {
|
} else if(obj_t == vm->tp_str) {
|
||||||
ss << _CAST(Str&, obj).escape('"');
|
ss << _CAST(Str&, obj).escape('"');
|
||||||
} else if(obj_t == vm->tp_list) {
|
} 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) {
|
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);
|
const PyTypeInfo* ti = _tp_info(lhs);
|
||||||
PyVar res;
|
PyVar res;
|
||||||
if(ti->m__eq__) {
|
if(ti->m__eq__) {
|
||||||
res = ti->m__eq__(this, lhs, rhs);
|
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);
|
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);
|
ti = _tp_info(rhs);
|
||||||
if(ti->m__eq__) {
|
if(ti->m__eq__) {
|
||||||
res = ti->m__eq__(this, rhs, lhs);
|
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);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +538,8 @@ i64 VM::py_hash(PyVar obj) {
|
|||||||
has_custom_eq = true;
|
has_custom_eq = true;
|
||||||
else {
|
else {
|
||||||
f = get_unbound_method(obj, __eq__, &self, false);
|
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) {
|
if(has_custom_eq) {
|
||||||
TypeError(_S("unhashable type: ", ti->name.escape()));
|
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_not_implemented_type, new_type_object(nullptr, "NotImplementedType", tp_object, false));
|
||||||
validate(tp_ellipsis, new_type_object(nullptr, "ellipsis", 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
|
// SyntaxError and IndentationError must be created here
|
||||||
PyObject* SyntaxError = new_type_object(nullptr, "SyntaxError", tp_exception, true);
|
PyObject* SyntaxError = new_type_object(nullptr, "SyntaxError", tp_exception, true);
|
||||||
PyObject* IndentationError = new_type_object(nullptr, "IndentationError", SyntaxError->as<Type>(), 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
|
// simple or normal
|
||||||
callstack.emplace(p0, co, fn._module, callable.get(), args.begin());
|
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();
|
return __run_top_frame();
|
||||||
/*****************_py_call*****************/
|
/*****************_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 new_f = *find_name_in_mro(PK_OBJ_GET(Type, callable), __new__);
|
||||||
PyVar obj;
|
PyVar obj;
|
||||||
assert(new_f != nullptr && p0[1] == PY_NULL);
|
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__
|
// fast path for object.__new__
|
||||||
obj = vm->new_object<DummyInstance>(PK_OBJ_GET(Type, callable));
|
obj = vm->new_object<DummyInstance>(PK_OBJ_GET(Type, callable));
|
||||||
} else {
|
} else {
|
||||||
@ -1326,7 +1330,7 @@ void VM::setattr(PyVar obj, StrName name, PyVar value) {
|
|||||||
// handle descriptor
|
// handle descriptor
|
||||||
if(is_type(*cls_var, tp_property)) {
|
if(is_type(*cls_var, tp_property)) {
|
||||||
const Property& prop = _CAST(Property&, *cls_var);
|
const Property& prop = _CAST(Property&, *cls_var);
|
||||||
if(prop.setter != vm->None) {
|
if(!is_none(prop.setter)) {
|
||||||
call(prop.setter, obj, value);
|
call(prop.setter, obj, value);
|
||||||
} else {
|
} else {
|
||||||
TypeError(_S("readonly attribute: ", name.escape()));
|
TypeError(_S("readonly attribute: ", name.escape()));
|
||||||
|
@ -113,8 +113,8 @@ struct Array2d {
|
|||||||
const Tuple& xy = CAST(Tuple&, _1);
|
const Tuple& xy = CAST(Tuple&, _1);
|
||||||
|
|
||||||
if(is_int(xy[0]) && is_int(xy[1])) {
|
if(is_int(xy[0]) && is_int(xy[1])) {
|
||||||
i64 col = xy[0].as<i64>();
|
i64 col = xy[0]._i64;
|
||||||
i64 row = xy[1].as<i64>();
|
i64 row = xy[1]._i64;
|
||||||
self.check_valid(vm, col, row);
|
self.check_valid(vm, col, row);
|
||||||
return self._get(col, row);
|
return self._get(col, row);
|
||||||
}
|
}
|
||||||
@ -138,8 +138,8 @@ struct Array2d {
|
|||||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||||
const Tuple& xy = CAST(Tuple&, _1);
|
const Tuple& xy = CAST(Tuple&, _1);
|
||||||
if(is_int(xy[0]) && is_int(xy[1])) {
|
if(is_int(xy[0]) && is_int(xy[1])) {
|
||||||
i64 col = xy[0].as<i64>();
|
i64 col = xy[0]._i64;
|
||||||
i64 row = xy[1].as<i64>();
|
i64 row = xy[1]._i64;
|
||||||
self.check_valid(vm, col, row);
|
self.check_valid(vm, col, row);
|
||||||
self._set(col, row, _2);
|
self._set(col, row, _2);
|
||||||
return;
|
return;
|
||||||
|
@ -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_staticmethod = 22, tp_classmethod = 23;
|
||||||
const pkpy_Type tp_none_type = 24, tp_not_implemented_type = 25;
|
const pkpy_Type tp_none_type = 24, tp_not_implemented_type = 25;
|
||||||
const pkpy_Type tp_ellipsis = 26;
|
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};
|
PyVar pkpy_True = {.type=tp_bool, .is_ptr=false, ._bool=true};
|
||||||
const PyVar pkpy_False = {.type=tp_bool, .is_ptr=false, .flags=0, .flags_ex=0, ._bool=false};
|
PyVar pkpy_False = {.type=tp_bool, .is_ptr=false, ._bool=false};
|
||||||
const PyVar pkpy_None = {.type=tp_none_type, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
|
PyVar pkpy_None = {.type=tp_none_type, .is_ptr=false};
|
||||||
const PyVar pkpy_NotImplemented = {.type=tp_not_implemented_type, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
|
PyVar pkpy_NotImplemented = {.type=tp_not_implemented_type, .is_ptr=false};
|
||||||
const PyVar pkpy_Ellipsis = {.type=tp_ellipsis, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
|
PyVar pkpy_Ellipsis = {.type=tp_ellipsis, .is_ptr=false};
|
||||||
const PyVar pkpy_NULL = {.type=0, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
|
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};
|
||||||
|
@ -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
|
|
@ -1,10 +1,8 @@
|
|||||||
#include "pocketpy/objects/object.h"
|
#include "pocketpy/objects/object.h"
|
||||||
|
|
||||||
void PyVar__ctor2(PyVar* self, PyObject* existing){
|
void PyVar__ctor3(PyVar* self, PyObject* existing){
|
||||||
assert(existing);
|
assert(existing);
|
||||||
self->type = existing->type;
|
self->type = existing->type;
|
||||||
self->is_ptr = true;
|
self->is_ptr = true;
|
||||||
self->flags = 0;
|
|
||||||
self->flags_ex = 0;
|
|
||||||
self->_obj = existing;
|
self->_obj = existing;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "pocketpy/modules/linalg.hpp"
|
#include "pocketpy/modules/linalg.hpp"
|
||||||
#include "pocketpy/modules/random.hpp"
|
#include "pocketpy/modules/random.hpp"
|
||||||
#include "pocketpy/modules/modules.hpp"
|
#include "pocketpy/modules/modules.hpp"
|
||||||
|
#include "pocketpy/objects/base.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#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>);
|
static_assert(std::is_same_v<T, List> || std::is_same_v<T, Tuple>);
|
||||||
const T& self = _CAST(T&, _0);
|
const T& self = _CAST(T&, _0);
|
||||||
if(is_int(_1)) {
|
if(is_int(_1)) {
|
||||||
i64 index = _1.as<i64>();
|
i64 index = _1._i64;
|
||||||
index = vm->normalized_index(index, self.size());
|
index = vm->normalized_index(index, self.size());
|
||||||
return self[index];
|
return self[index];
|
||||||
}
|
}
|
||||||
@ -374,7 +375,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__eq__(VM::tp_object, [](VM* vm, PyVar _0, PyVar _1) {
|
_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) {
|
_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])) {
|
switch(vm->_tp(args[1])) {
|
||||||
case VM::tp_float: return VAR((i64)_CAST(f64, args[1]));
|
case VM::tp_float: return VAR((i64)_CAST(f64, args[1]));
|
||||||
case VM::tp_int: return 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;
|
case VM::tp_str: break;
|
||||||
default: vm->TypeError("invalid arguments for int()");
|
default: vm->TypeError("invalid arguments for int()");
|
||||||
}
|
}
|
||||||
@ -542,7 +543,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
switch(vm->_tp(args[1])) {
|
switch(vm->_tp(args[1])) {
|
||||||
case VM::tp_int: return VAR((f64)CAST(i64, args[1]));
|
case VM::tp_int: return VAR((f64)CAST(i64, args[1]));
|
||||||
case VM::tp_float: return 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;
|
case VM::tp_str: break;
|
||||||
default: vm->TypeError("invalid arguments for float()");
|
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 {
|
_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);
|
List& iterable = _CAST(List&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
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++) {
|
for(int i = 0; i < iterable.size(); i++) {
|
||||||
ss << vm->py_repr(iterable[i]);
|
ss << vm->py_repr(iterable[i]);
|
||||||
if(i != iterable.size() - 1) ss << ", ";
|
if(i != iterable.size() - 1) ss << ", ";
|
||||||
@ -1150,7 +1151,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
return VAR(_CAST(bool, _0) != CAST(bool, _1));
|
return VAR(_CAST(bool, _0) != CAST(bool, _1));
|
||||||
});
|
});
|
||||||
_vm->bind__eq__(VM::tp_bool, [](VM* vm, PyVar _0, PyVar _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));
|
if(is_int(_1)) return VAR(_CAST(bool, _0) == (bool)CAST(i64, _1));
|
||||||
return vm->NotImplemented;
|
return vm->NotImplemented;
|
||||||
});
|
});
|
||||||
@ -1316,12 +1317,12 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyVar _0) -> Str {
|
_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);
|
MappingProxy& self = _CAST(MappingProxy&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "mappingproxy({";
|
ss << "mappingproxy({";
|
||||||
bool first = true;
|
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()) {
|
for(auto [k, v]: self.attr().items()) {
|
||||||
if(!first) ss << ", ";
|
if(!first) ss << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
@ -1472,12 +1473,12 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_dict, [](VM* vm, PyVar _0) -> Str {
|
_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);
|
Dict& self = _CAST(Dict&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "{";
|
ss << "{";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
vm->_repr_recursion_set.push_back(_0);
|
vm->_repr_recursion_set.push_back(_0.get());
|
||||||
self.apply([&](PyVar k, PyVar v) {
|
self.apply([&](PyVar k, PyVar v) {
|
||||||
if(!first) ss << ", ";
|
if(!first) ss << ", ";
|
||||||
first = false;
|
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) {
|
_vm->bind(_vm->_t(VM::tp_exception), "__init__(self, msg=...)", [](VM* vm, ArgsView args) {
|
||||||
Exception& self = _CAST(Exception&, args[0]);
|
Exception& self = _CAST(Exception&, args[0]);
|
||||||
if(args[1] == vm->Ellipsis) {
|
if(args[1].type == tp_ellipsis) {
|
||||||
self.msg = "";
|
self.msg = "";
|
||||||
} else {
|
} else {
|
||||||
self.msg = CAST(Str, args[1]);
|
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;
|
if(!is_type(rhs, vm->tp_bound_method)) return vm->NotImplemented;
|
||||||
const BoundMethod& _0 = PK_OBJ_GET(BoundMethod, lhs);
|
const BoundMethod& _0 = PK_OBJ_GET(BoundMethod, lhs);
|
||||||
const BoundMethod& _1 = PK_OBJ_GET(BoundMethod, rhs);
|
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) {
|
bind_property(_t(tp_slice), "start", [](VM* vm, ArgsView args) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user