This commit is contained in:
blueloveTH 2024-07-08 20:42:50 +08:00 committed by blueloveTH
parent fa5df75248
commit 40d6f1a19f
12 changed files with 160 additions and 34 deletions

View File

@ -108,6 +108,8 @@ py_Type pk_str_iterator__register();
py_Type pk_bytes__register();
py_Type pk_list__register();
py_Type pk_tuple__register();
py_Type pk_array_iterator__register();
py_Type pk_slice__register();
py_Type pk_function__register();
py_Type pk_nativefunc__register();
py_Type pk_range__register();

View File

@ -88,7 +88,7 @@ bool py_ismagicname(py_Name);
// opaque types
void py_newdict(py_Ref);
void py_newset(py_Ref);
void py_newslice(py_Ref, const py_Ref start, const py_Ref stop, const py_Ref step);
void py_newslice(py_Ref);
// old style argc-based function
void py_newnativefunc(py_Ref out, py_CFunction);
@ -400,6 +400,7 @@ enum py_PredefinedTypes {
tp_str_iterator,
tp_list, // c11_vector
tp_tuple, // N slots
tp_array_iterator,
tp_slice, // 3 slots (start, stop, step)
tp_range,
tp_range_iterator,

View File

@ -531,7 +531,10 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
case OP_BUILD_SLICE: {
// [start, stop, step]
py_TValue tmp;
py_newslice(&tmp, THIRD(), SECOND(), TOP());
py_newslice(&tmp);
py_setslot(&tmp, 0, THIRD());
py_setslot(&tmp, 1, SECOND());
py_setslot(&tmp, 2, TOP());
STACK_SHRINK(3);
PUSH(&tmp);
DISPATCH();

View File

@ -100,8 +100,9 @@ void pk_VM__ctor(pk_VM* self) {
validate(tp_list, pk_list__register());
validate(tp_tuple, pk_tuple__register());
validate(tp_array_iterator, pk_array_iterator__register());
validate(tp_slice, pk_VM__new_type(self, "slice", tp_object, NULL, false));
validate(tp_slice, pk_slice__register());
validate(tp_range, pk_range__register());
validate(tp_range_iterator, pk_range_iterator__register());
validate(tp_module, pk_VM__new_type(self, "module", tp_object, NULL, false));

75
src/public/py_array.c Normal file
View File

@ -0,0 +1,75 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/common/sstream.h"
typedef struct array_iterator {
py_TValue* p;
int length;
int index;
} array_iterator;
py_TValue* pk_arrayview(py_Ref self, int* length) {
if(self->type == tp_list) {
*length = py_list__len(self);
return py_list__data(self);
}
if(self->type == tp_tuple) {
*length = py_tuple__len(self);
return PyObject__slots(self->_obj);
}
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 bool _py_array_iterator__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
int length;
py_TValue* p = pk_arrayview(py_arg(1), &length);
if(!p) return TypeError("expected list or tuple, got %t", py_arg(1)->type);
array_iterator* ud = py_newobject(py_retval(), tp_array_iterator, 1, sizeof(array_iterator));
ud->p = p;
ud->length = length;
ud->index = 0;
// keep a reference to the object
py_setslot(py_retval(), 0, py_arg(1));
return true;
}
static bool _py_array_iterator__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
*py_retval() = *argv;
return true;
}
static bool _py_array_iterator__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
array_iterator* ud = py_touserdata(argv);
if(ud->index < ud->length) {
*py_retval() = ud->p[ud->index++];
return true;
}
return StopIteration();
}
py_Type pk_array_iterator__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "array_iterator", tp_object, NULL, false);
py_bindmagic(type, __new__, _py_array_iterator__new__);
py_bindmagic(type, __iter__, _py_array_iterator__iter__);
py_bindmagic(type, __next__, _py_array_iterator__next__);
return type;
}

View File

@ -386,6 +386,11 @@ static bool _py_list__sort(int argc, py_Ref argv) {
return true;
}
static bool _py_list__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_tpcall(tp_array_iterator, 1, argv);
}
py_Type pk_list__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false);
@ -403,6 +408,7 @@ py_Type pk_list__register() {
py_bindmagic(type, __mul__, _py_list__mul__);
py_bindmagic(type, __rmul__, _py_list__rmul__);
py_bindmagic(type, __repr__, _py_list__repr__);
py_bindmagic(type, __iter__, _py_list__iter__);
py_bindmethod(type, "append", _py_list__append);
py_bindmethod(type, "extend", _py_list__extend);

View File

@ -35,9 +35,9 @@ static bool _py_range__new__(int argc, py_Ref argv) {
ud->stop = py_toint(py_arg(2));
ud->step = py_toint(py_arg(3));
break;
default: return TypeError("range() expected at most 3 arguments, got %d", argc - 1);
default: return TypeError("range() expected at most 4 arguments, got %d", argc);
}
if(ud->step == 0) return ValueError("range() arg 3 must not be zero");
if(ud->step == 0) return ValueError("range() step must not be zero");
return true;
}

55
src/public/py_slice.c Normal file
View File

@ -0,0 +1,55 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/common/sstream.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
void py_newslice(py_Ref out){
pk_VM* vm = pk_current_vm;
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_slice, 3, 0);
out->type = tp_slice;
out->is_ptr = true;
out->_obj = obj;
}
static bool _py_slice__new__(int argc, py_Ref argv){
PY_CHECK_ARGC(1+3);
py_Ref slice = py_retval();
py_newslice(slice);
py_setslot(slice, 0, py_arg(1));
py_setslot(slice, 1, py_arg(2));
py_setslot(slice, 2, py_arg(3));
return true;
}
static bool _py_slice__repr__(int argc, py_Ref argv){
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_cstr(&buf, "slice(");
for(int i = 0; i < 3; i++) {
py_TValue* val = py_getslot(argv, i);
bool ok = py_repr(val);
if(!ok) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
if(i != 2) 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;
}
py_Type pk_slice__register(){
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "slice", tp_object, NULL, false);
py_bindmagic(type, __new__, _py_slice__new__);
py_bindmagic(type, __repr__, _py_slice__repr__);
return type;
}

View File

@ -44,6 +44,12 @@ const char* py_tostrn(const py_Ref self, int* size) {
return ud->data;
}
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(const py_Ref self, int* size) {
assert(self->type == tp_bytes);
c11_bytes* ud = PyObject__userdata(self->_obj);

View File

@ -120,6 +120,11 @@ static bool _py_tuple__ne__(int argc, py_Ref argv) {
return true;
}
static bool _py_tuple__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_tpcall(tp_array_iterator, 1, argv);
}
py_Type pk_tuple__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "tuple", tp_object, NULL, false);
@ -130,5 +135,6 @@ py_Type pk_tuple__register() {
py_bindmagic(type, __getitem__, _py_tuple__getitem__);
py_bindmagic(type, __eq__, _py_tuple__eq__);
py_bindmagic(type, __ne__, _py_tuple__ne__);
py_bindmagic(type, __iter__, _py_tuple__iter__);
return type;
}

View File

@ -88,13 +88,6 @@ void py_bind(py_Ref obj, const char* sig, py_CFunction f) {
py_setdict(obj, name, &tmp);
}
void py_newslice(py_Ref out, const py_Ref start, const py_Ref stop, const py_Ref step) {
py_newobject(out, tp_slice, 3, 0);
py_setslot(out, 0, start);
py_setslot(out, 1, stop);
py_setslot(out, 2, step);
}
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize) {
pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize);

View File

@ -35,28 +35,6 @@ const char* pk_opname(Opcode op) {
return OP_NAMES[op];
}
py_TValue* pk_arrayview(py_Ref self, int* length) {
if(self->type == tp_list) {
*length = py_list__len(self);
return py_list__data(self);
}
if(self->type == tp_tuple) {
*length = py_tuple__len(self);
return PyObject__slots(self->_obj);
}
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) {
c11_vector /*T=int*/ jumpTargets;
c11_vector__ctor(&jumpTargets, sizeof(int));