mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
...
This commit is contained in:
parent
a81563768d
commit
140255650d
@ -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();
|
||||||
|
@ -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')
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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));
|
||||||
|
@ -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)]
|
||||||
|
@ -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()) == '()'
|
Loading…
x
Reference in New Issue
Block a user