mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
some up
This commit is contained in:
parent
5be3300554
commit
cde78ea481
@ -63,8 +63,8 @@ typedef struct pk_VM {
|
||||
py_TValue last_retval;
|
||||
py_TValue reg[8]; // users' registers
|
||||
|
||||
PyObject* __curr_class;
|
||||
PyObject* __cached_object_new;
|
||||
py_TValue __curr_class;
|
||||
py_TValue __cached_object_new;
|
||||
FuncDecl_ __dynamic_func_decl;
|
||||
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||
|
||||
|
@ -29,7 +29,8 @@ typedef struct py_TValue{
|
||||
};
|
||||
} py_TValue;
|
||||
|
||||
static_assert(sizeof(py_TValue) <= 16, "!sizeof(py_TValue) <= 16");
|
||||
// 16 bytes to make py_arg() macro work
|
||||
static_assert(sizeof(py_TValue) == 16, "sizeof(py_TValue) != 16");
|
||||
|
||||
/* predefined vars */
|
||||
static const py_Type tp_object = {1}, tp_type = {2};
|
||||
|
@ -40,12 +40,12 @@ void py_newbool(py_Ref, bool);
|
||||
void py_newstr(py_Ref, const char*);
|
||||
void py_newstrn(py_Ref, const char*, int);
|
||||
// void py_newfstr(py_Ref, const char*, ...);
|
||||
// void py_newbytes(py_Ref, const uint8_t*, int);
|
||||
void py_newbytes(py_Ref, const unsigned char*, int);
|
||||
void py_newnone(py_Ref);
|
||||
void py_newnull(py_Ref);
|
||||
|
||||
void py_newtuple(py_Ref, int);
|
||||
// void py_newlist(py_Ref);
|
||||
void py_newtuple(py_Ref, int count);
|
||||
void py_newlist(py_Ref);
|
||||
|
||||
// new style decl-based function
|
||||
void py_newfunction(py_Ref out, py_CFunction, const char* sig);
|
||||
@ -101,6 +101,8 @@ bool py_istype(const py_Ref, py_Type);
|
||||
// bool py_issubclass(py_Type derived, py_Type base);
|
||||
|
||||
/************* References *************/
|
||||
#define py_arg(i) (py_Ref)((char*)argv+((i)<<4))
|
||||
|
||||
py_Ref py_getreg(int i);
|
||||
void py_setreg(int i, const py_Ref val);
|
||||
|
||||
@ -114,9 +116,13 @@ py_Ref py_getupvalue(py_Ref self);
|
||||
void py_setupvalue(py_Ref self, const py_Ref val);
|
||||
|
||||
/// Gets the attribute of the object.
|
||||
int py_getattr(const py_Ref self, py_Name name, py_Ref out);
|
||||
bool py_getattr(const py_Ref self, py_Name name, py_Ref out);
|
||||
/// Gets the unbound method of the object.
|
||||
bool py_getunboundmethod(const py_Ref self, py_Name name, bool fallback, py_Ref out, py_Ref out_self);
|
||||
/// Sets the attribute of the object.
|
||||
int py_setattr(py_Ref self, py_Name name, const py_Ref val);
|
||||
/// Deletes the attribute of the object.
|
||||
int py_delattr(py_Ref self, py_Name name);
|
||||
|
||||
/// Equivalent to `*dst = *src`.
|
||||
void py_assign(py_Ref dst, const py_Ref src);
|
||||
@ -193,6 +199,10 @@ void py_dict__setitem(py_Ref self, const py_Ref key, const py_Ref val);
|
||||
void py_dict__delitem(py_Ref self, const py_Ref key);
|
||||
void py_dict__clear(py_Ref self);
|
||||
|
||||
// internal functions
|
||||
typedef struct pk_TypeInfo pk_TypeInfo;
|
||||
pk_TypeInfo* pk_tpinfo(const py_Ref self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -29,14 +29,12 @@ OPCODE(LOAD_ATTR)
|
||||
OPCODE(LOAD_CLASS_GLOBAL)
|
||||
OPCODE(LOAD_METHOD)
|
||||
OPCODE(LOAD_SUBSCR)
|
||||
OPCODE(LOAD_SUBSCR_FAST)
|
||||
|
||||
OPCODE(STORE_FAST)
|
||||
OPCODE(STORE_NAME)
|
||||
OPCODE(STORE_GLOBAL)
|
||||
OPCODE(STORE_ATTR)
|
||||
OPCODE(STORE_SUBSCR)
|
||||
OPCODE(STORE_SUBSCR_FAST)
|
||||
|
||||
OPCODE(DELETE_FAST)
|
||||
OPCODE(DELETE_NAME)
|
||||
|
@ -1001,26 +1001,14 @@ void SubscrExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||
SubscrExpr* self = (SubscrExpr*)self_;
|
||||
vtemit_(self->lhs, ctx);
|
||||
vtemit_(self->rhs, ctx);
|
||||
Bytecode last_bc = c11_vector__back(Bytecode, &ctx->co->codes);
|
||||
if(self->rhs->vt->is_name && last_bc.op == OP_LOAD_FAST) {
|
||||
Ctx__revert_last_emit_(ctx);
|
||||
Ctx__emit_(ctx, OP_LOAD_SUBSCR_FAST, last_bc.arg, self->line);
|
||||
} else {
|
||||
Ctx__emit_(ctx, OP_LOAD_SUBSCR, BC_NOARG, self->line);
|
||||
}
|
||||
}
|
||||
|
||||
bool SubscrExpr__emit_store(Expr* self_, Ctx* ctx) {
|
||||
SubscrExpr* self = (SubscrExpr*)self_;
|
||||
vtemit_(self->lhs, ctx);
|
||||
vtemit_(self->rhs, ctx);
|
||||
Bytecode last_bc = c11_vector__back(Bytecode, &ctx->co->codes);
|
||||
if(self->rhs->vt->is_name && last_bc.op == OP_LOAD_FAST) {
|
||||
Ctx__revert_last_emit_(ctx);
|
||||
Ctx__emit_(ctx, OP_STORE_SUBSCR_FAST, last_bc.arg, self->line);
|
||||
} else {
|
||||
Ctx__emit_(ctx, OP_STORE_SUBSCR, BC_NOARG, self->line);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@ int UnboundLocalError(py_Name name) { return -1; }
|
||||
|
||||
int NameError(py_Name name) { return -1; }
|
||||
|
||||
#define AttributeError(obj, name)
|
||||
|
||||
#define DISPATCH() \
|
||||
do { \
|
||||
frame->ip++; \
|
||||
@ -26,15 +28,39 @@ int NameError(py_Name name) { return -1; }
|
||||
|
||||
/* Stack manipulation macros */
|
||||
// https://github.com/python/cpython/blob/3.9/Python/ceval.c#L1123
|
||||
#define TOP() self->stack.sp[-1]
|
||||
#define SECOND() self->stack.sp[-2]
|
||||
#define THIRD() self->stack.sp[-3]
|
||||
#define TOP() (self->stack.sp - 1)
|
||||
#define SECOND() (self->stack.sp - 2)
|
||||
#define THIRD() (self->stack.sp - 3)
|
||||
#define FOURTH() (self->stack.sp - 4)
|
||||
#define STACK_SHRINK(n) (self->stack.sp -= n)
|
||||
#define PUSH(v) (*self->stack.sp++ = v)
|
||||
#define PUSH(v) (*self->stack.sp++ = *v)
|
||||
#define POP() (--self->stack.sp)
|
||||
#define POPX() (*--self->stack.sp)
|
||||
#define SP() (self->stack.sp)
|
||||
|
||||
static void pack_stack_values(int n) {
|
||||
assert(n > 1);
|
||||
pk_VM* self = pk_current_vm;
|
||||
py_TValue tmp;
|
||||
py_newtuple(&tmp, n);
|
||||
for(int i = 0; i < n; i++)
|
||||
py_tuple__setitem(&tmp, i, SP() - n + i);
|
||||
STACK_SHRINK(n);
|
||||
PUSH(&tmp);
|
||||
}
|
||||
|
||||
// n == 1 is the most likely result
|
||||
#define HANDLE_RETVAL(n) \
|
||||
if(n != 1) { \
|
||||
if(n == 0) { \
|
||||
PUSH(&self->None); \
|
||||
} else if(n > 1) { \
|
||||
pack_stack_values(n); \
|
||||
} else { \
|
||||
goto __ERROR; \
|
||||
} \
|
||||
}
|
||||
|
||||
pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
Frame* frame = self->top_frame;
|
||||
const Frame* base_frame = frame;
|
||||
@ -72,39 +98,37 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
PUSH(SECOND()); // [a, b, a, b]
|
||||
DISPATCH();
|
||||
case OP_ROT_TWO: {
|
||||
py_TValue tmp = TOP();
|
||||
TOP() = SECOND();
|
||||
SECOND() = tmp;
|
||||
py_TValue tmp = *TOP();
|
||||
*TOP() = *SECOND();
|
||||
*SECOND() = tmp;
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_ROT_THREE: {
|
||||
// [a, b, c] -> [c, a, b]
|
||||
py_TValue _0 = TOP();
|
||||
TOP() = SECOND();
|
||||
SECOND() = THIRD();
|
||||
THIRD() = _0;
|
||||
py_TValue tmp = *TOP();
|
||||
*TOP() = *SECOND();
|
||||
*SECOND() = *THIRD();
|
||||
*THIRD() = tmp;
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_PRINT_EXPR:
|
||||
if(TOP().type != tp_none_type) {
|
||||
int err = py_repr(&TOP());
|
||||
if(TOP()->type != tp_none_type) {
|
||||
int err = py_repr(TOP());
|
||||
if(err) goto __ERROR;
|
||||
self->_stdout("%s\n", py_tostr(&TOP()));
|
||||
self->_stdout("%s\n", py_tostr(TOP()));
|
||||
POP();
|
||||
}
|
||||
POP();
|
||||
DISPATCH();
|
||||
/*****************************************/
|
||||
case OP_LOAD_CONST:
|
||||
PUSH(c11__getitem(py_TValue, &frame->co->consts, byte.arg));
|
||||
DISPATCH();
|
||||
case OP_LOAD_NONE: PUSH(self->None); DISPATCH();
|
||||
case OP_LOAD_TRUE: PUSH(self->True); DISPATCH();
|
||||
case OP_LOAD_FALSE: PUSH(self->False); DISPATCH();
|
||||
case OP_LOAD_CONST: PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg)); DISPATCH();
|
||||
case OP_LOAD_NONE: PUSH(&self->None); DISPATCH();
|
||||
case OP_LOAD_TRUE: PUSH(&self->True); DISPATCH();
|
||||
case OP_LOAD_FALSE: PUSH(&self->False); DISPATCH();
|
||||
/*****************************************/
|
||||
case OP_LOAD_SMALL_INT: py_newint(SP()++, (int64_t)(int16_t)byte.arg); DISPATCH();
|
||||
/*****************************************/
|
||||
case OP_LOAD_ELLIPSIS: PUSH(self->Ellipsis); DISPATCH();
|
||||
case OP_LOAD_ELLIPSIS: PUSH(&self->Ellipsis); DISPATCH();
|
||||
case OP_LOAD_FUNCTION: {
|
||||
// FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
|
||||
// py_TValue obj;
|
||||
@ -126,8 +150,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
DISPATCH();
|
||||
/*****************************************/
|
||||
case OP_LOAD_FAST: {
|
||||
PUSH(frame->locals[byte.arg]);
|
||||
if(py_isnull(&TOP())) {
|
||||
PUSH(&frame->locals[byte.arg]);
|
||||
if(py_isnull(TOP())) {
|
||||
py_Name name = c11__getitem(uint16_t, &frame->co->varnames, byte.arg);
|
||||
UnboundLocalError(name);
|
||||
goto __ERROR;
|
||||
@ -142,22 +166,22 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
UnboundLocalError(name);
|
||||
goto __ERROR;
|
||||
}
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = Frame__f_closure_try_get(frame, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = Frame__f_globals_try_get(frame, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = py_getdict(&self->builtins, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
NameError(name);
|
||||
@ -167,17 +191,17 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
py_Name name = byte.arg;
|
||||
py_Ref tmp = Frame__f_closure_try_get(frame, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = Frame__f_globals_try_get(frame, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = py_getdict(&self->builtins, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
NameError(name);
|
||||
@ -187,27 +211,203 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
py_Name name = byte.arg;
|
||||
py_Ref tmp = Frame__f_globals_try_get(frame, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = py_getdict(&self->builtins, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(*tmp);
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
NameError(name);
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_LOAD_ATTR: {
|
||||
int err = py_getattr(&TOP(), byte.arg, &TOP());
|
||||
if(err) goto __ERROR;
|
||||
if(!py_getattr(TOP(), byte.arg, TOP())) {
|
||||
AttributeError(TOP(), byte.arg);
|
||||
goto __ERROR;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
/*******************/
|
||||
case OP_LOAD_CLASS_GLOBAL: {
|
||||
assert(self->__curr_class.type);
|
||||
py_Name name = byte.arg;
|
||||
if(py_getattr(&self->__curr_class, name, SP())) {
|
||||
SP()++;
|
||||
DISPATCH();
|
||||
}
|
||||
// load global if attribute not found
|
||||
py_Ref tmp = Frame__f_globals_try_get(frame, name);
|
||||
if(tmp) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = py_getdict(&self->builtins, name);
|
||||
if(tmp) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
NameError(name);
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_LOAD_METHOD: {
|
||||
// `py_getunboundmethod` never fails on `fallback=true`
|
||||
py_getunboundmethod(TOP(), byte.arg, true, TOP(), SP());
|
||||
SP()++;
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_LOAD_SUBSCR: {
|
||||
// [a, b] -> a[b]
|
||||
int n = py_callmethod(SECOND(), __getitem__, TOP());
|
||||
HANDLE_RETVAL(n);
|
||||
// [a, b, retval]
|
||||
*THIRD() = *TOP(); // [retval, b, retval]
|
||||
STACK_SHRINK(2); // [retval]
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH();
|
||||
case OP_STORE_NAME: {
|
||||
py_Name _name = byte.arg;
|
||||
py_TValue _0 = POPX();
|
||||
if(frame->function) {
|
||||
py_Ref slot = Frame__f_locals_try_get(frame, _name);
|
||||
if(slot != NULL) {
|
||||
*slot = _0; // store in locals if possible
|
||||
} else {
|
||||
// Function& func = frame->_callable->as<Function>();
|
||||
// if(func.decl == __dynamic_func_decl) {
|
||||
// assert(func._closure != nullptr);
|
||||
// func._closure->set(_name, _0);
|
||||
// } else {
|
||||
// NameError(_name);
|
||||
// goto __ERROR;
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
pk_NameDict__set(Frame__f_globals(frame), _name, _0);
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_STORE_GLOBAL:
|
||||
pk_NameDict__set(Frame__f_globals(frame), byte.arg, POPX());
|
||||
DISPATCH();
|
||||
|
||||
// ...
|
||||
case OP_STORE_ATTR: {
|
||||
int err = py_setattr(TOP(), byte.arg, SECOND());
|
||||
if(err) goto __ERROR;
|
||||
STACK_SHRINK(2);
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_STORE_SUBSCR: {
|
||||
// [val, a, b] -> a[b] = val
|
||||
py_TValue* backup = SP();
|
||||
PUSH(THIRD()); // [val, a, b, val]
|
||||
bool ok = py_getunboundmethod(THIRD(), __setitem__, false, FOURTH(), THIRD());
|
||||
if(!ok) {
|
||||
// __setitem__ not found
|
||||
goto __ERROR;
|
||||
}
|
||||
// [__setitem__, self, b, val]
|
||||
int n = py_vectorcall(3, 0);
|
||||
if(n < 0) goto __ERROR;
|
||||
SP() = backup; // discard retval if any
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_DELETE_FAST: {
|
||||
py_Ref tmp = &frame->locals[byte.arg];
|
||||
if(py_isnull(tmp)) {
|
||||
UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
|
||||
goto __ERROR;
|
||||
}
|
||||
py_newnull(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_DELETE_NAME: {
|
||||
StrName name = byte.arg;
|
||||
if(frame->function) {
|
||||
py_TValue* slot = Frame__f_locals_try_get(frame, name);
|
||||
if(slot) {
|
||||
py_newnull(slot);
|
||||
} else {
|
||||
// Function& func = frame->_callable->as<Function>();
|
||||
// if(func.decl == __dynamic_func_decl) {
|
||||
// assert(func._closure != nullptr);
|
||||
// bool ok = func._closure->del(_name);
|
||||
// if(!ok) vm->NameError(_name);
|
||||
// } else {
|
||||
// vm->NameError(_name);
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
// if(!frame->f_globals().del(_name)) vm->NameError(_name);
|
||||
bool ok = pk_NameDict__del(Frame__f_globals(frame), name);
|
||||
if(!ok) {
|
||||
NameError(name);
|
||||
goto __ERROR;
|
||||
}
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_DELETE_GLOBAL: {
|
||||
StrName name = byte.arg;
|
||||
bool ok = pk_NameDict__del(Frame__f_globals(frame), name);
|
||||
if(!ok) {
|
||||
NameError(name);
|
||||
goto __ERROR;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
/*******************/
|
||||
case OP_DELETE_ATTR: {
|
||||
int err = py_delattr(TOP(), byte.arg);
|
||||
if(err) goto __ERROR;
|
||||
POP();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
case OP_DELETE_SUBSCR: {
|
||||
// [a, b] -> del a[b]
|
||||
py_Ref backup = SP();
|
||||
int n = py_callmethod(SECOND(), __delitem__, TOP());
|
||||
if(n < 0) { goto __ERROR; }
|
||||
SP() = backup; // discard retval if any
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
/*****************************************/
|
||||
|
||||
case OP_BUILD_LONG: {
|
||||
py_Ref _0 = py_getdict(&self->builtins, pk_id_long);
|
||||
assert(_0 != NULL);
|
||||
int n = py_call(_0, TOP());
|
||||
if(n < 0) goto __ERROR;
|
||||
assert(n == 1);
|
||||
// [x, long(x)]
|
||||
*SECOND() = *TOP(); // [long(x), long(x)]
|
||||
POP(); // [long(x)]
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
case OP_BUILD_IMAG: {
|
||||
py_Ref _0 = py_getdict(&self->builtins, pk_id_complex);
|
||||
assert(_0 != NULL);
|
||||
py_TValue zero;
|
||||
py_newint(&zero, 0);
|
||||
int n = py_call(_0, &zero, TOP());
|
||||
if(n < 0) goto __ERROR;
|
||||
assert(n == 1);
|
||||
// [x, complex(0, x)]
|
||||
*SECOND() = *TOP(); // [complex(0, x), complex(0, x)]
|
||||
POP(); // [complex(0, x)]
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_BUILD_BYTES: {
|
||||
py_Str* s = py_touserdata(TOP());
|
||||
unsigned char* p = (unsigned char*)malloc(s->size);
|
||||
memcpy(p, py_Str__data(s), s->size);
|
||||
py_newbytes(SP()++, p, s->size);
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_BUILD_TUPLE: {
|
||||
py_TValue tmp;
|
||||
py_newtuple(&tmp, byte.arg);
|
||||
@ -216,9 +416,49 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
py_tuple__setitem(&tmp, i, begin + i);
|
||||
}
|
||||
SP() = begin;
|
||||
PUSH(tmp);
|
||||
PUSH(&tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
// case OP_BUILD_LIST: {
|
||||
// PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
// STACK_SHRINK(byte.arg);
|
||||
// PUSH(_0);
|
||||
// DISPATCH();
|
||||
// }
|
||||
// case OP_BUILD_DICT: {
|
||||
// if(byte.arg == 0) {
|
||||
// PUSH(VAR(Dict()));
|
||||
// DISPATCH()
|
||||
// }
|
||||
// PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
// _0 = call(_t(tp_dict), _0);
|
||||
// STACK_SHRINK(byte.arg);
|
||||
// PUSH(_0);
|
||||
// DISPATCH();
|
||||
// }
|
||||
// case OP_BUILD_SET: {
|
||||
// PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
// _0 = call(builtins->attr()[pk_id_set], _0);
|
||||
// STACK_SHRINK(byte.arg);
|
||||
// PUSH(_0);
|
||||
// DISPATCH();
|
||||
// }
|
||||
// case OP_BUILD_SLICE: {
|
||||
// PyVar _2 = POPX(); // step
|
||||
// PyVar _1 = POPX(); // stop
|
||||
// PyVar _0 = POPX(); // start
|
||||
// PUSH(VAR(Slice(_0, _1, _2)));
|
||||
// DISPATCH();
|
||||
// }
|
||||
// case OP_BUILD_STRING: {
|
||||
// SStream ss;
|
||||
// ArgsView view = STACK_VIEW(byte.arg);
|
||||
// for(PyVar obj: view)
|
||||
// ss << py_str(obj);
|
||||
// STACK_SHRINK(byte.arg);
|
||||
// PUSH(VAR(ss.str()));
|
||||
// DISPATCH();
|
||||
// }
|
||||
/**************************** */
|
||||
case OP_RETURN_VALUE: {
|
||||
py_TValue tmp = byte.arg == BC_NOARG ? POPX() : self->None;
|
||||
@ -228,7 +468,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
return RES_RETURN;
|
||||
} else {
|
||||
frame = self->top_frame;
|
||||
PUSH(tmp);
|
||||
PUSH(&tmp);
|
||||
goto __NEXT_FRAME;
|
||||
}
|
||||
DISPATCH();
|
||||
|
@ -175,7 +175,7 @@ static int _py_int__invert__(int argc, py_Ref argv) {
|
||||
}
|
||||
|
||||
static int _py_int__bit_length(int argc, py_Ref argv) {
|
||||
int64_t x = py_toint(&argv[0]);
|
||||
int64_t x = py_toint(py_arg(0));
|
||||
if(x < 0) x = -x;
|
||||
int bits = 0;
|
||||
while(x) {
|
||||
|
@ -58,8 +58,8 @@ void pk_VM__ctor(pk_VM* self){
|
||||
self->last_error = NULL;
|
||||
self->last_retval = PY_NULL;
|
||||
|
||||
self->__curr_class = NULL;
|
||||
self->__cached_object_new = NULL;
|
||||
self->__curr_class = PY_NULL;
|
||||
self->__cached_object_new = PY_NULL;
|
||||
self->__dynamic_func_decl = NULL;
|
||||
|
||||
pk_ManagedHeap__ctor(&self->heap, self);
|
||||
|
@ -15,14 +15,14 @@ int py_repr(const py_Ref val) {
|
||||
return py_callmethod(val, __repr__);
|
||||
}
|
||||
|
||||
int py_getattr(const py_Ref self, py_Name name, py_Ref out){
|
||||
return -1;
|
||||
bool py_getattr(const py_Ref self, py_Name name, py_Ref out){
|
||||
return true;
|
||||
}
|
||||
|
||||
int py_setattr(py_Ref self, py_Name name, const py_Ref val){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int py_callmethod(py_Ref self, py_Name name, ...){
|
||||
int py_delattr(py_Ref self, py_Name name){
|
||||
return -1;
|
||||
}
|
@ -39,6 +39,18 @@ void py_newstrn(py_Ref out, const char* data, int size) {
|
||||
out->_obj = obj;
|
||||
}
|
||||
|
||||
void py_newbytes(py_Ref out, const unsigned char* data, int size) {
|
||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||
// 4 bytes size + data
|
||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_bytes, 0, sizeof(int) + size);
|
||||
int* psize = (int*)PyObject__value(obj);
|
||||
*psize = size;
|
||||
memcpy(psize + 1, data, size);
|
||||
out->type = tp_bytes;
|
||||
out->is_ptr = true;
|
||||
out->_obj = obj;
|
||||
}
|
||||
|
||||
void py_newnone(py_Ref out) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
*out = vm->None;
|
||||
|
@ -46,3 +46,19 @@ int py_eval(const char* source, py_Ref out) {
|
||||
}
|
||||
PK_UNREACHABLE();
|
||||
}
|
||||
|
||||
int py_call(py_Ref callable, ...){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int py_callmethod(py_Ref self, py_Name name, ...){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int py_vectorcall(int argc, int kwargc){
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool py_getunboundmethod(const py_Ref self, py_Name name, bool fallback, py_Ref out, py_Ref out_self){
|
||||
return -1;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user