mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-11-04 02:30:17 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "8de566f875733618be67b67c63975163b80f84e4" and "9d9674d1718d3a9856a34771826256cd07b00430" have entirely different histories.
		
	
	
		
			8de566f875
			...
			9d9674d171
		
	
		
@ -63,7 +63,7 @@ void pk_VM__dtor(pk_VM* self);
 | 
			
		||||
void pk_VM__push_frame(pk_VM* self, Frame* frame);
 | 
			
		||||
void pk_VM__pop_frame(pk_VM* self);
 | 
			
		||||
 | 
			
		||||
bool pk__parse_int_slice(py_Ref slice, int length, int* start, int* stop, int* step);
 | 
			
		||||
bool pk__parse_int_slice(const py_Ref slice, int length, int* start, int* stop, int* step);
 | 
			
		||||
bool pk__normalize_index(int* index, int length);
 | 
			
		||||
 | 
			
		||||
void pk_list__mark(void* ud, void (*marker)(py_TValue*));
 | 
			
		||||
@ -90,9 +90,8 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
 | 
			
		||||
const char* pk_opname(Opcode op);
 | 
			
		||||
 | 
			
		||||
py_TValue* pk_arrayview(py_Ref self, int* length);
 | 
			
		||||
int pk_arrayequal(py_TValue* lhs, int lhs_length, py_TValue* rhs, int rhs_length);
 | 
			
		||||
int pk_arrayeq(py_TValue* lhs, int lhs_length, py_TValue* rhs, int rhs_length);
 | 
			
		||||
bool pk_arrayiter(py_Ref val);
 | 
			
		||||
bool pk_arraycontains(py_Ref self, py_Ref val);
 | 
			
		||||
 | 
			
		||||
/// Assumes [a, b] are on the stack, performs a binary op.
 | 
			
		||||
/// The result is stored in `self->last_retval`.
 | 
			
		||||
 | 
			
		||||
@ -105,17 +105,17 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, vo
 | 
			
		||||
/// @param udsize size of your userdata. You can use `py_touserdata()` to get the pointer to it.
 | 
			
		||||
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
 | 
			
		||||
/************* Type Cast *************/
 | 
			
		||||
py_i64 py_toint(py_Ref);
 | 
			
		||||
py_f64 py_tofloat(py_Ref);
 | 
			
		||||
bool py_castfloat(py_Ref, py_f64* out);
 | 
			
		||||
bool py_tobool(py_Ref);
 | 
			
		||||
py_Type py_totype(py_Ref);
 | 
			
		||||
const char* py_tostr(py_Ref);
 | 
			
		||||
const char* py_tostrn(py_Ref, int* size);
 | 
			
		||||
c11_sv py_tosv(py_Ref);
 | 
			
		||||
unsigned char* py_tobytes(py_Ref, int* size);
 | 
			
		||||
py_i64 py_toint(const py_Ref);
 | 
			
		||||
py_f64 py_tofloat(const py_Ref);
 | 
			
		||||
bool py_castfloat(const py_Ref, py_f64* out);
 | 
			
		||||
bool py_tobool(const py_Ref);
 | 
			
		||||
py_Type py_totype(const py_Ref);
 | 
			
		||||
const char* py_tostr(const py_Ref);
 | 
			
		||||
const char* py_tostrn(const py_Ref, int* size);
 | 
			
		||||
c11_sv py_tosv(const py_Ref);
 | 
			
		||||
unsigned char* py_tobytes(const py_Ref, int* size);
 | 
			
		||||
 | 
			
		||||
void* py_touserdata(py_Ref);
 | 
			
		||||
void* py_touserdata(const py_Ref);
 | 
			
		||||
 | 
			
		||||
#define py_isint(self) py_istype(self, tp_int)
 | 
			
		||||
#define py_isfloat(self) py_istype(self, tp_float)
 | 
			
		||||
@ -125,8 +125,8 @@ void* py_touserdata(py_Ref);
 | 
			
		||||
#define py_istuple(self) py_istype(self, tp_tuple)
 | 
			
		||||
#define py_isdict(self) py_istype(self, tp_dict)
 | 
			
		||||
 | 
			
		||||
bool py_istype(py_Ref, py_Type);
 | 
			
		||||
bool py_isinstance(py_Ref obj, py_Type type);
 | 
			
		||||
bool py_istype(const py_Ref, py_Type);
 | 
			
		||||
bool py_isinstance(const py_Ref obj, py_Type type);
 | 
			
		||||
bool py_issubclass(py_Type derived, py_Type base);
 | 
			
		||||
 | 
			
		||||
extern py_GlobalRef py_True;
 | 
			
		||||
@ -149,7 +149,6 @@ py_GlobalRef py_tpmagic(py_Type type, py_Name name);
 | 
			
		||||
 | 
			
		||||
// new style decl-based bindings
 | 
			
		||||
void py_bind(py_Ref obj, const char* sig, py_CFunction f);
 | 
			
		||||
 | 
			
		||||
py_ObjectRef py_bind2(py_Ref obj,
 | 
			
		||||
                      const char* sig,
 | 
			
		||||
                      py_CFunction f,
 | 
			
		||||
@ -157,6 +156,20 @@ py_ObjectRef py_bind2(py_Ref obj,
 | 
			
		||||
                      const char* docstring,
 | 
			
		||||
                      int slots);
 | 
			
		||||
 | 
			
		||||
py_ObjectRef py_bind3(py_Ref obj,
 | 
			
		||||
                      py_CFunction f,
 | 
			
		||||
                      c11_sv name,
 | 
			
		||||
                      c11_sv* args,
 | 
			
		||||
                      int argc,
 | 
			
		||||
                      c11_sv starred_arg,
 | 
			
		||||
                      c11_sv* kwargs,
 | 
			
		||||
                      int kwargc,
 | 
			
		||||
                      py_Ref kwdefaults,  // a tuple contains default values
 | 
			
		||||
                      c11_sv starred_kwarg,
 | 
			
		||||
                      enum BindType bt,
 | 
			
		||||
                      const char* docstring,
 | 
			
		||||
                      int slots);
 | 
			
		||||
 | 
			
		||||
// old style argc-based bindings
 | 
			
		||||
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
 | 
			
		||||
void py_bindmethod2(py_Type type, const char* name, py_CFunction f, enum BindType bt);
 | 
			
		||||
@ -169,35 +182,35 @@ py_GlobalRef py_reg(int i);
 | 
			
		||||
/// Get the reference of the object's `__dict__`.
 | 
			
		||||
/// The object must have a `__dict__`.
 | 
			
		||||
/// Returns a reference to the value or NULL if not found.
 | 
			
		||||
py_ObjectRef py_getdict(py_Ref self, py_Name name);
 | 
			
		||||
void py_setdict(py_Ref self, py_Name name, py_Ref val);
 | 
			
		||||
py_ObjectRef py_getdict(const py_Ref self, py_Name name);
 | 
			
		||||
void py_setdict(py_Ref self, py_Name name, const py_Ref val);
 | 
			
		||||
bool py_deldict(py_Ref self, py_Name name);
 | 
			
		||||
 | 
			
		||||
/// Get the reference of the i-th slot of the object.
 | 
			
		||||
/// The object must have slots and `i` must be in range.
 | 
			
		||||
py_ObjectRef py_getslot(py_Ref self, int i);
 | 
			
		||||
void py_setslot(py_Ref self, int i, py_Ref val);
 | 
			
		||||
py_ObjectRef py_getslot(const py_Ref self, int i);
 | 
			
		||||
void py_setslot(py_Ref self, int i, const py_Ref val);
 | 
			
		||||
 | 
			
		||||
py_TmpRef py_getupvalue(py_StackRef argv);
 | 
			
		||||
void py_setupvalue(py_StackRef argv, py_Ref val);
 | 
			
		||||
void py_setupvalue(py_StackRef argv, const py_Ref val);
 | 
			
		||||
 | 
			
		||||
/// Gets the attribute of the object.
 | 
			
		||||
bool py_getattr(py_Ref self, py_Name name);
 | 
			
		||||
/// Sets the attribute of the object.
 | 
			
		||||
bool py_setattr(py_Ref self, py_Name name, py_Ref val);
 | 
			
		||||
bool py_setattr(py_Ref self, py_Name name, const py_Ref val);
 | 
			
		||||
/// Deletes the attribute of the object.
 | 
			
		||||
bool py_delattr(py_Ref self, py_Name name);
 | 
			
		||||
/// Gets the unbound method of the object.
 | 
			
		||||
bool py_getunboundmethod(py_Ref self, py_Name name, py_Ref out, py_Ref out_self);
 | 
			
		||||
 | 
			
		||||
bool py_getitem(py_Ref self, py_Ref key);
 | 
			
		||||
bool py_setitem(py_Ref self, py_Ref key, py_Ref val);
 | 
			
		||||
bool py_delitem(py_Ref self, py_Ref key);
 | 
			
		||||
bool py_getitem(const py_Ref self, const py_Ref key);
 | 
			
		||||
bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val);
 | 
			
		||||
bool py_delitem(py_Ref self, const py_Ref key);
 | 
			
		||||
 | 
			
		||||
/// Perform a binary operation on the stack.
 | 
			
		||||
/// It assumes `lhs` and `rhs` are already pushed to the stack.
 | 
			
		||||
/// The result will be set to `py_retval()`.
 | 
			
		||||
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop);
 | 
			
		||||
bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop);
 | 
			
		||||
 | 
			
		||||
#define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
 | 
			
		||||
#define py_binarysub(lhs, rhs) py_binaryop(lhs, rhs, __sub__, __rsub__)
 | 
			
		||||
@ -215,14 +228,14 @@ bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop);
 | 
			
		||||
#define py_binarymatmul(lhs, rhs) py_binaryop(lhs, rhs, __matmul__, 0)
 | 
			
		||||
 | 
			
		||||
/// Equivalent to `*dst = *src`.
 | 
			
		||||
void py_assign(py_Ref dst, py_Ref src);
 | 
			
		||||
void py_assign(py_Ref dst, const py_Ref src);
 | 
			
		||||
 | 
			
		||||
/************* Stack Operations *************/
 | 
			
		||||
/// Return a reference to the i-th object from the top of the stack.
 | 
			
		||||
/// i should be negative, e.g. (-1) means TOS.
 | 
			
		||||
py_StackRef py_peek(int i);
 | 
			
		||||
/// Push the object to the stack.
 | 
			
		||||
void py_push(py_Ref src);
 | 
			
		||||
void py_push(const py_Ref src);
 | 
			
		||||
/// Push a nil object to the stack.
 | 
			
		||||
void py_pushnil();
 | 
			
		||||
/// Pop an object from the stack.
 | 
			
		||||
@ -232,6 +245,12 @@ void py_shrink(int n);
 | 
			
		||||
/// Get a temporary variable from the stack and returns the reference to it.
 | 
			
		||||
py_StackRef py_pushtmp();
 | 
			
		||||
 | 
			
		||||
#define py_gettop() py_peek(-1)
 | 
			
		||||
#define py_getsecond() py_peek(-2)
 | 
			
		||||
#define py_settop(v) py_assign(py_peek(-1), v)
 | 
			
		||||
#define py_setsecond(v) py_assign(py_peek(-2), v)
 | 
			
		||||
#define py_duptop() py_push(py_peek(-1))
 | 
			
		||||
#define py_dupsecond() py_push(py_peek(-2))
 | 
			
		||||
/************* Modules *************/
 | 
			
		||||
py_TmpRef py_newmodule(const char* name, const char* package);
 | 
			
		||||
py_TmpRef py_getmodule(const char* name);
 | 
			
		||||
@ -267,28 +286,25 @@ bool KeyError(py_Ref key);
 | 
			
		||||
/// Equivalent to `bool(val)`.
 | 
			
		||||
/// Returns 1 if `val` is truthy, otherwise 0.
 | 
			
		||||
/// Returns -1 if an error occurred.
 | 
			
		||||
int py_bool(py_Ref val);
 | 
			
		||||
int py_bool(const py_Ref val);
 | 
			
		||||
 | 
			
		||||
#define py_eq(lhs, rhs) py_binaryop(lhs, rhs, __eq__, __eq__)
 | 
			
		||||
#define py_ne(lhs, rhs) py_binaryop(lhs, rhs, __ne__, __ne__)
 | 
			
		||||
#define py_lt(lhs, rhs) py_binaryop(lhs, rhs, __lt__, __gt__)
 | 
			
		||||
#define py_le(lhs, rhs) py_binaryop(lhs, rhs, __le__, __ge__)
 | 
			
		||||
#define py_gt(lhs, rhs) py_binaryop(lhs, rhs, __gt__, __lt__)
 | 
			
		||||
#define py_ge(lhs, rhs) py_binaryop(lhs, rhs, __ge__, __le__)
 | 
			
		||||
int py_eq(const py_Ref, const py_Ref);
 | 
			
		||||
int py_ne(const py_Ref, const py_Ref);
 | 
			
		||||
int py_le(const py_Ref, const py_Ref);
 | 
			
		||||
int py_lt(const py_Ref, const py_Ref);
 | 
			
		||||
int py_ge(const py_Ref, const py_Ref);
 | 
			
		||||
int py_gt(const py_Ref, const py_Ref);
 | 
			
		||||
 | 
			
		||||
int py_equal(py_Ref lhs, py_Ref rhs);
 | 
			
		||||
int py_less(py_Ref lhs, py_Ref rhs);
 | 
			
		||||
 | 
			
		||||
bool py_hash(py_Ref, py_i64* out);
 | 
			
		||||
bool py_hash(const py_Ref, py_i64* out);
 | 
			
		||||
 | 
			
		||||
/// Get the iterator of the object.
 | 
			
		||||
bool py_iter(py_Ref);
 | 
			
		||||
bool py_iter(const py_Ref);
 | 
			
		||||
/// Get the next element from the iterator.
 | 
			
		||||
/// 1: success, 0: StopIteration, -1: error
 | 
			
		||||
int py_next(py_Ref);
 | 
			
		||||
int py_next(const py_Ref);
 | 
			
		||||
 | 
			
		||||
/// Python equivalent to `lhs is rhs`.
 | 
			
		||||
bool py_isidentical(py_Ref, py_Ref);
 | 
			
		||||
bool py_isidentical(const py_Ref, const py_Ref);
 | 
			
		||||
 | 
			
		||||
/// A stack operation that calls a function.
 | 
			
		||||
/// It assumes `argc + kwargc` arguments are already pushed to the stack.
 | 
			
		||||
@ -325,28 +341,30 @@ py_GlobalRef py_retval();
 | 
			
		||||
/* tuple */
 | 
			
		||||
 | 
			
		||||
// unchecked functions, if self is not a tuple, the behavior is undefined
 | 
			
		||||
py_ObjectRef py_tuple__data(py_Ref self);
 | 
			
		||||
py_ObjectRef py_tuple__getitem(py_Ref self, int i);
 | 
			
		||||
void py_tuple__setitem(py_Ref self, int i, py_Ref val);
 | 
			
		||||
int py_tuple__len(py_Ref self);
 | 
			
		||||
py_ObjectRef py_tuple__data(const py_Ref self);
 | 
			
		||||
py_ObjectRef py_tuple__getitem(const py_Ref self, int i);
 | 
			
		||||
void py_tuple__setitem(py_Ref self, int i, const py_Ref val);
 | 
			
		||||
int py_tuple__len(const py_Ref self);
 | 
			
		||||
 | 
			
		||||
// unchecked functions, if self is not a list, the behavior is undefined
 | 
			
		||||
py_TmpRef py_list__data(py_Ref self);
 | 
			
		||||
py_TmpRef py_list__getitem(py_Ref self, int i);
 | 
			
		||||
void py_list__setitem(py_Ref self, int i, py_Ref val);
 | 
			
		||||
py_TmpRef py_list__data(const py_Ref self);
 | 
			
		||||
py_TmpRef py_list__getitem(const py_Ref self, int i);
 | 
			
		||||
void py_list__setitem(py_Ref self, int i, const py_Ref val);
 | 
			
		||||
void py_list__delitem(py_Ref self, int i);
 | 
			
		||||
int py_list__len(py_Ref self);
 | 
			
		||||
void py_list__append(py_Ref self, py_Ref val);
 | 
			
		||||
int py_list__len(const py_Ref self);
 | 
			
		||||
void py_list__append(py_Ref self, const py_Ref val);
 | 
			
		||||
void py_list__clear(py_Ref self);
 | 
			
		||||
void py_list__insert(py_Ref self, int i, py_Ref val);
 | 
			
		||||
void py_list__insert(py_Ref self, int i, const py_Ref val);
 | 
			
		||||
void py_list__reverse(py_Ref self);
 | 
			
		||||
 | 
			
		||||
// unchecked functions, if self is not a dict, the behavior is undefined
 | 
			
		||||
py_TmpRef py_dict__getitem(py_Ref self, py_Ref key);
 | 
			
		||||
void py_dict__setitem(py_Ref self, py_Ref key, py_Ref val);
 | 
			
		||||
bool py_dict__contains(py_Ref self, py_Ref key);
 | 
			
		||||
int py_dict__len(py_Ref self);
 | 
			
		||||
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx);
 | 
			
		||||
py_TmpRef py_dict__getitem(const py_Ref self, const py_Ref key);
 | 
			
		||||
void py_dict__setitem(py_Ref self, const py_Ref key, const py_Ref val);
 | 
			
		||||
bool py_dict__contains(const py_Ref self, const py_Ref key);
 | 
			
		||||
int py_dict__len(const py_Ref self);
 | 
			
		||||
bool py_dict__apply(const py_Ref self,
 | 
			
		||||
                    bool (*f)(const py_Ref key, const py_Ref val, void* ctx),
 | 
			
		||||
                    void* ctx);
 | 
			
		||||
 | 
			
		||||
/// Search the magic method from the given type to the base type.
 | 
			
		||||
/// Return the reference or NULL if not found.
 | 
			
		||||
@ -366,10 +384,7 @@ const char* py_tpname(py_Type type);
 | 
			
		||||
bool py_tpcall(py_Type type, int argc, py_Ref argv);
 | 
			
		||||
 | 
			
		||||
/// Check if the object is an instance of the given type.
 | 
			
		||||
bool py_checktype(py_Ref self, py_Type type);
 | 
			
		||||
 | 
			
		||||
/// Get the type of the object.
 | 
			
		||||
py_Type py_typeof(py_Ref self);
 | 
			
		||||
bool py_checktype(const py_Ref self, py_Type type);
 | 
			
		||||
 | 
			
		||||
#define py_checkint(self) py_checktype(self, tp_int)
 | 
			
		||||
#define py_checkfloat(self) py_checktype(self, tp_float)
 | 
			
		||||
 | 
			
		||||
@ -60,7 +60,7 @@ static bool format_object(py_Ref obj, c11_sv spec);
 | 
			
		||||
        }                                                                                          \
 | 
			
		||||
    } while(0)
 | 
			
		||||
 | 
			
		||||
static bool unpack_dict_to_buffer(py_Ref key, py_Ref val, void* ctx) {
 | 
			
		||||
static bool unpack_dict_to_buffer(const py_Ref key, const py_Ref val, void* ctx) {
 | 
			
		||||
    py_TValue** p = ctx;
 | 
			
		||||
    if(py_isstr(key)) {
 | 
			
		||||
        py_Name name = py_namev(py_tosv(key));
 | 
			
		||||
@ -553,7 +553,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
 | 
			
		||||
                    if(byte.arg) py_newbool(TOP(), !res);
 | 
			
		||||
                    DISPATCH();
 | 
			
		||||
                }
 | 
			
		||||
                TypeError("'%t' type does not support '__contains__'", SECOND()->type);
 | 
			
		||||
                // TODO: fallback to __iter__?
 | 
			
		||||
                TypeError("argument of type '%t' is not iterable", SECOND()->type);
 | 
			
		||||
                goto __ERROR;
 | 
			
		||||
            }
 | 
			
		||||
                /*****************************************/
 | 
			
		||||
@ -921,7 +922,7 @@ bool pk_stack_binaryop(pk_VM* self, py_Name op, py_Name rop) {
 | 
			
		||||
    return py_exception("TypeError", "unsupported operand type(s) for '%n'", op);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
 | 
			
		||||
bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) {
 | 
			
		||||
    pk_VM* self = pk_current_vm;
 | 
			
		||||
    PUSH(lhs);
 | 
			
		||||
    PUSH(rhs);
 | 
			
		||||
 | 
			
		||||
@ -200,7 +200,7 @@ static void _clip_int(int* value, int min, int max) {
 | 
			
		||||
    if(*value > max) *value = max;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool pk__parse_int_slice(py_Ref slice, int length, int* start, int* stop, int* step) {
 | 
			
		||||
bool pk__parse_int_slice(const py_Ref slice, int length, int* start, int* stop, int* step) {
 | 
			
		||||
    py_Ref s_start = py_getslot(slice, 0);
 | 
			
		||||
    py_Ref s_stop = py_getslot(slice, 1);
 | 
			
		||||
    py_Ref s_step = py_getslot(slice, 2);
 | 
			
		||||
 | 
			
		||||
@ -5,17 +5,17 @@
 | 
			
		||||
#include "pocketpy/objects/object.h"
 | 
			
		||||
#include "pocketpy/interpreter/vm.h"
 | 
			
		||||
 | 
			
		||||
int64_t py_toint(py_Ref self) {
 | 
			
		||||
int64_t py_toint(const py_Ref self) {
 | 
			
		||||
    assert(self->type == tp_int);
 | 
			
		||||
    return self->_i64;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double py_tofloat(py_Ref self) {
 | 
			
		||||
double py_tofloat(const py_Ref self) {
 | 
			
		||||
    assert(self->type == tp_float);
 | 
			
		||||
    return self->_f64;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_castfloat(py_Ref self, double* out) {
 | 
			
		||||
bool py_castfloat(const py_Ref self, double* out) {
 | 
			
		||||
    switch(self->type) {
 | 
			
		||||
        case tp_int: *out = (double)self->_i64; return true;
 | 
			
		||||
        case tp_float: *out = self->_f64; return true;
 | 
			
		||||
@ -23,27 +23,27 @@ bool py_castfloat(py_Ref self, double* out) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_tobool(py_Ref self) {
 | 
			
		||||
bool py_tobool(const py_Ref self) {
 | 
			
		||||
    assert(self->type == tp_bool);
 | 
			
		||||
    return self->_bool;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Type py_totype(py_Ref self) {
 | 
			
		||||
py_Type py_totype(const py_Ref self) {
 | 
			
		||||
    assert(self->type == tp_type);
 | 
			
		||||
    py_Type* ud = py_touserdata(self);
 | 
			
		||||
    return *ud;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* py_touserdata(py_Ref self) {
 | 
			
		||||
void* py_touserdata(const py_Ref self) {
 | 
			
		||||
    assert(self && self->is_ptr);
 | 
			
		||||
    return PyObject__userdata(self->_obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_istype(py_Ref self, py_Type type) { return self->type == type; }
 | 
			
		||||
bool py_istype(const py_Ref self, py_Type type) { return self->type == type; }
 | 
			
		||||
 | 
			
		||||
bool py_checktype(py_Ref self, py_Type type) {
 | 
			
		||||
    if(self->type == type) return true;
 | 
			
		||||
    return TypeError("expected %t, got %t", type, self->type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Type py_typeof(py_Ref self) { return self->type; }
 | 
			
		||||
bool py_checktype(const py_Ref self, py_Type type) {
 | 
			
		||||
    if(self->type != type) {
 | 
			
		||||
        return TypeError("expected %t, got %t", type, self->type);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
@ -23,10 +23,10 @@ py_TValue* pk_arrayview(py_Ref self, int* length) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pk_arrayequal(py_TValue* lhs, int lhs_length, py_TValue* rhs, int rhs_length) {
 | 
			
		||||
int pk_arrayeq(py_TValue* lhs, int lhs_length, py_TValue* rhs, int rhs_length) {
 | 
			
		||||
    if(lhs_length != rhs_length) return false;
 | 
			
		||||
    for(int i = 0; i < lhs_length; i++) {
 | 
			
		||||
        int res = py_equal(lhs + i, rhs + i);
 | 
			
		||||
        int res = py_eq(lhs + i, rhs + i);
 | 
			
		||||
        if(res == -1) return -1;
 | 
			
		||||
        if(!res) return false;
 | 
			
		||||
    }
 | 
			
		||||
@ -45,22 +45,6 @@ bool pk_arrayiter(py_Ref val) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool pk_arraycontains(py_Ref self, py_Ref val) {
 | 
			
		||||
    int length;
 | 
			
		||||
    py_TValue* p = pk_arrayview(self, &length);
 | 
			
		||||
    if(!p) return TypeError("expected list or tuple, got %t", self->type);
 | 
			
		||||
    for(int i = 0; i < length; i++) {
 | 
			
		||||
        int res = py_equal(p + i, val);
 | 
			
		||||
        if(res == -1) return false;
 | 
			
		||||
        if(res) {
 | 
			
		||||
            py_newbool(py_retval(), true);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    py_newbool(py_retval(), false);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool _py_array_iterator__iter__(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(1);
 | 
			
		||||
    *py_retval() = *argv;
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,7 @@ static bool Dict__try_get(Dict* self, py_TValue* key, DictEntry** out) {
 | 
			
		||||
        int idx2 = self->indices[idx]._[i];
 | 
			
		||||
        if(idx2 == -1) continue;
 | 
			
		||||
        DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
 | 
			
		||||
        int res = py_equal(&entry->key, key);
 | 
			
		||||
        int res = py_eq(&entry->key, key);
 | 
			
		||||
        if(res == 1) {
 | 
			
		||||
            *out = entry;
 | 
			
		||||
            return true;
 | 
			
		||||
@ -150,7 +150,7 @@ static bool Dict__set(Dict* self, py_TValue* key, py_TValue* val) {
 | 
			
		||||
        }
 | 
			
		||||
        // update existing entry
 | 
			
		||||
        DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
 | 
			
		||||
        int res = py_equal(&entry->key, key);
 | 
			
		||||
        int res = py_eq(&entry->key, key);
 | 
			
		||||
        if(res == 1) {
 | 
			
		||||
            entry->val = *val;
 | 
			
		||||
            return true;
 | 
			
		||||
@ -174,7 +174,7 @@ static bool Dict__pop(Dict* self, py_Ref key) {
 | 
			
		||||
        int idx2 = self->indices[idx]._[i];
 | 
			
		||||
        if(idx2 == -1) continue;
 | 
			
		||||
        DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
 | 
			
		||||
        int res = py_equal(&entry->key, key);
 | 
			
		||||
        int res = py_eq(&entry->key, key);
 | 
			
		||||
        if(res == 1) {
 | 
			
		||||
            *py_retval() = entry->val;
 | 
			
		||||
            py_newnil(&entry->key);
 | 
			
		||||
@ -318,7 +318,7 @@ static bool _py_dict__eq__(int argc, py_Ref argv) {
 | 
			
		||||
            py_newbool(py_retval(), false);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        int res = py_equal(&entry->val, &other_entry->val);
 | 
			
		||||
        int res = py_eq(&entry->val, &other_entry->val);
 | 
			
		||||
        if(res == -1) return false;
 | 
			
		||||
        if(!res) {
 | 
			
		||||
            py_newbool(py_retval(), false);
 | 
			
		||||
@ -491,7 +491,7 @@ void py_newdict(py_Ref out) {
 | 
			
		||||
    Dict__ctor(ud, 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Ref py_dict__getitem(py_Ref self, py_Ref key) {
 | 
			
		||||
py_Ref py_dict__getitem(const py_Ref self, const py_Ref key) {
 | 
			
		||||
    assert(py_isdict(self));
 | 
			
		||||
    Dict* ud = py_touserdata(self);
 | 
			
		||||
    DictEntry* entry;
 | 
			
		||||
@ -500,13 +500,13 @@ py_Ref py_dict__getitem(py_Ref self, py_Ref key) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_dict__setitem(py_Ref self, py_Ref key, py_Ref val) {
 | 
			
		||||
void py_dict__setitem(py_Ref self, const py_Ref key, const py_Ref val) {
 | 
			
		||||
    assert(py_isdict(self));
 | 
			
		||||
    Dict* ud = py_touserdata(self);
 | 
			
		||||
    Dict__set(ud, key, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_dict__contains(py_Ref self, py_Ref key) {
 | 
			
		||||
bool py_dict__contains(const py_Ref self, const py_Ref key) {
 | 
			
		||||
    assert(py_isdict(self));
 | 
			
		||||
    Dict* ud = py_touserdata(self);
 | 
			
		||||
    DictEntry* entry;
 | 
			
		||||
@ -514,13 +514,13 @@ bool py_dict__contains(py_Ref self, py_Ref key) {
 | 
			
		||||
    return ok && entry != NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int py_dict__len(py_Ref self) {
 | 
			
		||||
int py_dict__len(const py_Ref self) {
 | 
			
		||||
    assert(py_isdict(self));
 | 
			
		||||
    Dict* ud = py_touserdata(self);
 | 
			
		||||
    return ud->length;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void *), void *ctx){
 | 
			
		||||
bool py_dict__apply(const py_Ref self, bool (*f)(const py_Ref, const py_Ref, void *), void *ctx){
 | 
			
		||||
    Dict* ud = py_touserdata(self);
 | 
			
		||||
    for(int i = 0; i < ud->entries.count; i++) {
 | 
			
		||||
        DictEntry* entry = c11__at(DictEntry, &ud->entries, i);
 | 
			
		||||
 | 
			
		||||
@ -19,17 +19,17 @@ void py_newlistn(py_Ref out, int n) {
 | 
			
		||||
    userdata->count = n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Ref py_list__data(py_Ref self) {
 | 
			
		||||
py_Ref py_list__data(const py_Ref self) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    return userdata->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Ref py_list__getitem(py_Ref self, int i) {
 | 
			
		||||
py_Ref py_list__getitem(const py_Ref self, int i) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    return c11__at(py_TValue, userdata, i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list__setitem(py_Ref self, int i, py_Ref val) {
 | 
			
		||||
void py_list__setitem(py_Ref self, int i, const py_Ref val) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    c11__setitem(py_TValue, userdata, i, *val);
 | 
			
		||||
}
 | 
			
		||||
@ -39,12 +39,12 @@ void py_list__delitem(py_Ref self, int i) {
 | 
			
		||||
    c11_vector__erase(py_TValue, userdata, i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int py_list__len(py_Ref self) {
 | 
			
		||||
int py_list__len(const py_Ref self) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    return userdata->count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list__append(py_Ref self, py_Ref val) {
 | 
			
		||||
void py_list__append(py_Ref self, const py_Ref val) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    c11_vector__push(py_TValue, userdata, *val);
 | 
			
		||||
}
 | 
			
		||||
@ -54,7 +54,7 @@ void py_list__clear(py_Ref self) {
 | 
			
		||||
    c11_vector__clear(userdata);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list__insert(py_Ref self, int i, py_Ref val) {
 | 
			
		||||
void py_list__insert(py_Ref self, int i, const py_Ref val) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    c11_vector__insert(py_TValue, userdata, i, *val);
 | 
			
		||||
}
 | 
			
		||||
@ -78,7 +78,7 @@ static bool _py_list__eq__(int argc, py_Ref argv) {
 | 
			
		||||
        int length0, length1;
 | 
			
		||||
        py_TValue* a0 = pk_arrayview(py_arg(0), &length0);
 | 
			
		||||
        py_TValue* a1 = pk_arrayview(py_arg(1), &length1);
 | 
			
		||||
        int res = pk_arrayequal(a0, length0, a1, length1);
 | 
			
		||||
        int res = pk_arrayeq(a0, length0, a1, length1);
 | 
			
		||||
        if(res == -1) return false;
 | 
			
		||||
        py_newbool(py_retval(), res);
 | 
			
		||||
    } else {
 | 
			
		||||
@ -258,7 +258,7 @@ static bool _py_list__count(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(2);
 | 
			
		||||
    int count = 0;
 | 
			
		||||
    for(int i = 0; i < py_list__len(py_arg(0)); i++) {
 | 
			
		||||
        int res = py_equal(py_list__getitem(py_arg(0), i), py_arg(1));
 | 
			
		||||
        int res = py_eq(py_list__getitem(py_arg(0), i), py_arg(1));
 | 
			
		||||
        if(res == -1) return false;
 | 
			
		||||
        if(res) count++;
 | 
			
		||||
    }
 | 
			
		||||
@ -290,7 +290,7 @@ static bool _py_list__index(int argc, py_Ref argv) {
 | 
			
		||||
        start = py_toint(py_arg(2));
 | 
			
		||||
    }
 | 
			
		||||
    for(int i = start; i < py_list__len(py_arg(0)); i++) {
 | 
			
		||||
        int res = py_equal(py_list__getitem(py_arg(0), i), py_arg(1));
 | 
			
		||||
        int res = py_eq(py_list__getitem(py_arg(0), i), py_arg(1));
 | 
			
		||||
        if(res == -1) return false;
 | 
			
		||||
        if(res) {
 | 
			
		||||
            py_newint(py_retval(), i);
 | 
			
		||||
@ -311,7 +311,7 @@ static bool _py_list__reverse(int argc, py_Ref argv) {
 | 
			
		||||
static bool _py_list__remove(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(2);
 | 
			
		||||
    for(int i = 0; i < py_list__len(py_arg(0)); i++) {
 | 
			
		||||
        int res = py_equal(py_list__getitem(py_arg(0), i), py_arg(1));
 | 
			
		||||
        int res = py_eq(py_list__getitem(py_arg(0), i), py_arg(1));
 | 
			
		||||
        if(res == -1) return false;
 | 
			
		||||
        if(res) {
 | 
			
		||||
            py_list__delitem(py_arg(0), i);
 | 
			
		||||
@ -354,7 +354,7 @@ static bool _py_list__insert(int argc, py_Ref argv) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _py_lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
 | 
			
		||||
    if(!key) return py_less(a, b);
 | 
			
		||||
    if(!key) return py_lt(a, b);
 | 
			
		||||
    pk_VM* vm = pk_current_vm;
 | 
			
		||||
    // project a
 | 
			
		||||
    py_push(key);
 | 
			
		||||
@ -372,7 +372,7 @@ static int _py_lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
 | 
			
		||||
    bool ok = pk_stack_binaryop(vm, __lt__, __gt__);
 | 
			
		||||
    if(!ok) return -1;
 | 
			
		||||
    py_shrink(2);
 | 
			
		||||
    return py_bool(py_retval());
 | 
			
		||||
    return py_tobool(py_retval());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sort(self, key=None, reverse=False)
 | 
			
		||||
@ -401,11 +401,6 @@ static bool _py_list__iter__(int argc, py_Ref argv) {
 | 
			
		||||
    return pk_arrayiter(argv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool _py_list__contains__(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(2);
 | 
			
		||||
    return pk_arraycontains(py_arg(0), py_arg(1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Type pk_list__register() {
 | 
			
		||||
    py_Type type =
 | 
			
		||||
        pk_newtype("list", tp_object, NULL, (void (*)(void*))c11_vector__dtor, false, true);
 | 
			
		||||
@ -422,7 +417,6 @@ py_Type pk_list__register() {
 | 
			
		||||
    py_bindmagic(type, __rmul__, _py_list__rmul__);
 | 
			
		||||
    py_bindmagic(type, __repr__, _py_list__repr__);
 | 
			
		||||
    py_bindmagic(type, __iter__, _py_list__iter__);
 | 
			
		||||
    py_bindmagic(type, __contains__, _py_list__contains__);
 | 
			
		||||
 | 
			
		||||
    py_bindmethod(type, "append", _py_list__append);
 | 
			
		||||
    py_bindmethod(type, "extend", _py_list__extend);
 | 
			
		||||
@ -442,7 +436,7 @@ py_Type pk_list__register() {
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pk_list__mark(void* ud, void (*marker)(py_TValue*)) {
 | 
			
		||||
void pk_list__mark(void* ud, void (*marker)(py_TValue*)){
 | 
			
		||||
    List* self = ud;
 | 
			
		||||
    for(int i = 0; i < self->count; i++) {
 | 
			
		||||
        marker(c11__at(py_TValue, self, i));
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
#include "pocketpy/objects/base.h"
 | 
			
		||||
#include "pocketpy/pocketpy.h"
 | 
			
		||||
 | 
			
		||||
bool py_isidentical(py_Ref lhs, py_Ref rhs) {
 | 
			
		||||
bool py_isidentical(const py_Ref lhs, const py_Ref rhs) {
 | 
			
		||||
    if(lhs->type != rhs->type) return false;
 | 
			
		||||
    switch(lhs->type) {
 | 
			
		||||
        case tp_int: return lhs->_i64 == rhs->_i64;
 | 
			
		||||
@ -17,7 +17,7 @@ bool py_isidentical(py_Ref lhs, py_Ref rhs) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int py_bool(py_Ref val) {
 | 
			
		||||
int py_bool(const py_Ref val) {
 | 
			
		||||
    switch(val->type) {
 | 
			
		||||
        case tp_bool: return val->_bool;
 | 
			
		||||
        case tp_int: return val->_i64 != 0;
 | 
			
		||||
@ -26,14 +26,14 @@ int py_bool(py_Ref val) {
 | 
			
		||||
        default: {
 | 
			
		||||
            py_Ref tmp = py_tpfindmagic(val->type, __bool__);
 | 
			
		||||
            if(tmp) {
 | 
			
		||||
                if(!py_call(tmp, 1, val)) return -1;
 | 
			
		||||
                if(!py_checkbool(py_retval())) return -1;
 | 
			
		||||
                bool ok = py_call(tmp, 1, val);
 | 
			
		||||
                if(!ok) return -1;
 | 
			
		||||
                return py_tobool(py_retval());
 | 
			
		||||
            } else {
 | 
			
		||||
                tmp = py_tpfindmagic(val->type, __len__);
 | 
			
		||||
                if(tmp) {
 | 
			
		||||
                    if(!py_call(tmp, 1, val)) return -1;
 | 
			
		||||
                    if(!py_checkint(py_retval())) return -1;
 | 
			
		||||
                    bool ok = py_call(tmp, 1, val);
 | 
			
		||||
                    if(!ok) return -1;
 | 
			
		||||
                    return py_toint(py_retval());
 | 
			
		||||
                } else {
 | 
			
		||||
                    return 1;  // True
 | 
			
		||||
@ -43,7 +43,7 @@ int py_bool(py_Ref val) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_hash(py_Ref val, int64_t* out) {
 | 
			
		||||
bool py_hash(const py_Ref val, int64_t* out) {
 | 
			
		||||
    py_Type t = val->type;
 | 
			
		||||
    pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
 | 
			
		||||
    do {
 | 
			
		||||
@ -51,8 +51,8 @@ bool py_hash(py_Ref val, int64_t* out) {
 | 
			
		||||
        if(py_isnone(_hash)) break;
 | 
			
		||||
        py_Ref _eq = &types[t].magic[__eq__];
 | 
			
		||||
        if(!py_isnil(_hash) && !py_isnil(_eq)) {
 | 
			
		||||
            if(!py_call(_hash, 1, val)) return false;
 | 
			
		||||
            if(!py_checkint(py_retval())) return false;
 | 
			
		||||
            bool ok = py_call(_hash, 1, val);
 | 
			
		||||
            if(!ok) return false;
 | 
			
		||||
            *out = py_toint(py_retval());
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
@ -61,18 +61,19 @@ bool py_hash(py_Ref val, int64_t* out) {
 | 
			
		||||
    return TypeError("unhashable type: '%t'", val->type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_iter(py_Ref val) {
 | 
			
		||||
bool py_iter(const py_Ref val) {
 | 
			
		||||
    py_Ref tmp = py_tpfindmagic(val->type, __iter__);
 | 
			
		||||
    if(!tmp) return TypeError("'%t' object is not iterable", val->type);
 | 
			
		||||
    return py_call(tmp, 1, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int py_next(py_Ref val) {
 | 
			
		||||
int py_next(const py_Ref val) {
 | 
			
		||||
    pk_VM* vm = pk_current_vm;
 | 
			
		||||
    vm->is_stopiteration = false;
 | 
			
		||||
    py_Ref tmp = py_tpfindmagic(val->type, __next__);
 | 
			
		||||
    if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
 | 
			
		||||
    if(py_call(tmp, 1, val)) return true;
 | 
			
		||||
    bool ok = py_call(tmp, 1, val);
 | 
			
		||||
    if(ok) return true;
 | 
			
		||||
    return vm->is_stopiteration ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -134,7 +135,7 @@ bool py_getattr(py_Ref self, py_Name name) {
 | 
			
		||||
    return AttributeError(self, name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_setattr(py_Ref self, py_Name name, py_Ref val) {
 | 
			
		||||
bool py_setattr(py_Ref self, py_Name name, const py_Ref val) {
 | 
			
		||||
    py_Type type = self->type;
 | 
			
		||||
    // handle super() proxy
 | 
			
		||||
    if(py_istype(self, tp_super)) {
 | 
			
		||||
@ -175,7 +176,7 @@ bool py_delattr(py_Ref self, py_Name name) {
 | 
			
		||||
    return TypeError("cannot delete attribute");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_getitem(py_Ref self, py_Ref key) {
 | 
			
		||||
bool py_getitem(const py_Ref self, const py_Ref key) {
 | 
			
		||||
    py_push(self);
 | 
			
		||||
    py_push(key);
 | 
			
		||||
    bool ok = py_callmagic(__getitem__, 2, py_peek(-2));
 | 
			
		||||
@ -183,7 +184,7 @@ bool py_getitem(py_Ref self, py_Ref key) {
 | 
			
		||||
    return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_setitem(py_Ref self, py_Ref key, py_Ref val) {
 | 
			
		||||
bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val) {
 | 
			
		||||
    py_push(self);
 | 
			
		||||
    py_push(key);
 | 
			
		||||
    py_push(val);
 | 
			
		||||
@ -192,7 +193,7 @@ bool py_setitem(py_Ref self, py_Ref key, py_Ref val) {
 | 
			
		||||
    return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_delitem(py_Ref self, py_Ref key) {
 | 
			
		||||
bool py_delitem(py_Ref self, const py_Ref key) {
 | 
			
		||||
    py_push(self);
 | 
			
		||||
    py_push(key);
 | 
			
		||||
    bool ok = py_callmagic(__delitem__, 2, py_peek(-2));
 | 
			
		||||
@ -200,12 +201,16 @@ bool py_delitem(py_Ref self, py_Ref key) {
 | 
			
		||||
    return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int py_equal(py_Ref lhs, py_Ref rhs){
 | 
			
		||||
    if(!py_eq(lhs, rhs)) return -1;
 | 
			
		||||
    return py_bool(py_retval());
 | 
			
		||||
}
 | 
			
		||||
#define COMPARE_OP_IMPL(name, op, rop)                                                             \
 | 
			
		||||
    int py_##name(const py_Ref lhs, const py_Ref rhs) {                                            \
 | 
			
		||||
        bool ok = py_binaryop(lhs, rhs, op, rop);                                                  \
 | 
			
		||||
        if(!ok) return -1;                                                                         \
 | 
			
		||||
        return py_tobool(py_retval());                                                             \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
int py_less(py_Ref lhs, py_Ref rhs){
 | 
			
		||||
    if(!py_lt(lhs, rhs)) return -1;
 | 
			
		||||
    return py_bool(py_retval());
 | 
			
		||||
}
 | 
			
		||||
COMPARE_OP_IMPL(eq, __eq__, __eq__)
 | 
			
		||||
COMPARE_OP_IMPL(ne, __ne__, __ne__)
 | 
			
		||||
COMPARE_OP_IMPL(lt, __lt__, __gt__)
 | 
			
		||||
COMPARE_OP_IMPL(le, __le__, __ge__)
 | 
			
		||||
COMPARE_OP_IMPL(gt, __gt__, __lt__)
 | 
			
		||||
COMPARE_OP_IMPL(ge, __ge__, __le__)
 | 
			
		||||
@ -31,26 +31,26 @@ unsigned char* py_newbytes(py_Ref out, int size) {
 | 
			
		||||
    return ud->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* py_tostr(py_Ref self) {
 | 
			
		||||
const char* py_tostr(const py_Ref self) {
 | 
			
		||||
    assert(self->type == tp_str);
 | 
			
		||||
    c11_string* ud = PyObject__userdata(self->_obj);
 | 
			
		||||
    return ud->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* py_tostrn(py_Ref self, int* size) {
 | 
			
		||||
const char* py_tostrn(const py_Ref self, int* size) {
 | 
			
		||||
    assert(self->type == tp_str);
 | 
			
		||||
    c11_string* ud = PyObject__userdata(self->_obj);
 | 
			
		||||
    *size = ud->size;
 | 
			
		||||
    return ud->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
c11_sv py_tosv(py_Ref self) {
 | 
			
		||||
c11_sv py_tosv(const py_Ref self) {
 | 
			
		||||
    assert(self->type == tp_str);
 | 
			
		||||
    c11_string* ud = PyObject__userdata(self->_obj);
 | 
			
		||||
    return c11_string__sv(ud);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned char* py_tobytes(py_Ref self, int* size) {
 | 
			
		||||
unsigned char* py_tobytes(const py_Ref self, int* size) {
 | 
			
		||||
    assert(self->type == tp_bytes);
 | 
			
		||||
    c11_bytes* ud = PyObject__userdata(self->_obj);
 | 
			
		||||
    *size = ud->size;
 | 
			
		||||
 | 
			
		||||
@ -13,13 +13,13 @@ void py_newtuple(py_Ref out, int n) {
 | 
			
		||||
    out->_obj = obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Ref py_tuple__getitem(py_Ref self, int i) { return py_getslot(self, i); }
 | 
			
		||||
py_Ref py_tuple__getitem(const py_Ref self, int i) { return py_getslot(self, i); }
 | 
			
		||||
 | 
			
		||||
py_Ref py_tuple__data(py_Ref self) { return PyObject__slots(self->_obj); }
 | 
			
		||||
py_Ref py_tuple__data(const py_Ref self) { return PyObject__slots(self->_obj); }
 | 
			
		||||
 | 
			
		||||
void py_tuple__setitem(py_Ref self, int i, py_Ref val) { py_setslot(self, i, val); }
 | 
			
		||||
void py_tuple__setitem(py_Ref self, int i, const py_Ref val) { py_setslot(self, i, val); }
 | 
			
		||||
 | 
			
		||||
int py_tuple__len(py_Ref self) { return self->_obj->slots; }
 | 
			
		||||
int py_tuple__len(const py_Ref self) { return self->_obj->slots; }
 | 
			
		||||
 | 
			
		||||
//////////////
 | 
			
		||||
static bool _py_tuple__len__(int argc, py_Ref argv) {
 | 
			
		||||
@ -103,7 +103,7 @@ static bool _py_tuple__eq__(int argc, py_Ref argv) {
 | 
			
		||||
        int length0, length1;
 | 
			
		||||
        py_TValue* a0 = pk_arrayview(py_arg(0), &length0);
 | 
			
		||||
        py_TValue* a1 = pk_arrayview(py_arg(1), &length1);
 | 
			
		||||
        int res = pk_arrayequal(a0, length0, a1, length1);
 | 
			
		||||
        int res = pk_arrayeq(a0, length0, a1, length1);
 | 
			
		||||
        if(res == -1) return false;
 | 
			
		||||
        py_newbool(py_retval(), res);
 | 
			
		||||
    } else {
 | 
			
		||||
@ -126,11 +126,6 @@ static bool _py_tuple__iter__(int argc, py_Ref argv) {
 | 
			
		||||
    return pk_arrayiter(argv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool _py_tuple__contains__(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(2);
 | 
			
		||||
    return pk_arraycontains(py_arg(0), py_arg(1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Type pk_tuple__register() {
 | 
			
		||||
    py_Type type = pk_newtype("tuple", tp_object, NULL, NULL, false, true);
 | 
			
		||||
 | 
			
		||||
@ -141,6 +136,5 @@ py_Type pk_tuple__register() {
 | 
			
		||||
    py_bindmagic(type, __eq__, _py_tuple__eq__);
 | 
			
		||||
    py_bindmagic(type, __ne__, _py_tuple__ne__);
 | 
			
		||||
    py_bindmagic(type, __iter__, _py_tuple__iter__);
 | 
			
		||||
    py_bindmagic(type, __contains__, _py_tuple__contains__);
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
 | 
			
		||||
py_Ref py_reg(int i) { return pk_current_vm->reg + i; }
 | 
			
		||||
 | 
			
		||||
py_Ref py_getdict(py_Ref self, py_Name name) {
 | 
			
		||||
py_Ref py_getdict(const py_Ref self, py_Name name) {
 | 
			
		||||
    assert(self && self->is_ptr);
 | 
			
		||||
    if(!py_ismagicname(name) || self->type != tp_type) {
 | 
			
		||||
        return pk_NameDict__try_get(PyObject__dict(self->_obj), name);
 | 
			
		||||
@ -17,7 +17,7 @@ py_Ref py_getdict(py_Ref self, py_Name name) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_setdict(py_Ref self, py_Name name, py_Ref val) {
 | 
			
		||||
void py_setdict(py_Ref self, py_Name name, const py_Ref val) {
 | 
			
		||||
    assert(self && self->is_ptr);
 | 
			
		||||
    if(!py_ismagicname(name) || self->type != tp_type) {
 | 
			
		||||
        pk_NameDict__set(PyObject__dict(self->_obj), name, *val);
 | 
			
		||||
@ -39,19 +39,19 @@ bool py_deldict(py_Ref self, py_Name name) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Ref py_getslot(py_Ref self, int i) {
 | 
			
		||||
py_Ref py_getslot(const py_Ref self, int i) {
 | 
			
		||||
    assert(self && self->is_ptr);
 | 
			
		||||
    assert(i >= 0 && i < self->_obj->slots);
 | 
			
		||||
    return PyObject__slots(self->_obj) + i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_setslot(py_Ref self, int i, py_Ref val) {
 | 
			
		||||
void py_setslot(py_Ref self, int i, const py_Ref val) {
 | 
			
		||||
    assert(self && self->is_ptr);
 | 
			
		||||
    assert(i >= 0 && i < self->_obj->slots);
 | 
			
		||||
    PyObject__slots(self->_obj)[i] = *val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_assign(py_Ref dst, py_Ref src) { *dst = *src; }
 | 
			
		||||
void py_assign(py_Ref dst, const py_Ref src) { *dst = *src; }
 | 
			
		||||
 | 
			
		||||
/* Stack References */
 | 
			
		||||
py_Ref py_peek(int i) {
 | 
			
		||||
@ -69,7 +69,7 @@ void py_shrink(int n) {
 | 
			
		||||
    vm->stack.sp -= n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_push(py_Ref src) {
 | 
			
		||||
void py_push(const py_Ref src) {
 | 
			
		||||
    pk_VM* vm = pk_current_vm;
 | 
			
		||||
    *vm->stack.sp++ = *src;
 | 
			
		||||
}
 | 
			
		||||
@ -82,5 +82,5 @@ void py_pushnil() {
 | 
			
		||||
py_Ref py_pushtmp() {
 | 
			
		||||
    pk_VM* vm = pk_current_vm;
 | 
			
		||||
    py_newnil(vm->stack.sp++);
 | 
			
		||||
    return py_peek(-1);
 | 
			
		||||
    return py_gettop();
 | 
			
		||||
}
 | 
			
		||||
@ -152,13 +152,9 @@ assert repr([1, [2, 3], 4]) == "[1, [2, 3], 4]"
 | 
			
		||||
assert repr([1, [2, [3, 4]], 5]) == "[1, [2, [3, 4]], 5]"
 | 
			
		||||
assert repr([]) == "[]"
 | 
			
		||||
 | 
			
		||||
# test in and not in
 | 
			
		||||
assert 1 in [1, 2, 3]
 | 
			
		||||
assert 4 not in [1, 2, 3]
 | 
			
		||||
 | 
			
		||||
b = [(1, 2), (3, 3), (5, 1)]
 | 
			
		||||
b.sort(key=lambda x:x[1])
 | 
			
		||||
assert b == [(5, 1), (1, 2), (3,3)]
 | 
			
		||||
# b = [(1, 2), (3, 3), (5, 1)]
 | 
			
		||||
# b.sort(key=lambda x:x[1])
 | 
			
		||||
# assert b == [(5, 1), (1, 2), (3,3)]
 | 
			
		||||
 | 
			
		||||
# test cyclic reference
 | 
			
		||||
# a = []
 | 
			
		||||
 | 
			
		||||
@ -30,8 +30,4 @@ assert l[-3:-1] == (2,3)
 | 
			
		||||
assert repr((1,)) == '(1,)'
 | 
			
		||||
assert repr((1,2,)) == '(1, 2)'
 | 
			
		||||
assert repr((1,2,(3,4))) == '(1, 2, (3, 4))'
 | 
			
		||||
assert repr(tuple()) == '()'
 | 
			
		||||
 | 
			
		||||
# test in and not in
 | 
			
		||||
assert 1 in (1, 2, 3)
 | 
			
		||||
assert 4 not in (1, 2, 3)
 | 
			
		||||
assert repr(tuple()) == '()'
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user