mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
...
This commit is contained in:
parent
fa5df75248
commit
40d6f1a19f
@ -108,6 +108,8 @@ 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_tuple__register();
|
||||||
|
py_Type pk_array_iterator__register();
|
||||||
|
py_Type pk_slice__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();
|
||||||
|
@ -88,7 +88,7 @@ bool py_ismagicname(py_Name);
|
|||||||
// opaque types
|
// opaque types
|
||||||
void py_newdict(py_Ref);
|
void py_newdict(py_Ref);
|
||||||
void py_newset(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
|
// old style argc-based function
|
||||||
void py_newnativefunc(py_Ref out, py_CFunction);
|
void py_newnativefunc(py_Ref out, py_CFunction);
|
||||||
|
|
||||||
@ -400,6 +400,7 @@ enum py_PredefinedTypes {
|
|||||||
tp_str_iterator,
|
tp_str_iterator,
|
||||||
tp_list, // c11_vector
|
tp_list, // c11_vector
|
||||||
tp_tuple, // N slots
|
tp_tuple, // N slots
|
||||||
|
tp_array_iterator,
|
||||||
tp_slice, // 3 slots (start, stop, step)
|
tp_slice, // 3 slots (start, stop, step)
|
||||||
tp_range,
|
tp_range,
|
||||||
tp_range_iterator,
|
tp_range_iterator,
|
||||||
|
@ -531,7 +531,10 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
case OP_BUILD_SLICE: {
|
case OP_BUILD_SLICE: {
|
||||||
// [start, stop, step]
|
// [start, stop, step]
|
||||||
py_TValue tmp;
|
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);
|
STACK_SHRINK(3);
|
||||||
PUSH(&tmp);
|
PUSH(&tmp);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -100,8 +100,9 @@ void pk_VM__ctor(pk_VM* self) {
|
|||||||
|
|
||||||
validate(tp_list, pk_list__register());
|
validate(tp_list, pk_list__register());
|
||||||
validate(tp_tuple, pk_tuple__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, pk_range__register());
|
||||||
validate(tp_range_iterator, pk_range_iterator__register());
|
validate(tp_range_iterator, pk_range_iterator__register());
|
||||||
validate(tp_module, pk_VM__new_type(self, "module", tp_object, NULL, false));
|
validate(tp_module, pk_VM__new_type(self, "module", tp_object, NULL, false));
|
||||||
|
75
src/public/py_array.c
Normal file
75
src/public/py_array.c
Normal 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;
|
||||||
|
}
|
@ -386,6 +386,11 @@ static bool _py_list__sort(int argc, py_Ref argv) {
|
|||||||
return true;
|
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() {
|
py_Type pk_list__register() {
|
||||||
pk_VM* vm = pk_current_vm;
|
pk_VM* vm = pk_current_vm;
|
||||||
py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false);
|
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, __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_bindmagic(type, __repr__, _py_list__repr__);
|
||||||
|
py_bindmagic(type, __iter__, _py_list__iter__);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -35,9 +35,9 @@ static bool _py_range__new__(int argc, py_Ref argv) {
|
|||||||
ud->stop = py_toint(py_arg(2));
|
ud->stop = py_toint(py_arg(2));
|
||||||
ud->step = py_toint(py_arg(3));
|
ud->step = py_toint(py_arg(3));
|
||||||
break;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
src/public/py_slice.c
Normal file
55
src/public/py_slice.c
Normal 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;
|
||||||
|
}
|
@ -44,6 +44,12 @@ const char* py_tostrn(const py_Ref self, int* size) {
|
|||||||
return ud->data;
|
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) {
|
unsigned char* py_tobytes(const py_Ref self, int* size) {
|
||||||
assert(self->type == tp_bytes);
|
assert(self->type == tp_bytes);
|
||||||
c11_bytes* ud = PyObject__userdata(self->_obj);
|
c11_bytes* ud = PyObject__userdata(self->_obj);
|
||||||
|
@ -120,6 +120,11 @@ static bool _py_tuple__ne__(int argc, py_Ref argv) {
|
|||||||
return true;
|
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() {
|
py_Type pk_tuple__register() {
|
||||||
pk_VM* vm = pk_current_vm;
|
pk_VM* vm = pk_current_vm;
|
||||||
py_Type type = pk_VM__new_type(vm, "tuple", tp_object, NULL, false);
|
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, __getitem__, _py_tuple__getitem__);
|
||||||
py_bindmagic(type, __eq__, _py_tuple__eq__);
|
py_bindmagic(type, __eq__, _py_tuple__eq__);
|
||||||
py_bindmagic(type, __ne__, _py_tuple__ne__);
|
py_bindmagic(type, __ne__, _py_tuple__ne__);
|
||||||
|
py_bindmagic(type, __iter__, _py_tuple__iter__);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -88,13 +88,6 @@ void py_bind(py_Ref obj, const char* sig, py_CFunction f) {
|
|||||||
py_setdict(obj, name, &tmp);
|
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) {
|
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize) {
|
||||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize);
|
PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize);
|
||||||
|
@ -35,28 +35,6 @@ const char* pk_opname(Opcode op) {
|
|||||||
return OP_NAMES[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) {
|
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));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user