mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
some fix
This commit is contained in:
parent
36b3c9ff8f
commit
c954431442
@ -18,10 +18,8 @@ typedef struct py_Error {
|
||||
/// Native function signature.
|
||||
/// @param argc number of arguments.
|
||||
/// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument.
|
||||
/// @param out output reference to the result. Please note that `out` could overlap with `argv`.
|
||||
/// Always set `out` after using `argv`.
|
||||
/// @return true if the function is successful.
|
||||
typedef bool (*py_CFunction)(int argc, py_TValue* argv, py_TValue* out);
|
||||
typedef bool (*py_CFunction)(int argc, py_TValue* argv);
|
||||
|
||||
typedef enum BindType {
|
||||
BindType_FUNCTION,
|
||||
|
@ -11,6 +11,8 @@ int NameError(py_Name name) { return -1; }
|
||||
#define AttributeError(obj, name) false
|
||||
#define BinaryOptError(op) false
|
||||
|
||||
static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
|
||||
|
||||
#define DISPATCH() \
|
||||
do { \
|
||||
frame->ip++; \
|
||||
@ -259,9 +261,10 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
|
||||
if(magic) {
|
||||
if(magic->type == tp_nativefunc) {
|
||||
bool ok = magic->_cfunc(2, SECOND(), SECOND());
|
||||
bool ok = magic->_cfunc(2, SECOND());
|
||||
if(!ok) goto __ERROR;
|
||||
POP();
|
||||
*TOP() = self->last_retval;
|
||||
} else {
|
||||
INSERT_THIRD(); // [?, a, b]
|
||||
*THIRD() = *magic; // [__getitem__, a, b]
|
||||
@ -311,9 +314,10 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__);
|
||||
if(magic) {
|
||||
if(magic->type == tp_nativefunc) {
|
||||
bool ok = magic->_cfunc(3, THIRD(), FOURTH());
|
||||
bool ok = magic->_cfunc(3, THIRD());
|
||||
if(!ok) goto __ERROR;
|
||||
STACK_SHRINK(4);
|
||||
STACK_SHRINK(3);
|
||||
*TOP() = self->last_retval;
|
||||
} else {
|
||||
INSERT_THIRD(); // [?, a, b]
|
||||
*FOURTH() = *magic; // [__selitem__, a, b, val]
|
||||
@ -380,9 +384,10 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
|
||||
if(magic) {
|
||||
if(magic->type == tp_nativefunc) {
|
||||
bool ok = magic->_cfunc(2, SECOND(), SECOND());
|
||||
bool ok = magic->_cfunc(2, SECOND());
|
||||
if(!ok) goto __ERROR;
|
||||
STACK_SHRINK(2);
|
||||
POP();
|
||||
*TOP() = self->last_retval;
|
||||
} else {
|
||||
INSERT_THIRD(); // [?, a, b]
|
||||
*THIRD() = *magic; // [__delitem__, a, b]
|
||||
@ -492,67 +497,11 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
/*****************************/
|
||||
case OP_BINARY_OP: {
|
||||
py_Name op = byte.arg & 0xFF;
|
||||
// [a, b]
|
||||
py_Ref _0 = py_tpfindmagic(SECOND()->type, op);
|
||||
py_Ref _1;
|
||||
py_TValue tmp;
|
||||
if(_0) {
|
||||
if(_0->type == tp_nativefunc) {
|
||||
bool ok = _0->_cfunc(2, SECOND(), &tmp);
|
||||
if(!ok) goto __ERROR;
|
||||
if(tmp.type != tp_not_implemented_type) {
|
||||
POP();
|
||||
*TOP() = tmp;
|
||||
DISPATCH();
|
||||
}
|
||||
} else {
|
||||
// standard call
|
||||
bool ok = py_call(_0, 2, SECOND());
|
||||
if(!ok) goto __ERROR;
|
||||
if(self->last_retval.type != tp_not_implemented_type) {
|
||||
POP();
|
||||
*TOP() = self->last_retval;
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
}
|
||||
// try reverse operation
|
||||
op = byte.arg >> 8;
|
||||
if(op) {
|
||||
// [a, b] -> [b, a]
|
||||
tmp = *TOP();
|
||||
*TOP() = *SECOND();
|
||||
*SECOND() = tmp;
|
||||
_1 = py_tpfindmagic(SECOND()->type, op);
|
||||
if(_1) {
|
||||
if(_1->type == tp_nativefunc) {
|
||||
bool ok = _1->_cfunc(2, SECOND(), &tmp);
|
||||
if(!ok) goto __ERROR;
|
||||
if(tmp.type != tp_not_implemented_type) {
|
||||
POP();
|
||||
*TOP() = tmp;
|
||||
DISPATCH();
|
||||
}
|
||||
} else {
|
||||
// standard call
|
||||
bool ok = py_call(_1, 2, SECOND());
|
||||
if(!ok) goto __ERROR;
|
||||
if(self->last_retval.type != tp_not_implemented_type) {
|
||||
POP();
|
||||
*TOP() = self->last_retval;
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// eq/ne op never fails
|
||||
if(op == __eq__ || op == __ne__) {
|
||||
POP();
|
||||
*TOP() = (op == __eq__) ? self->False : self->True;
|
||||
DISPATCH();
|
||||
}
|
||||
BinaryOptError(byte.arg);
|
||||
goto __ERROR;
|
||||
py_Name rop = byte.arg >> 8;
|
||||
if(!stack_binaryop(self, op, rop)) goto __ERROR;
|
||||
POP();
|
||||
*TOP() = self->last_retval;
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_IS_OP: {
|
||||
bool res = py_isidentical(SECOND(), TOP());
|
||||
@ -566,7 +515,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
|
||||
if(magic) {
|
||||
if(magic->type == tp_nativefunc) {
|
||||
bool ok = magic->_cfunc(2, SECOND(), SECOND());
|
||||
bool ok = magic->_cfunc(2, SECOND());
|
||||
if(!ok) goto __ERROR;
|
||||
POP();
|
||||
*TOP() = self->last_retval;
|
||||
@ -667,29 +616,22 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
return RES_RETURN;
|
||||
}
|
||||
|
||||
bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) {
|
||||
pk_VM* self = pk_current_vm;
|
||||
PUSH(lhs);
|
||||
PUSH(rhs);
|
||||
/// Assumes [a, b] are on the stack, performs a binary op.
|
||||
/// The result is stored in `self->last_retval`.
|
||||
/// The stack remains unchanged.
|
||||
static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop) {
|
||||
// [a, b]
|
||||
py_Ref _0 = py_tpfindmagic(SECOND()->type, op);
|
||||
py_Ref _1;
|
||||
if(_0) {
|
||||
if(_0->type == tp_nativefunc) {
|
||||
bool ok = _0->_cfunc(2, SECOND(), &self->last_retval);
|
||||
py_Ref magic = py_tpfindmagic(SECOND()->type, op);
|
||||
if(magic) {
|
||||
if(magic->type == tp_nativefunc) {
|
||||
bool ok = magic->_cfunc(2, SECOND());
|
||||
if(!ok) return false;
|
||||
if(self->last_retval.type != tp_not_implemented_type) {
|
||||
STACK_SHRINK(2);
|
||||
return true;
|
||||
}
|
||||
if(self->last_retval.type != tp_not_implemented_type) return true;
|
||||
} else {
|
||||
// standard call
|
||||
bool ok = py_call(_0, 2, SECOND());
|
||||
bool ok = py_call(magic, 2, SECOND());
|
||||
if(!ok) return false;
|
||||
if(self->last_retval.type != tp_not_implemented_type) {
|
||||
STACK_SHRINK(2);
|
||||
return true;
|
||||
}
|
||||
if(self->last_retval.type != tp_not_implemented_type) return true;
|
||||
}
|
||||
}
|
||||
// try reverse operation
|
||||
@ -698,31 +640,31 @@ bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) {
|
||||
py_TValue tmp = *TOP();
|
||||
*TOP() = *SECOND();
|
||||
*SECOND() = tmp;
|
||||
_1 = py_tpfindmagic(SECOND()->type, rop);
|
||||
if(_1) {
|
||||
if(_1->type == tp_nativefunc) {
|
||||
bool ok = _1->_cfunc(2, SECOND(), &self->last_retval);
|
||||
magic = py_tpfindmagic(SECOND()->type, rop);
|
||||
if(magic) {
|
||||
if(magic->type == tp_nativefunc) {
|
||||
bool ok = magic->_cfunc(2, SECOND());
|
||||
if(!ok) return false;
|
||||
if(tmp.type != tp_not_implemented_type) {
|
||||
STACK_SHRINK(2);
|
||||
return true;
|
||||
}
|
||||
if(self->last_retval.type != tp_not_implemented_type) return true;
|
||||
} else {
|
||||
// standard call
|
||||
bool ok = py_call(_1, 2, SECOND());
|
||||
bool ok = py_call(magic, 2, SECOND());
|
||||
if(!ok) return false;
|
||||
if(self->last_retval.type != tp_not_implemented_type) {
|
||||
STACK_SHRINK(2);
|
||||
return true;
|
||||
}
|
||||
if(self->last_retval.type != tp_not_implemented_type) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// eq/ne op never fails
|
||||
if(op == __eq__ || op == __ne__) {
|
||||
STACK_SHRINK(2);
|
||||
self->last_retval = (op == __eq__) ? self->False : self->True;
|
||||
return true;
|
||||
}
|
||||
return BinaryOptError(byte.arg);
|
||||
}
|
||||
|
||||
bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) {
|
||||
pk_VM* self = pk_current_vm;
|
||||
PUSH(lhs);
|
||||
PUSH(rhs);
|
||||
return stack_binaryop(self, op, rop);
|
||||
}
|
@ -40,29 +40,29 @@
|
||||
// }
|
||||
|
||||
#define DEF_NUM_BINARY_OP(name, op, rint, rfloat) \
|
||||
static bool _py_int##name(int argc, py_Ref argv, py_Ref out) { \
|
||||
static bool _py_int##name(int argc, py_Ref argv) { \
|
||||
py_checkargc(2); \
|
||||
if(py_isint(&argv[1])) { \
|
||||
int64_t lhs = py_toint(&argv[0]); \
|
||||
int64_t rhs = py_toint(&argv[1]); \
|
||||
rint(out, lhs op rhs); \
|
||||
rint(py_lastretval(), lhs op rhs); \
|
||||
} else if(py_isfloat(&argv[1])) { \
|
||||
int64_t lhs = py_toint(&argv[0]); \
|
||||
double rhs = py_tofloat(&argv[1]); \
|
||||
rfloat(out, lhs op rhs); \
|
||||
rfloat(py_lastretval(), lhs op rhs); \
|
||||
} else { \
|
||||
py_newnotimplemented(out); \
|
||||
py_newnotimplemented(py_lastretval()); \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
static bool _py_float##name(int argc, py_Ref argv, py_Ref out) { \
|
||||
static bool _py_float##name(int argc, py_Ref argv) { \
|
||||
py_checkargc(2); \
|
||||
double lhs = py_tofloat(&argv[0]); \
|
||||
double rhs; \
|
||||
if(py_castfloat(&argv[1], &rhs)) { \
|
||||
rfloat(out, lhs op rhs); \
|
||||
rfloat(py_lastretval(), lhs op rhs); \
|
||||
} else { \
|
||||
py_newnotimplemented(out); \
|
||||
py_newnotimplemented(py_lastretval()); \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
@ -80,47 +80,47 @@ DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
|
||||
|
||||
#undef DEF_NUM_BINARY_OP
|
||||
|
||||
static bool _py_int__neg__(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_int__neg__(int argc, py_Ref argv) {
|
||||
py_checkargc(1);
|
||||
int64_t val = py_toint(&argv[0]);
|
||||
py_newint(out, -val);
|
||||
py_newint(py_lastretval(), -val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_float__neg__(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_float__neg__(int argc, py_Ref argv) {
|
||||
py_checkargc(1);
|
||||
double val = py_tofloat(&argv[0]);
|
||||
py_newfloat(out, -val);
|
||||
py_newfloat(py_lastretval(), -val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__truediv__(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_int__truediv__(int argc, py_Ref argv) {
|
||||
py_checkargc(2);
|
||||
int64_t lhs = py_toint(&argv[0]);
|
||||
double rhs;
|
||||
if(py_castfloat(&argv[1], &rhs)) {
|
||||
py_newfloat(out, lhs / rhs);
|
||||
py_newfloat(py_lastretval(), lhs / rhs);
|
||||
} else {
|
||||
py_newnotimplemented(out);
|
||||
py_newnotimplemented(py_lastretval());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_float__truediv__(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_float__truediv__(int argc, py_Ref argv) {
|
||||
py_checkargc(2);
|
||||
double lhs = py_tofloat(&argv[0]);
|
||||
double rhs;
|
||||
if(py_castfloat(&argv[1], &rhs)) {
|
||||
py_newfloat(out, lhs / rhs);
|
||||
py_newfloat(py_lastretval(), lhs / rhs);
|
||||
} else {
|
||||
py_newnotimplemented(out);
|
||||
py_newnotimplemented(py_lastretval());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ZeroDivisionError(msg) false
|
||||
|
||||
static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_number__pow__(int argc, py_Ref argv) {
|
||||
py_checkargc(2);
|
||||
if(py_isint(&argv[0]) && py_isint(&argv[1])) {
|
||||
int64_t lhs = py_toint(&argv[0]);
|
||||
@ -129,7 +129,7 @@ static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
|
||||
if(lhs == 0) {
|
||||
return ZeroDivisionError("0.0 cannot be raised to a negative power");
|
||||
} else {
|
||||
py_newfloat(out, pow(lhs, rhs));
|
||||
py_newfloat(py_lastretval(), pow(lhs, rhs));
|
||||
}
|
||||
} else {
|
||||
int64_t ret = 1;
|
||||
@ -138,54 +138,54 @@ static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
|
||||
lhs *= lhs;
|
||||
rhs >>= 1;
|
||||
}
|
||||
py_newint(out, ret);
|
||||
py_newint(py_lastretval(), ret);
|
||||
}
|
||||
} else {
|
||||
double lhs, rhs;
|
||||
py_castfloat(&argv[0], &lhs);
|
||||
if(py_castfloat(&argv[1], &rhs)) {
|
||||
py_newfloat(out, pow(lhs, rhs));
|
||||
py_newfloat(py_lastretval(), pow(lhs, rhs));
|
||||
} else {
|
||||
py_newnotimplemented(out);
|
||||
py_newnotimplemented(py_lastretval());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__floordiv__(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_int__floordiv__(int argc, py_Ref argv) {
|
||||
py_checkargc(2);
|
||||
int64_t lhs = py_toint(&argv[0]);
|
||||
if(py_isint(&argv[1])) {
|
||||
int64_t rhs = py_toint(&argv[1]);
|
||||
if(rhs == 0) return -1;
|
||||
py_newint(out, lhs / rhs);
|
||||
py_newint(py_lastretval(), lhs / rhs);
|
||||
} else {
|
||||
py_newnotimplemented(out);
|
||||
py_newnotimplemented(py_lastretval());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__mod__(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_int__mod__(int argc, py_Ref argv) {
|
||||
py_checkargc(2);
|
||||
int64_t lhs = py_toint(&argv[0]);
|
||||
if(py_isint(&argv[1])) {
|
||||
int64_t rhs = py_toint(&argv[1]);
|
||||
if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
|
||||
py_newint(out, lhs % rhs);
|
||||
py_newint(py_lastretval(), lhs % rhs);
|
||||
} else {
|
||||
py_newnotimplemented(out);
|
||||
py_newnotimplemented(py_lastretval());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__invert__(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_int__invert__(int argc, py_Ref argv) {
|
||||
py_checkargc(1);
|
||||
int64_t val = py_toint(&argv[0]);
|
||||
py_newint(out, ~val);
|
||||
py_newint(py_lastretval(), ~val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__bit_length(int argc, py_Ref argv, py_Ref out) {
|
||||
static bool _py_int__bit_length(int argc, py_Ref argv) {
|
||||
py_checkargc(1);
|
||||
int64_t x = py_toint(py_arg(0));
|
||||
if(x < 0) x = -x;
|
||||
@ -194,19 +194,19 @@ static bool _py_int__bit_length(int argc, py_Ref argv, py_Ref out) {
|
||||
x >>= 1;
|
||||
bits++;
|
||||
}
|
||||
py_newint(out, bits);
|
||||
py_newint(py_lastretval(), bits);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DEF_INT_BITWISE_OP(name, op) \
|
||||
static bool _py_int##name(int argc, py_Ref argv, py_Ref out) { \
|
||||
static bool _py_int##name(int argc, py_Ref argv) { \
|
||||
py_checkargc(2); \
|
||||
int64_t lhs = py_toint(&argv[0]); \
|
||||
if(py_isint(&argv[1])) { \
|
||||
int64_t rhs = py_toint(&argv[1]); \
|
||||
py_newint(out, lhs op rhs); \
|
||||
py_newint(py_lastretval(), lhs op rhs); \
|
||||
} else { \
|
||||
py_newnotimplemented(out); \
|
||||
py_newnotimplemented(py_lastretval()); \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
@ -91,6 +91,6 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv) {
|
||||
assert(argc >= 1);
|
||||
py_Ref tmp = py_tpfindmagic(argv->type, name);
|
||||
if(!tmp) return TypeError(name);
|
||||
if(tmp->type == tp_nativefunc) { return tmp->_cfunc(argc, argv, &pk_current_vm->last_retval); }
|
||||
if(tmp->type == tp_nativefunc) { return tmp->_cfunc(argc, argv); }
|
||||
return py_call(tmp, argc, argv);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user