This commit is contained in:
blueloveTH 2024-07-07 23:51:48 +08:00
parent a81563768d
commit 140255650d
11 changed files with 260 additions and 76 deletions

View File

@ -42,8 +42,8 @@ typedef struct pk_VM {
pk_NameDict modules; pk_NameDict modules;
c11_vector /*T=pk_TypeInfo*/ types; c11_vector /*T=pk_TypeInfo*/ types;
py_TValue builtins; // builtins module py_TValue builtins; // builtins module
py_TValue main; // __main__ module py_TValue main; // __main__ module
void (*_ceval_on_step)(Frame*, Bytecode); void (*_ceval_on_step)(Frame*, Bytecode);
unsigned char* (*_import_file)(const char*); unsigned char* (*_import_file)(const char*);
@ -93,6 +93,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
const char* pk_opname(Opcode op); const char* pk_opname(Opcode op);
py_TValue* pk_arrayview(py_Ref self, int* length); py_TValue* pk_arrayview(py_Ref self, int* length);
int pk_arrayeq(py_TValue* lhs, int lhs_length, py_TValue* rhs, int rhs_length);
/// Assumes [a, b] are on the stack, performs a binary op. /// Assumes [a, b] are on the stack, performs a binary op.
/// The result is stored in `self->last_retval`. /// The result is stored in `self->last_retval`.
@ -106,6 +107,7 @@ py_Type pk_str__register();
py_Type pk_str_iterator__register(); py_Type pk_str_iterator__register();
py_Type pk_bytes__register(); py_Type pk_bytes__register();
py_Type pk_list__register(); py_Type pk_list__register();
py_Type pk_tuple__register();
py_Type pk_function__register(); py_Type pk_function__register();
py_Type pk_nativefunc__register(); py_Type pk_nativefunc__register();
py_Type pk_range__register(); py_Type pk_range__register();

View File

@ -33,8 +33,10 @@ def test_dir(path):
else: else:
if not test_file(filepath): if not test_file(filepath):
print('-' * 50) print('-' * 50)
print("TEST FAILED! Press any key to continue...") print("TEST FAILED!")
input() exit(1)
# print("TEST FAILED! Press any key to continue...")
# input()
print('CPython:', str(sys.version).replace('\n', '')) print('CPython:', str(sys.version).replace('\n', ''))
print('System:', '64-bit' if sys.maxsize > 2**32 else '32-bit') print('System:', '64-bit' if sys.maxsize > 2**32 else '32-bit')

View File

@ -179,10 +179,16 @@ bool StarredExpr__emit_store(Expr* self_, Ctx* ctx) {
return vtemit_store(self->child, ctx); return vtemit_store(self->child, ctx);
} }
void StarredExpr__dtor(Expr* self_) {
StarredExpr* self = (StarredExpr*)self_;
vtdelete(self->child);
}
StarredExpr* StarredExpr__new(int line, Expr* child, int level) { StarredExpr* StarredExpr__new(int line, Expr* child, int level) {
const static ExprVt Vt = {.emit_ = StarredExpr__emit_, const static ExprVt Vt = {.emit_ = StarredExpr__emit_,
.emit_store = StarredExpr__emit_store, .emit_store = StarredExpr__emit_store,
.is_starred = true}; .is_starred = true,
.dtor = StarredExpr__dtor};
static_assert_expr_size(StarredExpr); static_assert_expr_size(StarredExpr);
StarredExpr* self = PoolExpr_alloc(); StarredExpr* self = PoolExpr_alloc();
self->vt = &Vt; self->vt = &Vt;

View File

@ -98,7 +98,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
break; break;
} }
case tp_tuple: { case tp_tuple: {
pk_sprintf(&buf, "tuple(%d)", py_list__len(p)); pk_sprintf(&buf, "tuple(%d)", py_tuple__len(p));
break; break;
} }
case tp_function: { case tp_function: {
@ -313,14 +313,15 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__); py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
py_TValue* next_sp = TOP();
bool ok = magic->_cfunc(2, SECOND()); bool ok = magic->_cfunc(2, SECOND());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
POP(); SP() = next_sp;
*TOP() = self->last_retval; *TOP() = self->last_retval;
} else { } else {
INSERT_THIRD(); // [?, a, b] INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__getitem__, a, b] *THIRD() = *magic; // [__getitem__, a, b]
vectorcall_opcall(2, 0); vectorcall_opcall(1, 0);
} }
DISPATCH(); DISPATCH();
} }
@ -366,14 +367,14 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__); py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
py_TValue* next_sp = THIRD();
bool ok = magic->_cfunc(3, THIRD()); bool ok = magic->_cfunc(3, THIRD());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
STACK_SHRINK(3); SP() = next_sp;
*TOP() = self->last_retval; *TOP() = self->last_retval;
} else { } else {
INSERT_THIRD(); // [?, a, b]
*FOURTH() = *magic; // [__selitem__, a, b, val] *FOURTH() = *magic; // [__selitem__, a, b, val]
vectorcall_opcall(3, 0); vectorcall_opcall(2, 0);
POP(); // discard retval POP(); // discard retval
} }
DISPATCH(); DISPATCH();
@ -437,13 +438,14 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__); py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
py_TValue* next_sp = SECOND();
bool ok = magic->_cfunc(2, SECOND()); bool ok = magic->_cfunc(2, SECOND());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
STACK_SHRINK(2); SP() = next_sp;
} else { } else {
INSERT_THIRD(); // [?, a, b] INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__delitem__, a, b] *THIRD() = *magic; // [__delitem__, a, b]
vectorcall_opcall(2, 0); vectorcall_opcall(1, 0);
POP(); // discard retval POP(); // discard retval
} }
DISPATCH(); DISPATCH();
@ -567,18 +569,19 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
DISPATCH(); DISPATCH();
} }
case OP_CONTAINS_OP: { case OP_CONTAINS_OP: {
// [b, a] -> b __contains__ a (a in b) // [b, a] -> b __contains__ a (a in b) -> [retval]
py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__); py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
py_TValue* next_sp = TOP();
bool ok = magic->_cfunc(2, SECOND()); bool ok = magic->_cfunc(2, SECOND());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
POP(); SP() = next_sp;
*TOP() = self->last_retval; *TOP() = self->last_retval;
} else { } else {
INSERT_THIRD(); // [?, b, a] INSERT_THIRD(); // [?, b, a]
*THIRD() = *magic; // [__contains__, a, b] *THIRD() = *magic; // [__contains__, a, b]
vectorcall_opcall(2, 0); vectorcall_opcall(1, 0);
} }
bool res = py_tobool(TOP()); bool res = py_tobool(TOP());
if(byte.arg) py_newbool(TOP(), !res); if(byte.arg) py_newbool(TOP(), !res);
@ -713,6 +716,28 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
if(!stack_unpack_sequence(self, byte.arg)) goto __ERROR; if(!stack_unpack_sequence(self, byte.arg)) goto __ERROR;
DISPATCH(); DISPATCH();
} }
case OP_UNPACK_EX: {
int length;
py_TValue* p = pk_arrayview(TOP(), &length);
if(!p) {
TypeError("expected list or tuple to unpack, got '%t'", TOP()->type);
goto __ERROR;
}
int exceed = length - byte.arg;
if(exceed < 0) {
ValueError("not enough values to unpack");
goto __ERROR;
}
POP();
for(int i = 0; i < byte.arg; i++) {
PUSH(p + i);
}
py_newlistn(SP()++, exceed);
for(int i = 0; i < exceed; i++) {
py_list__setitem(TOP(), i, p + byte.arg + i);
}
DISPATCH();
}
/////////// ///////////
case OP_RAISE_ASSERT: { case OP_RAISE_ASSERT: {
@ -781,7 +806,8 @@ static bool stack_unpack_sequence(pk_VM* self, uint16_t arg) {
if(!p) return TypeError("expected list or tuple to unpack, got '%t'", TOP()->type); if(!p) return TypeError("expected list or tuple to unpack, got '%t'", TOP()->type);
if(length != arg) return ValueError("expected %d values to unpack, got %d", arg, length); if(length != arg) return ValueError("expected %d values to unpack, got %d", arg, length);
POP(); POP();
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++) {
PUSH(p + i); PUSH(p + i);
}
return true; return true;
} }

View File

@ -99,7 +99,7 @@ void pk_VM__ctor(pk_VM* self) {
validate(tp_str_iterator, pk_str_iterator__register()); validate(tp_str_iterator, pk_str_iterator__register());
validate(tp_list, pk_list__register()); validate(tp_list, pk_list__register());
validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false)); validate(tp_tuple, pk_tuple__register());
validate(tp_slice, pk_VM__new_type(self, "slice", tp_object, NULL, false)); validate(tp_slice, pk_VM__new_type(self, "slice", tp_object, NULL, false));
validate(tp_range, pk_range__register()); validate(tp_range, pk_range__register());

View File

@ -3,6 +3,7 @@
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
#include "pocketpy/common/sstream.h"
typedef c11_vector List; typedef c11_vector List;
@ -68,25 +69,13 @@ static bool _py_list__len__(int argc, py_Ref argv) {
static bool _py_list__eq__(int argc, py_Ref argv) { static bool _py_list__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
py_Ref _0 = py_arg(0); if(py_istype(py_arg(1), tp_list)) {
py_Ref _1 = py_arg(1); int length0, length1;
if(py_istype(_1, tp_list)) { py_TValue* a0 = pk_arrayview(py_arg(0), &length0);
int length = py_list__len(_0); py_TValue* a1 = pk_arrayview(py_arg(1), &length1);
if(length != py_list__len(_1)) { int res = pk_arrayeq(a0, length0, a1, length1);
py_newbool(py_retval(), false); if(res == -1) return false;
return true; py_newbool(py_retval(), res);
}
for(int i = 0; i < length; i++) {
py_Ref a = py_list__getitem(_0, i);
py_Ref b = py_list__getitem(_1, i);
int res = py_eq(a, b);
if(res == -1) return false;
if(res == 0) {
py_newbool(py_retval(), false);
return true;
}
}
py_newbool(py_retval(), true);
} else { } else {
py_newnotimplemented(py_retval()); py_newnotimplemented(py_retval());
} }
@ -225,6 +214,30 @@ static bool _py_list__append(int argc, py_Ref argv) {
return true; return true;
} }
static bool _py_list__repr__(int argc, py_Ref argv) {
List* self = py_touserdata(py_arg(0));
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_char(&buf, '[');
for(int i = 0; i < self->count; i++) {
py_TValue* val = c11__at(py_TValue, self, i);
bool ok = py_repr(val);
if(!ok) {
c11_sbuf__dtor(&buf);
return false;
}
int size;
const char* data = py_tostrn(py_retval(), &size);
c11_sbuf__write_cstrn(&buf, data, size);
if(i != self->count - 1) c11_sbuf__write_cstr(&buf, ", ");
}
c11_sbuf__write_char(&buf, ']');
c11_string* res = c11_sbuf__submit(&buf);
py_newstrn(py_retval(), res->data, res->size);
c11_string__delete(res);
return true;
}
static bool _py_list__extend(int argc, py_Ref argv) { static bool _py_list__extend(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
List* self = py_touserdata(py_arg(0)); List* self = py_touserdata(py_arg(0));
@ -355,10 +368,10 @@ static bool _py_list__sort(int argc, py_Ref argv) {
if(py_isnone(key)) key = NULL; if(py_isnone(key)) key = NULL;
bool ok = c11__stable_sort(self->data, bool ok = c11__stable_sort(self->data,
self->count, self->count,
sizeof(py_TValue), sizeof(py_TValue),
(int (*)(const void*, const void*, void*))_py_lt_with_key, (int (*)(const void*, const void*, void*))_py_lt_with_key,
key); key);
if(!ok) return false; if(!ok) return false;
PY_CHECK_ARG_TYPE(2, tp_bool); PY_CHECK_ARG_TYPE(2, tp_bool);
@ -384,6 +397,7 @@ py_Type pk_list__register() {
py_bindmagic(type, __add__, _py_list__add__); py_bindmagic(type, __add__, _py_list__add__);
py_bindmagic(type, __mul__, _py_list__mul__); py_bindmagic(type, __mul__, _py_list__mul__);
py_bindmagic(type, __rmul__, _py_list__rmul__); py_bindmagic(type, __rmul__, _py_list__rmul__);
py_bindmagic(type, __repr__, _py_list__repr__);
py_bindmethod(type, "append", _py_list__append); py_bindmethod(type, "append", _py_list__append);
py_bindmethod(type, "extend", _py_list__extend); py_bindmethod(type, "extend", _py_list__extend);

View File

@ -1,6 +1,7 @@
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
#include "pocketpy/common/sstream.h"
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
@ -12,14 +13,122 @@ void py_newtuple(py_Ref out, int n) {
out->_obj = obj; out->_obj = obj;
} }
py_Ref py_tuple__getitem(const py_Ref self, int i){ py_Ref py_tuple__getitem(const py_Ref self, int i) { return py_getslot(self, i); }
return py_getslot(self, i);
void py_tuple__setitem(py_Ref self, int i, const py_Ref val) { py_setslot(self, i, val); }
int py_tuple__len(const py_Ref self) { return self->_obj->slots; }
//////////////
static bool _py_tuple__len__(int argc, py_Ref argv) {
py_newint(py_retval(), py_tuple__len(argv));
return true;
} }
void py_tuple__setitem(py_Ref self, int i, const py_Ref val){ static bool _py_tuple__repr__(int argc, py_Ref argv) {
py_setslot(self, i, val); c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_char(&buf, '(');
int length = py_tuple__len(argv);
for(int i = 0; i < length; i++) {
py_TValue* val = py_getslot(argv, i);
bool ok = py_repr(val);
if(!ok) {
c11_sbuf__dtor(&buf);
return false;
}
int size;
const char* data = py_tostrn(py_retval(), &size);
c11_sbuf__write_cstrn(&buf, data, size);
if(i != length - 1) c11_sbuf__write_cstr(&buf, ", ");
}
if(length == 1) c11_sbuf__write_char(&buf, ',');
c11_sbuf__write_char(&buf, ')');
c11_string* res = c11_sbuf__submit(&buf);
py_newstrn(py_retval(), res->data, res->size);
c11_string__delete(res);
return true;
} }
int py_tuple__len(const py_Ref self){ static bool _py_tuple__new__(int argc, py_Ref argv) {
return self->_obj->slots; if(argc == 1 + 0) {
py_newtuple(py_retval(), 0);
return true;
}
if(argc == 1 + 1) {
bool ok = py_tpcall(tp_list, 1, py_arg(1));
if(!ok) return false;
py_Ref tmp = py_pushtmp();
*tmp = *py_retval(); // backup the list
int length = py_list__len(tmp);
py_newtuple(py_retval(), length);
for(int i = 0; i < py_tuple__len(py_retval()); i++) {
py_tuple__setitem(py_retval(), i, py_list__getitem(tmp, i));
}
return true;
}
return TypeError("tuple() takes at most 1 argument");
}
static bool _py_tuple__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
int length = py_tuple__len(argv);
py_Ref _1 = py_arg(1);
if(_1->type == tp_int) {
int index = py_toint(py_arg(1));
if(!pk__normalize_index(&index, length)) return false;
*py_retval() = *py_getslot(argv, index);
return true;
} else if(_1->type == tp_slice) {
int start, stop, step;
bool ok = pk__parse_int_slice(_1, length, &start, &stop, &step);
if(!ok) return false;
py_Ref tmp = py_pushtmp();
py_newlist(tmp);
PK_SLICE_LOOP(i, start, stop, step) py_list__append(tmp, py_getslot(argv, i));
// convert list to tuple
py_newtuple(py_retval(), py_list__len(tmp));
for(int i = 0; i < py_tuple__len(py_retval()); i++) {
py_tuple__setitem(py_retval(), i, py_list__getitem(tmp, i));
}
return true;
} else {
return TypeError("tuple indices must be integers");
}
}
static bool _py_tuple__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(py_istype(py_arg(1), tp_tuple)) {
int length0, length1;
py_TValue* a0 = pk_arrayview(py_arg(0), &length0);
py_TValue* a1 = pk_arrayview(py_arg(1), &length1);
int res = pk_arrayeq(a0, length0, a1, length1);
if(res == -1) return false;
py_newbool(py_retval(), res);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool _py_tuple__ne__(int argc, py_Ref argv) {
bool ok = _py_tuple__eq__(argc, argv);
if(!ok) return false;
py_Ref retval = py_retval();
py_newbool(retval, !py_tobool(retval));
return true;
}
py_Type pk_tuple__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "tuple", tp_object, NULL, false);
py_bindmagic(type, __len__, _py_tuple__len__);
py_bindmagic(type, __repr__, _py_tuple__repr__);
py_bindmagic(type, __new__, _py_tuple__new__);
py_bindmagic(type, __getitem__, _py_tuple__getitem__);
py_bindmagic(type, __eq__, _py_tuple__eq__);
py_bindmagic(type, __ne__, _py_tuple__ne__);
return type;
} }

View File

@ -4,13 +4,11 @@
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
py_Ref py_reg(int i){ py_Ref py_reg(int i) { return pk_current_vm->reg + i; }
return pk_current_vm->reg + i;
}
py_Ref py_getdict(const py_Ref self, py_Name name){ py_Ref py_getdict(const py_Ref self, py_Name name) {
assert(self && self->is_ptr); assert(self && self->is_ptr);
if(self->type == tp_type && py_ismagicname(name)){ if(self->type == tp_type && py_ismagicname(name)) {
py_Type* ud = py_touserdata(self); py_Type* ud = py_touserdata(self);
py_Ref slot = py_tpmagic(*ud, name); py_Ref slot = py_tpmagic(*ud, name);
return py_isnil(slot) ? NULL : slot; return py_isnil(slot) ? NULL : slot;
@ -18,58 +16,56 @@ py_Ref py_getdict(const py_Ref self, py_Name name){
return pk_NameDict__try_get(PyObject__dict(self->_obj), name); return pk_NameDict__try_get(PyObject__dict(self->_obj), name);
} }
void py_setdict(py_Ref self, py_Name name, const py_Ref val){ void py_setdict(py_Ref self, py_Name name, const py_Ref val) {
assert(self && self->is_ptr); assert(self && self->is_ptr);
if(self->type == tp_type && py_ismagicname(name)){ if(self->type == tp_type && py_ismagicname(name)) {
py_Type* ud = py_touserdata(self); py_Type* ud = py_touserdata(self);
*py_tpmagic(*ud, name) = *val; *py_tpmagic(*ud, name) = *val;
} }
pk_NameDict__set(PyObject__dict(self->_obj), name, *val); pk_NameDict__set(PyObject__dict(self->_obj), name, *val);
} }
py_Ref py_getslot(const py_Ref self, int i){ py_Ref py_getslot(const py_Ref self, int i) {
assert(self && self->is_ptr); assert(self && self->is_ptr);
assert(i >= 0 && i < self->_obj->slots); assert(i >= 0 && i < self->_obj->slots);
return PyObject__slots(self->_obj) + i; return PyObject__slots(self->_obj) + i;
} }
void py_setslot(py_Ref self, int i, const py_Ref val){ void py_setslot(py_Ref self, int i, const py_Ref val) {
assert(self && self->is_ptr); assert(self && self->is_ptr);
assert(i >= 0 && i < self->_obj->slots); assert(i >= 0 && i < self->_obj->slots);
PyObject__slots(self->_obj)[i] = *val; PyObject__slots(self->_obj)[i] = *val;
} }
void py_assign(py_Ref dst, const py_Ref src){ void py_assign(py_Ref dst, const py_Ref src) { *dst = *src; }
*dst = *src;
}
/* Stack References */ /* Stack References */
py_Ref py_peek(int i){ py_Ref py_peek(int i) {
assert(i < 0); assert(i < 0);
return pk_current_vm->stack.sp + i; return pk_current_vm->stack.sp + i;
} }
void py_pop(){ void py_pop() {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
vm->stack.sp--; vm->stack.sp--;
} }
void py_shrink(int n){ void py_shrink(int n) {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
vm->stack.sp -= n; vm->stack.sp -= n;
} }
void py_push(const py_Ref src){ void py_push(const py_Ref src) {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
*vm->stack.sp++ = *src; *vm->stack.sp++ = *src;
} }
void py_pushnil(){ void py_pushnil() {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
py_newnil(vm->stack.sp++); py_newnil(vm->stack.sp++);
} }
py_Ref py_pushtmp(){ py_Ref py_pushtmp() {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
py_newnil(vm->stack.sp++); py_newnil(vm->stack.sp++);
return py_gettop(); return py_gettop();

View File

@ -42,11 +42,21 @@ py_TValue* pk_arrayview(py_Ref self, int* length) {
} }
if(self->type == tp_tuple) { if(self->type == tp_tuple) {
*length = py_tuple__len(self); *length = py_tuple__len(self);
return py_tuple__getitem(self, 0); return PyObject__slots(self->_obj);
} }
return NULL; return NULL;
} }
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_eq(lhs + i, rhs + i);
if(res == -1) return -1;
if(!res) return false;
}
return true;
}
static void disassemble(CodeObject* co) { static void disassemble(CodeObject* co) {
c11_vector /*T=int*/ jumpTargets; c11_vector /*T=int*/ jumpTargets;
c11_vector__ctor(&jumpTargets, sizeof(int)); c11_vector__ctor(&jumpTargets, sizeof(int));

View File

@ -133,6 +133,25 @@ assert sorted(a, key=key) == [9, 8, 4, 2, 2]
assert sorted(a, key=key, reverse=True) == [2, 2, 4, 8, 9] assert sorted(a, key=key, reverse=True) == [2, 2, 4, 8, 9]
assert a == [8, 2, 4, 2, 9] assert a == [8, 2, 4, 2, 9]
# test unpack ex
a, *b = [1,2,3,4]
assert a == 1
assert b == [2,3,4]
a, b, *c = [1, 2]
assert a == 1
assert b == 2
assert c == []
a, b, c, *d = [1, 2, 3, 4, 5]
assert d == [4, 5]
# test repr
assert repr([1, 2, 3]) == "[1, 2, 3]"
assert repr([1, [2, 3], 4]) == "[1, [2, 3], 4]"
assert repr([1, [2, [3, 4]], 5]) == "[1, [2, [3, 4]], 5]"
assert repr([]) == "[]"
# b = [(1, 2), (3, 3), (5, 1)] # b = [(1, 2), (3, 3), (5, 1)]
# b.sort(key=lambda x:x[1]) # b.sort(key=lambda x:x[1])
# assert b == [(5, 1), (1, 2), (3,3)] # assert b == [(5, 1), (1, 2), (3,3)]

View File

@ -7,15 +7,9 @@ assert a == 2
assert b == 1 assert b == 1
assert len(tup) == 6 assert len(tup) == 6
# unpacking builder # empty tuple
a = 1, 2, 3
b = *a, 4, 5
assert b == (1, 2, 3, 4, 5)
a = tuple([]) a = tuple([])
b = *a, 1, 2, 3, *a, *a assert len(a) == 0
assert b == (1, 2, 3)
assert (1,) == tuple([1]) assert (1,) == tuple([1])
assert (1,2,) == tuple([1,2]) assert (1,2,) == tuple([1,2])
@ -31,3 +25,9 @@ assert l[32:] == tuple([])
assert l[1:4] == (2,3,4) assert l[1:4] == (2,3,4)
assert l[-1:-3] == tuple([]) assert l[-1:-3] == tuple([])
assert l[-3:-1] == (2,3) assert l[-3:-1] == (2,3)
# test repr
assert repr((1,)) == '(1,)'
assert repr((1,2,)) == '(1, 2)'
assert repr((1,2,(3,4))) == '(1, 2, (3, 4))'
assert repr(tuple()) == '()'