This commit is contained in:
blueloveTH 2024-07-07 13:00:42 +08:00
parent e4c8c47c2e
commit 400b8fbef4
11 changed files with 172 additions and 1175 deletions

View File

@ -42,7 +42,6 @@ typedef struct pk_VM {
pk_NameDict modules; pk_NameDict modules;
c11_vector /*T=pk_TypeInfo*/ types; c11_vector /*T=pk_TypeInfo*/ types;
py_TValue StopIteration; // a special Exception class
py_TValue builtins; // builtins module py_TValue builtins; // builtins module
py_TValue main; // __main__ module py_TValue main; // __main__ module
@ -53,6 +52,7 @@ typedef struct pk_VM {
py_TValue last_retval; py_TValue last_retval;
bool has_error; bool has_error;
bool is_stopiteration;
py_TValue reg[8]; // users' registers py_TValue reg[8]; // users' registers
@ -91,6 +91,7 @@ py_Type pk_VM__new_type(pk_VM* self,
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall); pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
const char* pk_opname(Opcode op); const char* pk_opname(Opcode op);
py_TValue* pk_arrayview(py_Ref self, int* size);
// type registration // type registration
void pk_object__register(); void pk_object__register();
@ -101,6 +102,8 @@ py_Type pk_bytes__register();
py_Type pk_list__register(); py_Type pk_list__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_iterator__register();
py_TValue pk_builtins__register(); py_TValue pk_builtins__register();

View File

@ -244,13 +244,14 @@ void py_formatexc(char* out);
#define TypeError(...) py_exception("TypeError", __VA_ARGS__) #define TypeError(...) py_exception("TypeError", __VA_ARGS__)
#define ValueError(...) py_exception("ValueError", __VA_ARGS__) #define ValueError(...) py_exception("ValueError", __VA_ARGS__)
#define IndexError(...) py_exception("IndexError", __VA_ARGS__) #define IndexError(...) py_exception("IndexError", __VA_ARGS__)
#define StopIteration() py_exception("StopIteration", "")
#define NotImplementedError() py_exception("NotImplementedError", "") #define NotImplementedError() py_exception("NotImplementedError", "")
#define AttributeError(self, n) \ #define AttributeError(self, n) \
py_exception("AttributeError", "'%t' object has no attribute '%n'", (self)->type, (n)) py_exception("AttributeError", "'%t' object has no attribute '%n'", (self)->type, (n))
#define UnboundLocalError(n) \ #define UnboundLocalError(n) \
py_exception("UnboundLocalError", "local variable '%n' referenced before assignment", (n)) py_exception("UnboundLocalError", "local variable '%n' referenced before assignment", (n))
bool StopIteration();
/************* Operators *************/ /************* Operators *************/
/// Equivalent to `bool(val)`. /// Equivalent to `bool(val)`.
/// Returns 1 if `val` is truthy, otherwise 0. /// Returns 1 if `val` is truthy, otherwise 0.
@ -385,6 +386,7 @@ enum py_PredefinedTypes {
tp_tuple, // N slots tp_tuple, // N slots
tp_slice, // 3 slots (start, stop, step) tp_slice, // 3 slots (start, stop, step)
tp_range, tp_range,
tp_range_iterator,
tp_module, tp_module,
tp_function, tp_function,
tp_nativefunc, tp_nativefunc,

View File

@ -6,6 +6,7 @@
#include <stdbool.h> #include <stdbool.h>
static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop); static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
static bool stack_unpack_sequence(pk_VM* self, uint16_t arg);
#define DISPATCH() \ #define DISPATCH() \
do { \ do { \
@ -32,7 +33,7 @@ static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
#define STACK_SHRINK(n) (self->stack.sp -= n) #define STACK_SHRINK(n) (self->stack.sp -= n)
#define PUSH(v) \ #define PUSH(v) \
do { \ do { \
*self->stack.sp = *v; \ *self->stack.sp = *(v); \
self->stack.sp++; \ self->stack.sp++; \
} while(0) } while(0)
#define POP() (--self->stack.sp) #define POP() (--self->stack.sp)
@ -693,6 +694,13 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
DISPATCH(); DISPATCH();
} }
//
case OP_UNPACK_SEQUENCE: {
if(!stack_unpack_sequence(self, byte.arg)) goto __ERROR;
DISPATCH();
}
/////////// ///////////
case OP_RAISE_ASSERT: { case OP_RAISE_ASSERT: {
if(byte.arg) { if(byte.arg) {
@ -755,4 +763,15 @@ bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) {
bool ok = stack_binaryop(self, op, rop); bool ok = stack_binaryop(self, op, rop);
STACK_SHRINK(2); STACK_SHRINK(2);
return ok; return ok;
} }
static bool stack_unpack_sequence(pk_VM* self, uint16_t arg) {
int length;
py_TValue* p = pk_arrayview(TOP(), &length);
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);
POP();
for(int i = 0; i < length; i++)
PUSH(p + i);
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,6 @@ void pk_VM__ctor(pk_VM* self) {
pk_NameDict__ctor(&self->modules); pk_NameDict__ctor(&self->modules);
c11_vector__ctor(&self->types, sizeof(pk_TypeInfo)); c11_vector__ctor(&self->types, sizeof(pk_TypeInfo));
self->StopIteration = PY_NIL;
self->builtins = PY_NIL; self->builtins = PY_NIL;
self->main = PY_NIL; self->main = PY_NIL;
@ -73,6 +72,7 @@ void pk_VM__ctor(pk_VM* self) {
self->last_retval = PY_NIL; self->last_retval = PY_NIL;
self->has_error = false; self->has_error = false;
self->is_stopiteration = false;
self->__curr_class = PY_NIL; self->__curr_class = PY_NIL;
self->__dynamic_func_decl = NULL; self->__dynamic_func_decl = NULL;
@ -102,7 +102,8 @@ void pk_VM__ctor(pk_VM* self) {
validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false)); validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false));
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_VM__new_type(self, "range", tp_object, NULL, false)); 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)); validate(tp_module, pk_VM__new_type(self, "module", tp_object, NULL, false));
validate(tp_function, pk_function__register()); validate(tp_function, pk_function__register());
@ -130,7 +131,6 @@ void pk_VM__ctor(pk_VM* self) {
validate(tp_stop_iteration, pk_VM__new_type(self, "StopIteration", tp_exception, NULL, false)); validate(tp_stop_iteration, pk_VM__new_type(self, "StopIteration", tp_exception, NULL, false));
#undef validate #undef validate
self->StopIteration = *py_tpobject(tp_stop_iteration);
self->builtins = pk_builtins__register(); self->builtins = pk_builtins__register();
/* Setup Public Builtin Types */ /* Setup Public Builtin Types */

View File

@ -117,11 +117,8 @@ static bool _py_builtins__next(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
int res = py_next(argv); int res = py_next(argv);
if(res == -1) return false; if(res == -1) return false;
if(res) { if(res) return true;
return true; return py_exception("StopIteration", "");
} else {
return StopIteration();
}
} }
py_TValue pk_builtins__register() { py_TValue pk_builtins__register() {

View File

@ -4,7 +4,7 @@
static bool _py_object__new__(int argc, py_Ref argv) { static bool _py_object__new__(int argc, py_Ref argv) {
assert(argc >= 1); assert(argc >= 1);
py_Type cls = argv[0].type; py_Type cls = py_totype(py_arg(0));
py_newobject(py_retval(), cls, 0, 0); py_newobject(py_retval(), cls, 0, 0);
return true; return true;
} }
@ -42,10 +42,24 @@ static bool _py_object__repr__(int argc, py_Ref argv) {
return true; return true;
} }
static bool _py_type__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
pk_sprintf(&buf, "<class '%t'>", py_totype(argv));
c11_string* res = c11_sbuf__submit(&buf);
py_newstrn(py_retval(), res->data, res->size);
c11_string__delete(res);
return true;
}
void pk_object__register() { void pk_object__register() {
py_bindmagic(tp_object, __new__, _py_object__new__); py_bindmagic(tp_object, __new__, _py_object__new__);
py_bindmagic(tp_object, __hash__, _py_object__hash__); py_bindmagic(tp_object, __hash__, _py_object__hash__);
py_bindmagic(tp_object, __eq__, _py_object__eq__); py_bindmagic(tp_object, __eq__, _py_object__eq__);
py_bindmagic(tp_object, __ne__, _py_object__ne__); py_bindmagic(tp_object, __ne__, _py_object__ne__);
py_bindmagic(tp_object, __repr__, _py_object__repr__); py_bindmagic(tp_object, __repr__, _py_object__repr__);
// type patch...
py_bindmagic(tp_type, __repr__, _py_type__repr__);
} }

View File

@ -67,15 +67,13 @@ bool py_iter(const py_Ref val) {
} }
int py_next(const 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__); py_Ref tmp = py_tpfindmagic(val->type, __next__);
if(!tmp) return TypeError("'%t' object is not an iterator", val->type); if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
bool ok = py_call(tmp, 1, val); bool ok = py_call(tmp, 1, val);
if(ok) { if(ok) return true;
py_Ref retval = py_retval(); return vm->is_stopiteration ? 0 : -1;
bool is_end = retval->type == tp_type && py_totype(retval) == tp_stop_iteration;
return !is_end;
}
return -1;
} }
int py_getattr(const py_Ref self, py_Name name, py_Ref out) { return -1; } int py_getattr(const py_Ref self, py_Name name, py_Ref out) { return -1; }

99
src/public/py_range.c Normal file
View File

@ -0,0 +1,99 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
typedef struct Range {
py_i64 start;
py_i64 stop;
py_i64 step;
} Range;
static bool _py_range__new__(int argc, py_Ref argv) {
Range* ud = py_newobject(py_retval(), tp_range, 0, sizeof(Range));
switch(argc - 1) { // skip cls
case 1: {
PY_CHECK_ARG_TYPE(1, tp_int);
ud->start = 0;
ud->stop = py_toint(py_arg(1));
ud->step = 1;
break;
}
case 2:
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
ud->start = py_toint(py_arg(1));
ud->stop = py_toint(py_arg(2));
ud->step = 1;
break;
case 3:
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
PY_CHECK_ARG_TYPE(3, tp_int);
ud->start = py_toint(py_arg(1));
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);
}
if(ud->step == 0) return ValueError("range() arg 3 must not be zero");
return true;
}
static bool _py_range__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_tpcall(tp_range_iterator, 1, argv);
}
py_Type pk_range__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "range", tp_object, NULL, false);
py_bindmagic(type, __new__, _py_range__new__);
py_bindmagic(type, __iter__, _py_range__iter__);
return type;
}
typedef struct RangeIterator {
Range range;
py_i64 current;
} RangeIterator;
static bool _py_range_iterator__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_range);
RangeIterator* ud = py_newobject(py_retval(), tp_range_iterator, 0, sizeof(RangeIterator));
ud->range = *(Range*)py_touserdata(py_arg(1));
ud->current = ud->range.start;
return true;
}
static bool _py_range_iterator__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
*py_retval() = *py_arg(0);
return true;
}
static bool _py_range_iterator__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
RangeIterator* ud = py_touserdata(py_arg(0));
if(ud->range.step > 0) {
if(ud->current >= ud->range.stop) return StopIteration();
} else {
if(ud->current <= ud->range.stop) return StopIteration();
}
py_newint(py_retval(), ud->current);
ud->current += ud->range.step;
return true;
}
py_Type pk_range_iterator__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "range_iterator", tp_object, NULL, false);
py_bindmagic(type, __new__, _py_range_iterator__new__);
py_bindmagic(type, __iter__, _py_range_iterator__iter__);
py_bindmagic(type, __next__, _py_range_iterator__next__);
return type;
}

View File

@ -521,10 +521,7 @@ static bool _py_str_iterator__next__(int argc, py_Ref argv) {
int* ud = py_touserdata(&argv[0]); int* ud = py_touserdata(&argv[0]);
int size; int size;
const char* data = py_tostrn(py_getslot(argv, 0), &size); const char* data = py_tostrn(py_getslot(argv, 0), &size);
if(*ud == size) { if(*ud == size) return StopIteration();
*py_retval() = pk_current_vm->StopIteration;
return true;
}
int start = *ud; int start = *ud;
int len = c11__u8_header(data[*ud], false); int len = c11__u8_header(data[*ud], false);
*ud += len; *ud += len;

View File

@ -35,6 +35,18 @@ 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__getitem(self, 0);
}
if(self->type == tp_tuple) {
*length = py_tuple__len(self);
return py_tuple__getitem(self, 0);
}
return NULL;
}
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));
@ -294,7 +306,7 @@ const char* py_tpname(py_Type type) {
return py_name2str(name); return py_name2str(name);
} }
bool py_tpcall(py_Type type, int argc, py_Ref argv){ bool py_tpcall(py_Type type, int argc, py_Ref argv) {
return py_call(py_tpobject(type), argc, argv); return py_call(py_tpobject(type), argc, argv);
} }
@ -305,3 +317,10 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv) {
if(!tmp) return AttributeError(argv, name); if(!tmp) return AttributeError(argv, name);
return py_call(tmp, argc, argv); return py_call(tmp, argc, argv);
} }
bool StopIteration() {
pk_VM* vm = pk_current_vm;
assert(!vm->is_stopiteration); // flag is already set
vm->is_stopiteration = true;
return false;
}