This commit is contained in:
blueloveTH 2024-07-01 01:42:08 +08:00
parent 36b3c9ff8f
commit c954431442
4 changed files with 78 additions and 138 deletions

View File

@ -18,10 +18,8 @@ typedef struct py_Error {
/// Native function signature. /// Native function signature.
/// @param argc number of arguments. /// @param argc number of arguments.
/// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument. /// @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. /// @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 { typedef enum BindType {
BindType_FUNCTION, BindType_FUNCTION,

View File

@ -11,6 +11,8 @@ int NameError(py_Name name) { return -1; }
#define AttributeError(obj, name) false #define AttributeError(obj, name) false
#define BinaryOptError(op) false #define BinaryOptError(op) false
static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
#define DISPATCH() \ #define DISPATCH() \
do { \ do { \
frame->ip++; \ frame->ip++; \
@ -259,9 +261,10 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__); py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
bool ok = magic->_cfunc(2, SECOND(), SECOND()); bool ok = magic->_cfunc(2, SECOND());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
POP(); POP();
*TOP() = self->last_retval;
} else { } else {
INSERT_THIRD(); // [?, a, b] INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__getitem__, 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__); py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
bool ok = magic->_cfunc(3, THIRD(), FOURTH()); bool ok = magic->_cfunc(3, THIRD());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
STACK_SHRINK(4); STACK_SHRINK(3);
*TOP() = self->last_retval;
} else { } else {
INSERT_THIRD(); // [?, a, b] INSERT_THIRD(); // [?, a, b]
*FOURTH() = *magic; // [__selitem__, a, b, val] *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__); py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
bool ok = magic->_cfunc(2, SECOND(), SECOND()); bool ok = magic->_cfunc(2, SECOND());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
STACK_SHRINK(2); POP();
*TOP() = self->last_retval;
} else { } else {
INSERT_THIRD(); // [?, a, b] INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__delitem__, a, b] *THIRD() = *magic; // [__delitem__, a, b]
@ -492,68 +497,12 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
/*****************************/ /*****************************/
case OP_BINARY_OP: { case OP_BINARY_OP: {
py_Name op = byte.arg & 0xFF; py_Name op = byte.arg & 0xFF;
// [a, b] py_Name rop = byte.arg >> 8;
py_Ref _0 = py_tpfindmagic(SECOND()->type, op); if(!stack_binaryop(self, op, rop)) goto __ERROR;
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(); POP();
*TOP() = self->last_retval; *TOP() = self->last_retval;
DISPATCH(); 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;
}
case OP_IS_OP: { case OP_IS_OP: {
bool res = py_isidentical(SECOND(), TOP()); bool res = py_isidentical(SECOND(), TOP());
POP(); POP();
@ -566,7 +515,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__); py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
bool ok = magic->_cfunc(2, SECOND(), SECOND()); bool ok = magic->_cfunc(2, SECOND());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
POP(); POP();
*TOP() = self->last_retval; *TOP() = self->last_retval;
@ -667,29 +616,22 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
return RES_RETURN; return RES_RETURN;
} }
bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) { /// Assumes [a, b] are on the stack, performs a binary op.
pk_VM* self = pk_current_vm; /// The result is stored in `self->last_retval`.
PUSH(lhs); /// The stack remains unchanged.
PUSH(rhs); static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop) {
// [a, b] // [a, b]
py_Ref _0 = py_tpfindmagic(SECOND()->type, op); py_Ref magic = py_tpfindmagic(SECOND()->type, op);
py_Ref _1; if(magic) {
if(_0) { if(magic->type == tp_nativefunc) {
if(_0->type == tp_nativefunc) { bool ok = magic->_cfunc(2, SECOND());
bool ok = _0->_cfunc(2, SECOND(), &self->last_retval);
if(!ok) return false; if(!ok) return false;
if(self->last_retval.type != tp_not_implemented_type) { if(self->last_retval.type != tp_not_implemented_type) return true;
STACK_SHRINK(2);
return true;
}
} else { } else {
// standard call // standard call
bool ok = py_call(_0, 2, SECOND()); bool ok = py_call(magic, 2, SECOND());
if(!ok) return false; if(!ok) return false;
if(self->last_retval.type != tp_not_implemented_type) { if(self->last_retval.type != tp_not_implemented_type) return true;
STACK_SHRINK(2);
return true;
}
} }
} }
// try reverse operation // 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(); py_TValue tmp = *TOP();
*TOP() = *SECOND(); *TOP() = *SECOND();
*SECOND() = tmp; *SECOND() = tmp;
_1 = py_tpfindmagic(SECOND()->type, rop); magic = py_tpfindmagic(SECOND()->type, rop);
if(_1) { if(magic) {
if(_1->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
bool ok = _1->_cfunc(2, SECOND(), &self->last_retval); bool ok = magic->_cfunc(2, SECOND());
if(!ok) return false; if(!ok) return false;
if(tmp.type != tp_not_implemented_type) { if(self->last_retval.type != tp_not_implemented_type) return true;
STACK_SHRINK(2);
return true;
}
} else { } else {
// standard call // standard call
bool ok = py_call(_1, 2, SECOND()); bool ok = py_call(magic, 2, SECOND());
if(!ok) return false; if(!ok) return false;
if(self->last_retval.type != tp_not_implemented_type) { if(self->last_retval.type != tp_not_implemented_type) return true;
STACK_SHRINK(2);
return true;
}
} }
} }
} }
// eq/ne op never fails // eq/ne op never fails
if(op == __eq__ || op == __ne__) { if(op == __eq__ || op == __ne__) {
STACK_SHRINK(2);
self->last_retval = (op == __eq__) ? self->False : self->True; self->last_retval = (op == __eq__) ? self->False : self->True;
return true; return true;
} }
return BinaryOptError(byte.arg); 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);
}

View File

@ -40,29 +40,29 @@
// } // }
#define DEF_NUM_BINARY_OP(name, op, rint, rfloat) \ #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); \ py_checkargc(2); \
if(py_isint(&argv[1])) { \ if(py_isint(&argv[1])) { \
int64_t lhs = py_toint(&argv[0]); \ int64_t lhs = py_toint(&argv[0]); \
int64_t rhs = py_toint(&argv[1]); \ int64_t rhs = py_toint(&argv[1]); \
rint(out, lhs op rhs); \ rint(py_lastretval(), lhs op rhs); \
} else if(py_isfloat(&argv[1])) { \ } else if(py_isfloat(&argv[1])) { \
int64_t lhs = py_toint(&argv[0]); \ int64_t lhs = py_toint(&argv[0]); \
double rhs = py_tofloat(&argv[1]); \ double rhs = py_tofloat(&argv[1]); \
rfloat(out, lhs op rhs); \ rfloat(py_lastretval(), lhs op rhs); \
} else { \ } else { \
py_newnotimplemented(out); \ py_newnotimplemented(py_lastretval()); \
} \ } \
return true; \ 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); \ py_checkargc(2); \
double lhs = py_tofloat(&argv[0]); \ double lhs = py_tofloat(&argv[0]); \
double rhs; \ double rhs; \
if(py_castfloat(&argv[1], &rhs)) { \ if(py_castfloat(&argv[1], &rhs)) { \
rfloat(out, lhs op rhs); \ rfloat(py_lastretval(), lhs op rhs); \
} else { \ } else { \
py_newnotimplemented(out); \ py_newnotimplemented(py_lastretval()); \
} \ } \
return true; \ return true; \
} }
@ -80,47 +80,47 @@ DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
#undef DEF_NUM_BINARY_OP #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); py_checkargc(1);
int64_t val = py_toint(&argv[0]); int64_t val = py_toint(&argv[0]);
py_newint(out, -val); py_newint(py_lastretval(), -val);
return true; 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); py_checkargc(1);
double val = py_tofloat(&argv[0]); double val = py_tofloat(&argv[0]);
py_newfloat(out, -val); py_newfloat(py_lastretval(), -val);
return true; 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); py_checkargc(2);
int64_t lhs = py_toint(&argv[0]); int64_t lhs = py_toint(&argv[0]);
double rhs; double rhs;
if(py_castfloat(&argv[1], &rhs)) { if(py_castfloat(&argv[1], &rhs)) {
py_newfloat(out, lhs / rhs); py_newfloat(py_lastretval(), lhs / rhs);
} else { } else {
py_newnotimplemented(out); py_newnotimplemented(py_lastretval());
} }
return true; 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); py_checkargc(2);
double lhs = py_tofloat(&argv[0]); double lhs = py_tofloat(&argv[0]);
double rhs; double rhs;
if(py_castfloat(&argv[1], &rhs)) { if(py_castfloat(&argv[1], &rhs)) {
py_newfloat(out, lhs / rhs); py_newfloat(py_lastretval(), lhs / rhs);
} else { } else {
py_newnotimplemented(out); py_newnotimplemented(py_lastretval());
} }
return true; return true;
} }
#define ZeroDivisionError(msg) false #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); py_checkargc(2);
if(py_isint(&argv[0]) && py_isint(&argv[1])) { if(py_isint(&argv[0]) && py_isint(&argv[1])) {
int64_t lhs = py_toint(&argv[0]); 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) { if(lhs == 0) {
return ZeroDivisionError("0.0 cannot be raised to a negative power"); return ZeroDivisionError("0.0 cannot be raised to a negative power");
} else { } else {
py_newfloat(out, pow(lhs, rhs)); py_newfloat(py_lastretval(), pow(lhs, rhs));
} }
} else { } else {
int64_t ret = 1; int64_t ret = 1;
@ -138,54 +138,54 @@ static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
lhs *= lhs; lhs *= lhs;
rhs >>= 1; rhs >>= 1;
} }
py_newint(out, ret); py_newint(py_lastretval(), ret);
} }
} else { } else {
double lhs, rhs; double lhs, rhs;
py_castfloat(&argv[0], &lhs); py_castfloat(&argv[0], &lhs);
if(py_castfloat(&argv[1], &rhs)) { if(py_castfloat(&argv[1], &rhs)) {
py_newfloat(out, pow(lhs, rhs)); py_newfloat(py_lastretval(), pow(lhs, rhs));
} else { } else {
py_newnotimplemented(out); py_newnotimplemented(py_lastretval());
} }
} }
return true; 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); py_checkargc(2);
int64_t lhs = py_toint(&argv[0]); int64_t lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) { if(py_isint(&argv[1])) {
int64_t rhs = py_toint(&argv[1]); int64_t rhs = py_toint(&argv[1]);
if(rhs == 0) return -1; if(rhs == 0) return -1;
py_newint(out, lhs / rhs); py_newint(py_lastretval(), lhs / rhs);
} else { } else {
py_newnotimplemented(out); py_newnotimplemented(py_lastretval());
} }
return true; 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); py_checkargc(2);
int64_t lhs = py_toint(&argv[0]); int64_t lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) { if(py_isint(&argv[1])) {
int64_t rhs = py_toint(&argv[1]); int64_t rhs = py_toint(&argv[1]);
if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero"); if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
py_newint(out, lhs % rhs); py_newint(py_lastretval(), lhs % rhs);
} else { } else {
py_newnotimplemented(out); py_newnotimplemented(py_lastretval());
} }
return true; 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); py_checkargc(1);
int64_t val = py_toint(&argv[0]); int64_t val = py_toint(&argv[0]);
py_newint(out, ~val); py_newint(py_lastretval(), ~val);
return true; 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); py_checkargc(1);
int64_t x = py_toint(py_arg(0)); int64_t x = py_toint(py_arg(0));
if(x < 0) x = -x; 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; x >>= 1;
bits++; bits++;
} }
py_newint(out, bits); py_newint(py_lastretval(), bits);
return true; return true;
} }
#define DEF_INT_BITWISE_OP(name, op) \ #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); \ py_checkargc(2); \
int64_t lhs = py_toint(&argv[0]); \ int64_t lhs = py_toint(&argv[0]); \
if(py_isint(&argv[1])) { \ if(py_isint(&argv[1])) { \
int64_t rhs = py_toint(&argv[1]); \ int64_t rhs = py_toint(&argv[1]); \
py_newint(out, lhs op rhs); \ py_newint(py_lastretval(), lhs op rhs); \
} else { \ } else { \
py_newnotimplemented(out); \ py_newnotimplemented(py_lastretval()); \
} \ } \
return true; \ return true; \
} }

View File

@ -91,6 +91,6 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv) {
assert(argc >= 1); assert(argc >= 1);
py_Ref tmp = py_tpfindmagic(argv->type, name); py_Ref tmp = py_tpfindmagic(argv->type, name);
if(!tmp) return TypeError(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); return py_call(tmp, argc, argv);
} }