This commit is contained in:
blueloveTH 2024-07-01 00:21:03 +08:00
parent 8270d9035b
commit 52b210b016
9 changed files with 188 additions and 63 deletions

View File

@ -39,6 +39,7 @@ extern uint16_t __next__;
extern uint16_t __neg__; extern uint16_t __neg__;
// logical operators // logical operators
extern uint16_t __eq__; extern uint16_t __eq__;
extern uint16_t __ne__;
extern uint16_t __lt__; extern uint16_t __lt__;
extern uint16_t __le__; extern uint16_t __le__;
extern uint16_t __gt__; extern uint16_t __gt__;
@ -52,9 +53,13 @@ extern uint16_t __rsub__;
extern uint16_t __mul__; extern uint16_t __mul__;
extern uint16_t __rmul__; extern uint16_t __rmul__;
extern uint16_t __truediv__; extern uint16_t __truediv__;
extern uint16_t __rtruediv__;
extern uint16_t __floordiv__; extern uint16_t __floordiv__;
extern uint16_t __rfloordiv__;
extern uint16_t __mod__; extern uint16_t __mod__;
extern uint16_t __rmod__;
extern uint16_t __pow__; extern uint16_t __pow__;
extern uint16_t __rpow__;
extern uint16_t __matmul__; extern uint16_t __matmul__;
extern uint16_t __lshift__; extern uint16_t __lshift__;
extern uint16_t __rshift__; extern uint16_t __rshift__;

View File

@ -186,10 +186,14 @@ py_Error* py_lasterror();
void py_Error__print(py_Error*); void py_Error__print(py_Error*);
/************* Operators *************/ /************* Operators *************/
bool py_bool(const py_Ref);
int py_eq(const py_Ref, const py_Ref); int py_eq(const py_Ref, const py_Ref);
int py_le(const py_Ref, const py_Ref); int py_le(const py_Ref, const py_Ref);
bool py_hash(const py_Ref, int64_t* out); bool py_hash(const py_Ref, int64_t* out);
/// Compare two objects without using magic methods.
bool py_isidentical(const py_Ref, const py_Ref);
/// A stack operation that calls a function. /// A stack operation that calls a function.
/// It assumes `argc + kwargc` arguments are already pushed to the stack. /// It assumes `argc + kwargc` arguments are already pushed to the stack.
/// The result will be set to `vm->last_retval`. /// The result will be set to `vm->last_retval`.

View File

@ -53,18 +53,8 @@ OPCODE(BUILD_SLICE)
OPCODE(BUILD_STRING) OPCODE(BUILD_STRING)
/**************************/ /**************************/
OPCODE(BINARY_OP) OPCODE(BINARY_OP)
OPCODE(COMPARE_LT)
OPCODE(COMPARE_LE)
OPCODE(COMPARE_EQ)
OPCODE(COMPARE_NE)
OPCODE(COMPARE_GT)
OPCODE(COMPARE_GE)
OPCODE(IS_OP) OPCODE(IS_OP)
OPCODE(IS_NOT_OP) OPCODE(CONTAINS_OP)
OPCODE(IN_OP)
OPCODE(NOT_IN_OP)
/**************************/ /**************************/
OPCODE(JUMP_FORWARD) OPCODE(JUMP_FORWARD)
OPCODE(POP_JUMP_IF_FALSE) OPCODE(POP_JUMP_IF_FALSE)

View File

@ -29,6 +29,7 @@ void pk_StrName__initialize() {
__neg__ = pk_StrName__map("__neg__"); __neg__ = pk_StrName__map("__neg__");
// logical operators // logical operators
__eq__ = pk_StrName__map("__eq__"); __eq__ = pk_StrName__map("__eq__");
__ne__ = pk_StrName__map("__ne__");
__lt__ = pk_StrName__map("__lt__"); __lt__ = pk_StrName__map("__lt__");
__le__ = pk_StrName__map("__le__"); __le__ = pk_StrName__map("__le__");
__gt__ = pk_StrName__map("__gt__"); __gt__ = pk_StrName__map("__gt__");
@ -42,9 +43,13 @@ void pk_StrName__initialize() {
__mul__ = pk_StrName__map("__mul__"); __mul__ = pk_StrName__map("__mul__");
__rmul__ = pk_StrName__map("__rmul__"); __rmul__ = pk_StrName__map("__rmul__");
__truediv__ = pk_StrName__map("__truediv__"); __truediv__ = pk_StrName__map("__truediv__");
__rtruediv__ = pk_StrName__map("__rtruediv__");
__floordiv__ = pk_StrName__map("__floordiv__"); __floordiv__ = pk_StrName__map("__floordiv__");
__rfloordiv__ = pk_StrName__map("__rfloordiv__");
__mod__ = pk_StrName__map("__mod__"); __mod__ = pk_StrName__map("__mod__");
__rmod__ = pk_StrName__map("__rmod__");
__pow__ = pk_StrName__map("__pow__"); __pow__ = pk_StrName__map("__pow__");
__rpow__ = pk_StrName__map("__rpow__");
__matmul__ = pk_StrName__map("__matmul__"); __matmul__ = pk_StrName__map("__matmul__");
__lshift__ = pk_StrName__map("__lshift__"); __lshift__ = pk_StrName__map("__lshift__");
__rshift__ = pk_StrName__map("__rshift__"); __rshift__ = pk_StrName__map("__rshift__");
@ -71,15 +76,15 @@ void pk_StrName__initialize() {
__class__ = pk_StrName__map("__class__"); __class__ = pk_StrName__map("__class__");
__missing__ = pk_StrName__map("__missing__"); __missing__ = pk_StrName__map("__missing__");
// print all names
for(int i = 0; i < _interned.count; i++) {
printf("%d: %s\n", i+1, c11__getitem(char*, &_r_interned, i));
}
pk_id_add = pk_StrName__map("add"); pk_id_add = pk_StrName__map("add");
pk_id_set = pk_StrName__map("set"); pk_id_set = pk_StrName__map("set");
pk_id_long = pk_StrName__map("long"); pk_id_long = pk_StrName__map("long");
pk_id_complex = pk_StrName__map("complex"); pk_id_complex = pk_StrName__map("complex");
// // print all names
// for(int i = 0; i < _interned.count; i++) {
// printf("%d: %s\n", i+1, c11__getitem(char*, &_r_interned, i));
// }
} }
void pk_StrName__finalize() { void pk_StrName__finalize() {
@ -138,6 +143,7 @@ uint16_t __next__;
uint16_t __neg__; uint16_t __neg__;
// logical operators // logical operators
uint16_t __eq__; uint16_t __eq__;
uint16_t __ne__;
uint16_t __lt__; uint16_t __lt__;
uint16_t __le__; uint16_t __le__;
uint16_t __gt__; uint16_t __gt__;
@ -151,9 +157,13 @@ uint16_t __rsub__;
uint16_t __mul__; uint16_t __mul__;
uint16_t __rmul__; uint16_t __rmul__;
uint16_t __truediv__; uint16_t __truediv__;
uint16_t __rtruediv__;
uint16_t __floordiv__; uint16_t __floordiv__;
uint16_t __rfloordiv__;
uint16_t __mod__; uint16_t __mod__;
uint16_t __rmod__;
uint16_t __pow__; uint16_t __pow__;
uint16_t __rpow__;
uint16_t __matmul__; uint16_t __matmul__;
uint16_t __lshift__; uint16_t __lshift__;
uint16_t __rshift__; uint16_t __rshift__;

View File

@ -849,19 +849,19 @@ static void BinaryExpr__dtor(Expr* self_) {
vtdelete(self->rhs); vtdelete(self->rhs);
} }
static Opcode cmp_token2op(TokenIndex token) { static Opcode cmp_token2name(TokenIndex token) {
switch(token) { switch(token) {
case TK_LT: return OP_COMPARE_LT; break; case TK_LT: return __lt__;
case TK_LE: return OP_COMPARE_LE; break; case TK_LE: return __le__;
case TK_EQ: return OP_COMPARE_EQ; break; case TK_EQ: return __eq__;
case TK_NE: return OP_COMPARE_NE; break; case TK_NE: return __ne__;
case TK_GT: return OP_COMPARE_GT; break; case TK_GT: return __gt__;
case TK_GE: return OP_COMPARE_GE; break; case TK_GE: return __ge__;
default: return OP_NO_OP; // 0 default: return 0;
} }
} }
#define is_compare_expr(e) ((e)->vt->is_binary && cmp_token2op(((BinaryExpr*)(e))->op)) #define is_compare_expr(e) ((e)->vt->is_binary && cmp_token2name(((BinaryExpr*)(e))->op))
static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) { static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) {
if(is_compare_expr(self->lhs)) { if(is_compare_expr(self->lhs)) {
@ -872,8 +872,7 @@ static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) {
vtemit_(self->rhs, ctx); // [a, b] vtemit_(self->rhs, ctx); // [a, b]
Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [a, b, b] Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [a, b, b]
Ctx__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line); // [b, a, b] Ctx__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line); // [b, a, b]
Opcode opcode = cmp_token2op(self->op); Ctx__emit_(ctx, OP_BINARY_OP, cmp_token2name(self->op), self->line);
Ctx__emit_(ctx, opcode, BC_NOARG, self->line);
// [b, RES] // [b, RES]
int index = Ctx__emit_(ctx, OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, self->line); int index = Ctx__emit_(ctx, OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, self->line);
c11_vector__push(int, jmps, index); c11_vector__push(int, jmps, index);
@ -883,7 +882,7 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) {
BinaryExpr* self = (BinaryExpr*)self_; BinaryExpr* self = (BinaryExpr*)self_;
c11_vector /*T=int*/ jmps; c11_vector /*T=int*/ jmps;
c11_vector__ctor(&jmps, sizeof(int)); c11_vector__ctor(&jmps, sizeof(int));
if(cmp_token2op(self->op) && is_compare_expr(self->lhs)) { if(cmp_token2name(self->op) && is_compare_expr(self->lhs)) {
// (a < b) < c // (a < b) < c
BinaryExpr* e = (BinaryExpr*)self->lhs; BinaryExpr* e = (BinaryExpr*)self->lhs;
_emit_compare(e, ctx, &jmps); _emit_compare(e, ctx, &jmps);
@ -906,22 +905,34 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) {
case TK_ADD: arg = __add__ | (__radd__ << 8); break; case TK_ADD: arg = __add__ | (__radd__ << 8); break;
case TK_SUB: arg = __sub__ | (__rsub__ << 8); break; case TK_SUB: arg = __sub__ | (__rsub__ << 8); break;
case TK_MUL: arg = __mul__ | (__rmul__ << 8); break; case TK_MUL: arg = __mul__ | (__rmul__ << 8); break;
case TK_DIV: arg = __truediv__; break; case TK_DIV: arg = __truediv__ | (__rtruediv__ << 8); break;
case TK_FLOORDIV: arg = __floordiv__; break; case TK_FLOORDIV: arg = __floordiv__ | (__rfloordiv__ << 8); break;
case TK_MOD: arg = __mod__; break; case TK_MOD: arg = __mod__ | (__rmod__ << 8); break;
case TK_POW: arg = __pow__; break; case TK_POW: arg = __pow__ | (__rpow__ << 8); break;
case TK_LT: opcode = OP_COMPARE_LT; break; case TK_LT: arg = __lt__ | (__gt__ << 8); break;
case TK_LE: opcode = OP_COMPARE_LE; break; case TK_LE: arg = __le__ | (__ge__ << 8); break;
case TK_EQ: opcode = OP_COMPARE_EQ; break; case TK_EQ: arg = __eq__ | (__eq__ << 8); break;
case TK_NE: opcode = OP_COMPARE_NE; break; case TK_NE: arg = __ne__ | (__ne__ << 8); break;
case TK_GT: opcode = OP_COMPARE_GT; break; case TK_GT: arg = __gt__ | (__lt__ << 8); break;
case TK_GE: opcode = OP_COMPARE_GE; break; case TK_GE: arg = __ge__ | (__le__ << 8); break;
case TK_IN: opcode = OP_IN_OP; break; case TK_IN:
case TK_NOT_IN: opcode = OP_NOT_IN_OP; break; opcode = OP_CONTAINS_OP;
case TK_IS: opcode = OP_IS_OP; break; arg = 0;
case TK_IS_NOT: opcode = OP_IS_NOT_OP; break; break;
case TK_NOT_IN:
opcode = OP_CONTAINS_OP;
arg = 1;
break;
case TK_IS:
opcode = OP_IS_OP;
arg = 0;
break;
case TK_IS_NOT:
opcode = OP_IS_OP;
arg = 1;
break;
case TK_LSHIFT: arg = __lshift__; break; case TK_LSHIFT: arg = __lshift__; break;
case TK_RSHIFT: arg = __rshift__; break; case TK_RSHIFT: arg = __rshift__; break;
@ -1734,8 +1745,13 @@ static Error* exprBinaryOp(Compiler* self) {
TokenIndex op = prev()->type; TokenIndex op = prev()->type;
check(parse_expression(self, rules[op].precedence + 1, false)); check(parse_expression(self, rules[op].precedence + 1, false));
BinaryExpr* e = BinaryExpr__new(line, op, false); BinaryExpr* e = BinaryExpr__new(line, op, false);
if(op == TK_IN || op == TK_NOT_IN) {
e->lhs = Ctx__s_popx(ctx());
e->rhs = Ctx__s_popx(ctx());
} else {
e->rhs = Ctx__s_popx(ctx()); e->rhs = Ctx__s_popx(ctx());
e->lhs = Ctx__s_popx(ctx()); e->lhs = Ctx__s_popx(ctx());
}
Ctx__s_push(ctx(), (Expr*)e); Ctx__s_push(ctx(), (Expr*)e);
return NULL; return NULL;
} }

View File

@ -545,10 +545,101 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
} }
} }
} }
// eq/ne op never fails
if(op == __eq__ || op == __ne__) {
POP();
*TOP() = (op == __eq__) ? self->False : self->True;
DISPATCH();
}
BinaryOptError(byte.arg); BinaryOptError(byte.arg);
goto __ERROR; goto __ERROR;
} }
case OP_IS_OP: {
bool res = py_isidentical(SECOND(), TOP());
POP();
if(byte.arg) res = !res;
*TOP() = res ? self->True : self->False;
DISPATCH();
}
case OP_CONTAINS_OP: {
// [b, a] -> b __contains__ a (a in b)
py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
if(magic) {
if(magic->type == tp_nativefunc) {
bool ok = magic->_cfunc(2, SECOND(), SECOND());
if(!ok) goto __ERROR;
POP();
*TOP() = self->last_retval;
} else {
INSERT_THIRD(); // [?, b, a]
*THIRD() = *magic; // [__contains__, a, b]
vectorcall_opcall(2);
}
bool res = py_tobool(TOP());
if(byte.arg) py_newbool(TOP(), !res);
DISPATCH();
}
TypeError();
goto __ERROR;
}
/*****************************************/
case OP_JUMP_FORWARD: DISPATCH_JUMP((int16_t)byte.arg);
case OP_POP_JUMP_IF_FALSE: {
bool res = py_bool(TOP());
POP();
if(!res) DISPATCH_JUMP((int16_t)byte.arg);
DISPATCH();
}
case OP_POP_JUMP_IF_TRUE: {
bool res = py_bool(TOP());
POP();
if(res) DISPATCH_JUMP((int16_t)byte.arg);
DISPATCH();
}
case OP_JUMP_IF_TRUE_OR_POP:
if(py_bool(TOP())) {
DISPATCH_JUMP((int16_t)byte.arg);
} else {
POP();
DISPATCH();
}
case OP_JUMP_IF_FALSE_OR_POP:
if(!py_bool(TOP())) {
DISPATCH_JUMP((int16_t)byte.arg);
} else {
POP();
DISPATCH();
}
case OP_SHORTCUT_IF_FALSE_OR_POP:
if(!py_bool(TOP())) { // [b, False]
STACK_SHRINK(2); // []
PUSH(&self->False); // [False]
DISPATCH_JUMP((int16_t)byte.arg);
} else {
POP(); // [b]
DISPATCH();
}
case OP_LOOP_CONTINUE:
// just an alias of OP_JUMP_FORWARD
DISPATCH_JUMP((int16_t)byte.arg);
case OP_LOOP_BREAK: {
int target = Frame__ip(frame) + byte.arg;
Frame__prepare_jump_break(frame, &self->stack, target);
DISPATCH_JUMP((int16_t)byte.arg);
}
case OP_JUMP_ABSOLUTE_TOP: {
int target = py_toint(TOP());
POP();
DISPATCH_JUMP_ABSOLUTE(target);
}
// case OP_GOTO: {
// StrName _name(byte.arg);
// int target = c11_smallmap_n2i__get(&frame->co->labels, byte.arg, -1);
// if(target < 0) RuntimeError(_S("label ", _name.escape(), " not found"));
// frame->prepare_jump_break(&s_data, target);
// DISPATCH_JUMP_ABSOLUTE(target)
// }
/*****************************************/
case OP_RETURN_VALUE: { case OP_RETURN_VALUE: {
self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None; self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None;
pk_VM__pop_frame(self); pk_VM__pop_frame(self);

View File

@ -39,17 +39,17 @@
// return 0; // return 0;
// } // }
#define DEF_NUM_BINARY_OP(name, op) \ #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_Ref out) { \
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]); \
py_newint(out, lhs op rhs); \ rint(out, 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]); \
py_newfloat(out, lhs op rhs); \ rfloat(out, lhs op rhs); \
} else { \ } else { \
py_newnotimplemented(out); \ py_newnotimplemented(out); \
} \ } \
@ -60,22 +60,23 @@
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 op rhs); \ rfloat(out, lhs op rhs); \
} else { \ } else { \
py_newnotimplemented(out); \ py_newnotimplemented(out); \
} \ } \
return true; \ return true; \
} }
DEF_NUM_BINARY_OP(__add__, +) DEF_NUM_BINARY_OP(__add__, +, py_newint, py_newfloat)
DEF_NUM_BINARY_OP(__sub__, -) DEF_NUM_BINARY_OP(__sub__, -, py_newint, py_newfloat)
DEF_NUM_BINARY_OP(__mul__, *) DEF_NUM_BINARY_OP(__mul__, *, py_newint, py_newfloat)
DEF_NUM_BINARY_OP(__eq__, ==) DEF_NUM_BINARY_OP(__eq__, ==, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__lt__, <) DEF_NUM_BINARY_OP(__ne__, ==, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__le__, <=) DEF_NUM_BINARY_OP(__lt__, <, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__gt__, >) DEF_NUM_BINARY_OP(__le__, <=, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__ge__, >=) DEF_NUM_BINARY_OP(__gt__, >, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
#undef DEF_NUM_BINARY_OP #undef DEF_NUM_BINARY_OP
@ -229,6 +230,8 @@ void pk_VM__init_builtins(pk_VM* self) {
py_bindmagic(tp_int, __eq__, _py_int__eq__); py_bindmagic(tp_int, __eq__, _py_int__eq__);
py_bindmagic(tp_float, __eq__, _py_float__eq__); py_bindmagic(tp_float, __eq__, _py_float__eq__);
py_bindmagic(tp_int, __ne__, _py_int__ne__);
py_bindmagic(tp_float, __ne__, _py_float__ne__);
py_bindmagic(tp_int, __lt__, _py_int__lt__); py_bindmagic(tp_int, __lt__, _py_int__lt__);
py_bindmagic(tp_float, __lt__, _py_float__lt__); py_bindmagic(tp_float, __lt__, _py_float__lt__);
py_bindmagic(tp_int, __le__, _py_int__le__); py_bindmagic(tp_int, __le__, _py_int__le__);

View File

@ -5,6 +5,15 @@ int py_eq(const py_Ref lhs, const py_Ref rhs) { return 0; }
int py_le(const py_Ref lhs, const py_Ref rhs) { return 0; } int py_le(const py_Ref lhs, const py_Ref rhs) { return 0; }
bool py_isidentical(const py_Ref lhs, const py_Ref rhs){
if(lhs->is_ptr && rhs->is_ptr){
return lhs->_obj == rhs->_obj;
}
return false;
}
bool py_bool(const py_Ref val) { return 0; }
bool py_hash(const py_Ref val, int64_t* out) { return 0; } bool py_hash(const py_Ref val, int64_t* out) { return 0; }
bool py_getattr(const py_Ref self, py_Name name, py_Ref out) { return true; } bool py_getattr(const py_Ref self, py_Name name, py_Ref out) { return true; }

View File

@ -25,7 +25,7 @@ int main(int argc, char** argv) {
#endif #endif
py_initialize(); py_initialize();
const char* source = "[1/2, 'a']"; const char* source = "1 < 2";
py_Ref r0 = py_reg(0); py_Ref r0 = py_reg(0);
if(py_eval(source, r0)){ if(py_eval(source, r0)){
@ -33,11 +33,8 @@ int main(int argc, char** argv) {
py_Error__print(err); py_Error__print(err);
}else{ }else{
// handle the result // handle the result
py_Ref _0 = py_list__getitem(r0, 0); bool _L0 = py_tobool(r0);
py_Ref _1 = py_list__getitem(r0, 1); printf("%d\n", _L0);
float _L0 = py_tofloat(_0);
const char* _L1 = py_tostr(_1);
printf("%f, %s\n", _L0, _L1);
} }
py_finalize(); py_finalize();