diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 2e3db29d..390fcd6a 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -90,6 +90,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo const char* pk_opname(Opcode op); // type registration +void pk_object__register(); void pk_number__register(); py_Type pk_str__register(); py_Type pk_bytes__register(); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 8f3a3f3c..05e17eef 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -272,24 +272,29 @@ ImagExpr* ImagExpr__new(int line, double value) { typedef struct LiteralExpr { EXPR_COMMON_HEADER const TokenValue* value; + bool negated; } LiteralExpr; void LiteralExpr__emit_(Expr* self_, Ctx* ctx) { LiteralExpr* self = (LiteralExpr*)self_; switch(self->value->index) { case TokenValue_I64: { - int64_t val = self->value->_i64; + py_i64 val = self->value->_i64; + if(self->negated) val = -val; Ctx__emit_int(ctx, val, self->line); break; } case TokenValue_F64: { py_TValue value; - py_newfloat(&value, self->value->_f64); + py_f64 val = self->value->_f64; + if(self->negated) val = -val; + py_newfloat(&value, val); int index = Ctx__add_const(ctx, &value); Ctx__emit_(ctx, OP_LOAD_CONST, index, self->line); break; } case TokenValue_STR: { + assert(!self->negated); c11_sv sv = c11_string__sv(self->value->_str); int index = Ctx__add_const_string(ctx, sv); Ctx__emit_(ctx, OP_LOAD_CONST, index, self->line); @@ -308,6 +313,7 @@ LiteralExpr* LiteralExpr__new(int line, const TokenValue* value) { self->vt = &Vt; self->line = line; self->value = value; + self->negated = false; return self; } @@ -330,9 +336,7 @@ void Literal0Expr__emit_(Expr* self_, Ctx* ctx) { } Literal0Expr* Literal0Expr__new(int line, TokenIndex token) { - const static ExprVt Vt = {.emit_ = Literal0Expr__emit_, - .is_literal = true, - .is_json_object = true}; + const static ExprVt Vt = {.emit_ = Literal0Expr__emit_, .is_json_object = true}; static_assert_expr_size(Literal0Expr); Literal0Expr* self = PoolExpr_alloc(); self->vt = &Vt; @@ -1771,7 +1775,19 @@ static Error* exprUnaryOp(Compiler* self) { check(parse_expression(self, PREC_UNARY + 1, false)); Expr* e = Ctx__s_popx(ctx()); switch(op) { - case TK_SUB: Ctx__s_push(ctx(), (Expr*)UnaryExpr__new(line, e, OP_UNARY_NEGATIVE)); break; + case TK_SUB: { + // constant fold + if(e->vt->is_literal) { + LiteralExpr* le = (LiteralExpr*)e; + if(le->value->index == TokenValue_I64 || le->value->index == TokenValue_F64) { + le->negated = true; + } + Ctx__s_push(ctx(), e); + } else { + Ctx__s_push(ctx(), (Expr*)UnaryExpr__new(line, e, OP_UNARY_NEGATIVE)); + } + break; + } case TK_INVERT: Ctx__s_push(ctx(), (Expr*)UnaryExpr__new(line, e, OP_UNARY_INVERT)); break; case TK_MUL: Ctx__s_push(ctx(), (Expr*)StarredExpr__new(line, e, 1)); break; case TK_POW: Ctx__s_push(ctx(), (Expr*)StarredExpr__new(line, e, 2)); break; diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index b7bdb927..aae34418 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -86,7 +86,27 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { c11_sbuf buf; c11_sbuf__ctor(&buf); for(py_Ref p = self->stack.begin; p != SP(); p++) { - c11_sbuf__write_cstr(&buf, py_tpname(p->type)); + switch(p->type){ + case 0: c11_sbuf__write_cstr(&buf, "nil"); break; + case tp_int: c11_sbuf__write_i64(&buf, p->_i64); break; + case tp_float: c11_sbuf__write_f64(&buf, p->_f64, -1); break; + case tp_bool: c11_sbuf__write_cstr(&buf, p->_bool ? "True" : "False"); break; + case tp_none_type: c11_sbuf__write_cstr(&buf, "None"); break; + case tp_type: { + pk_sprintf(&buf, "", py_totype(p)); + break; + } + case tp_str: { + int size; + const char* data = py_tostrn(p, &size); + pk_sprintf(&buf, "%q", (c11_sv){data, size}); + break; + } + default:{ + pk_sprintf(&buf, "(%t)", p->type); + break; + } + } if(p != TOP()) c11_sbuf__write_cstr(&buf, ", "); } c11_string* stack_str = c11_sbuf__submit(&buf); @@ -694,16 +714,9 @@ static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop) { // [a, b] 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) return true; - } else { - // standard call - bool ok = py_call(magic, 2, SECOND()); - if(!ok) return false; - if(self->last_retval.type != tp_not_implemented_type) return true; - } + bool ok = py_call(magic, 2, SECOND()); + if(!ok) return false; + if(self->last_retval.type != tp_not_implemented_type) return true; } // try reverse operation if(rop) { @@ -713,16 +726,9 @@ static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop) { *SECOND() = tmp; magic = py_tpfindmagic(SECOND()->type, rop); 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) return true; - } else { - // standard call - bool ok = py_call(magic, 2, SECOND()); - if(!ok) return false; - if(self->last_retval.type != tp_not_implemented_type) return true; - } + bool ok = py_call(magic, 2, SECOND()); + if(!ok) return false; + if(self->last_retval.type != tp_not_implemented_type) return true; } } // eq/ne op never fails due to object.__eq__ diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 1ebf6e2a..ddbb498d 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -56,12 +56,7 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self, void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); } -static bool _py_object__new__(int argc, py_Ref argv) { - assert(argc >= 1); - py_Type cls = argv[0].type; - py_newobject(py_retval(), cls, 0, 0); - return true; -} + void pk_VM__ctor(pk_VM* self) { self->top_frame = NULL; @@ -95,6 +90,7 @@ void pk_VM__ctor(pk_VM* self) { validate(tp_object, pk_VM__new_type(self, "object", 0, NULL, true)); validate(tp_type, pk_VM__new_type(self, "type", 1, NULL, false)); + pk_object__register(); validate(tp_int, pk_VM__new_type(self, "int", tp_object, NULL, false)); validate(tp_float, pk_VM__new_type(self, "float", tp_object, NULL, false)); @@ -166,10 +162,6 @@ void pk_VM__ctor(pk_VM* self) { py_newnotimplemented(&tmp); py_setdict(&self->builtins, py_name("NotImplemented"), &tmp); - /* Do Buildin Bindings*/ - // object.__new__ - py_bindmagic(tp_object, __new__, _py_object__new__); - self->main = *py_newmodule("__main__", NULL); } diff --git a/src/public/py_number.c b/src/public/py_number.c index 0866a5e1..c2162e02 100644 --- a/src/public/py_number.c +++ b/src/public/py_number.c @@ -7,12 +7,12 @@ static bool _py_int##name(int argc, py_Ref argv) { \ PY_CHECK_ARGC(2); \ if(py_isint(&argv[1])) { \ - int64_t lhs = py_toint(&argv[0]); \ - int64_t rhs = py_toint(&argv[1]); \ + py_i64 lhs = py_toint(&argv[0]); \ + py_i64 rhs = py_toint(&argv[1]); \ rint(py_retval(), lhs op rhs); \ } else if(py_isfloat(&argv[1])) { \ - int64_t lhs = py_toint(&argv[0]); \ - double rhs = py_tofloat(&argv[1]); \ + py_i64 lhs = py_toint(&argv[0]); \ + py_f64 rhs = py_tofloat(&argv[1]); \ rfloat(py_retval(), lhs op rhs); \ } else { \ py_newnotimplemented(py_retval()); \ @@ -21,8 +21,8 @@ } \ static bool _py_float##name(int argc, py_Ref argv) { \ PY_CHECK_ARGC(2); \ - double lhs = py_tofloat(&argv[0]); \ - double rhs; \ + py_f64 lhs = py_tofloat(&argv[0]); \ + py_f64 rhs; \ if(py_castfloat(&argv[1], &rhs)) { \ rfloat(py_retval(), lhs op rhs); \ } else { \ @@ -36,7 +36,7 @@ DEF_NUM_BINARY_OP(__sub__, -, py_newint, py_newfloat) DEF_NUM_BINARY_OP(__mul__, *, py_newint, py_newfloat) DEF_NUM_BINARY_OP(__eq__, ==, py_newbool, py_newbool) -DEF_NUM_BINARY_OP(__ne__, ==, py_newbool, py_newbool) +DEF_NUM_BINARY_OP(__ne__, !=, py_newbool, py_newbool) DEF_NUM_BINARY_OP(__lt__, <, py_newbool, py_newbool) DEF_NUM_BINARY_OP(__le__, <=, py_newbool, py_newbool) DEF_NUM_BINARY_OP(__gt__, >, py_newbool, py_newbool) @@ -46,22 +46,22 @@ DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool) static bool _py_int__neg__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - int64_t val = py_toint(&argv[0]); + py_i64 val = py_toint(&argv[0]); py_newint(py_retval(), -val); return true; } static bool _py_float__neg__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - double val = py_tofloat(&argv[0]); + py_f64 val = py_tofloat(&argv[0]); py_newfloat(py_retval(), -val); return true; } static bool _py_int__truediv__(int argc, py_Ref argv) { PY_CHECK_ARGC(2); - int64_t lhs = py_toint(&argv[0]); - double rhs; + py_i64 lhs = py_toint(&argv[0]); + py_f64 rhs; if(py_castfloat(&argv[1], &rhs)) { py_newfloat(py_retval(), lhs / rhs); } else { @@ -72,8 +72,8 @@ static bool _py_int__truediv__(int argc, py_Ref argv) { static bool _py_float__truediv__(int argc, py_Ref argv) { PY_CHECK_ARGC(2); - double lhs = py_tofloat(&argv[0]); - double rhs; + py_f64 lhs = py_tofloat(&argv[0]); + py_f64 rhs; if(py_castfloat(&argv[1], &rhs)) { py_newfloat(py_retval(), lhs / rhs); } else { @@ -87,8 +87,8 @@ static bool _py_float__truediv__(int argc, py_Ref argv) { static bool _py_number__pow__(int argc, py_Ref argv) { PY_CHECK_ARGC(2); if(py_isint(&argv[0]) && py_isint(&argv[1])) { - int64_t lhs = py_toint(&argv[0]); - int64_t rhs = py_toint(&argv[1]); + py_i64 lhs = py_toint(&argv[0]); + py_i64 rhs = py_toint(&argv[1]); if(rhs < 0) { if(lhs == 0) { return ZeroDivisionError("0.0 cannot be raised to a negative power"); @@ -97,7 +97,7 @@ static bool _py_number__pow__(int argc, py_Ref argv) { } } else { // rhs >= 0 - int64_t ret = 1; + py_i64 ret = 1; while(true) { if(rhs & 1) ret *= lhs; rhs >>= 1; @@ -107,7 +107,7 @@ static bool _py_number__pow__(int argc, py_Ref argv) { py_newint(py_retval(), ret); } } else { - double lhs, rhs; + py_f64 lhs, rhs; py_castfloat(&argv[0], &lhs); if(py_castfloat(&argv[1], &rhs)) { py_newfloat(py_retval(), pow(lhs, rhs)); @@ -120,9 +120,9 @@ static bool _py_number__pow__(int argc, py_Ref argv) { static bool _py_int__floordiv__(int argc, py_Ref argv) { PY_CHECK_ARGC(2); - int64_t lhs = py_toint(&argv[0]); + py_i64 lhs = py_toint(&argv[0]); if(py_isint(&argv[1])) { - int64_t rhs = py_toint(&argv[1]); + py_i64 rhs = py_toint(&argv[1]); if(rhs == 0) return -1; py_newint(py_retval(), lhs / rhs); } else { @@ -133,9 +133,9 @@ static bool _py_int__floordiv__(int argc, py_Ref argv) { static bool _py_int__mod__(int argc, py_Ref argv) { PY_CHECK_ARGC(2); - int64_t lhs = py_toint(&argv[0]); + py_i64 lhs = py_toint(&argv[0]); if(py_isint(&argv[1])) { - int64_t rhs = py_toint(&argv[1]); + py_i64 rhs = py_toint(&argv[1]); if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero"); py_newint(py_retval(), lhs % rhs); } else { @@ -146,14 +146,14 @@ static bool _py_int__mod__(int argc, py_Ref argv) { static bool _py_int__invert__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - int64_t val = py_toint(&argv[0]); + py_i64 val = py_toint(&argv[0]); py_newint(py_retval(), ~val); return true; } static bool _py_int__bit_length(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - int64_t x = py_toint(py_arg(0)); + py_i64 x = py_toint(py_arg(0)); if(x < 0) x = -x; int bits = 0; while(x) { @@ -167,9 +167,9 @@ static bool _py_int__bit_length(int argc, py_Ref argv) { #define DEF_INT_BITWISE_OP(name, op) \ static bool _py_int##name(int argc, py_Ref argv) { \ PY_CHECK_ARGC(2); \ - int64_t lhs = py_toint(&argv[0]); \ + py_i64 lhs = py_toint(&argv[0]); \ if(py_isint(&argv[1])) { \ - int64_t rhs = py_toint(&argv[1]); \ + py_i64 rhs = py_toint(&argv[1]); \ py_newint(py_retval(), lhs op rhs); \ } else { \ py_newnotimplemented(py_retval()); \ @@ -187,7 +187,7 @@ DEF_INT_BITWISE_OP(__rshift__, >>) static bool _py_int__repr__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - int64_t val = py_toint(&argv[0]); + py_i64 val = py_toint(&argv[0]); char buf[32]; int size = snprintf(buf, sizeof(buf), "%lld", (long long)val); py_newstrn(py_retval(), buf, size); @@ -196,7 +196,7 @@ static bool _py_int__repr__(int argc, py_Ref argv) { static bool _py_float__repr__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - double val = py_tofloat(&argv[0]); + py_f64 val = py_tofloat(&argv[0]); char buf[32]; int size = snprintf(buf, sizeof(buf), "%f", val); py_newstrn(py_retval(), buf, size); @@ -223,7 +223,7 @@ static py_i64 c11_8bytes__hash(union c11_8bytes u) { static bool _py_int__hash__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - int64_t val = py_toint(&argv[0]); + py_i64 val = py_toint(&argv[0]); union c11_8bytes u = {._i64 = val}; py_newint(py_retval(), c11_8bytes__hash(u)); return true; @@ -231,7 +231,7 @@ static bool _py_int__hash__(int argc, py_Ref argv) { static bool _py_float__hash__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - double val = py_tofloat(&argv[0]); + py_f64 val = py_tofloat(&argv[0]); union c11_8bytes u = {._f64 = val}; py_newint(py_retval(), c11_8bytes__hash(u)); return true; @@ -248,7 +248,7 @@ static bool _py_int__new__(int argc, py_Ref argv) { switch(argv[1].type) { case tp_float: { // int(1.1) == 1 - py_newint(py_retval(), (int64_t)py_tofloat(&argv[1])); + py_newint(py_retval(), (py_i64)py_tofloat(&argv[1])); return true; } case tp_int: { @@ -258,7 +258,7 @@ static bool _py_int__new__(int argc, py_Ref argv) { } case tp_bool: { // int(True) == 1 - py_newint(py_retval(), (int64_t)py_tobool(&argv[1])); + py_newint(py_retval(), (py_i64)py_tobool(&argv[1])); return true; } case tp_str: break; // leave to the next block @@ -340,7 +340,7 @@ static bool _py_float__new__(int argc, py_Ref argv) { } // tp_bool -static bool _py_bool__new__(int argc, py_Ref argv){ +static bool _py_bool__new__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); int res = py_bool(argv); if(res == -1) return false; @@ -348,24 +348,24 @@ static bool _py_bool__new__(int argc, py_Ref argv){ return true; } -static bool _py_bool__hash__(int argc, py_Ref argv){ +static bool _py_bool__hash__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); bool res = py_tobool(argv); py_newint(py_retval(), res); return true; } -static bool _py_bool__repr__(int argc, py_Ref argv){ +static bool _py_bool__repr__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); bool res = py_tobool(argv); py_newstr(py_retval(), res ? "True" : "False"); return true; } -static bool _py_bool__eq__(int argc, py_Ref argv){ +static bool _py_bool__eq__(int argc, py_Ref argv) { PY_CHECK_ARGC(2); bool lhs = py_tobool(&argv[0]); - if(argv[1].type == tp_bool){ + if(argv[1].type == tp_bool) { bool rhs = py_tobool(&argv[1]); py_newbool(py_retval(), lhs == rhs); } else { @@ -374,10 +374,10 @@ static bool _py_bool__eq__(int argc, py_Ref argv){ return true; } -static bool _py_bool__ne__(int argc, py_Ref argv){ +static bool _py_bool__ne__(int argc, py_Ref argv) { PY_CHECK_ARGC(2); bool lhs = py_tobool(&argv[0]); - if(argv[1].type == tp_bool){ + if(argv[1].type == tp_bool) { bool rhs = py_tobool(&argv[1]); py_newbool(py_retval(), lhs != rhs); } else { diff --git a/src/public/py_object.c b/src/public/py_object.c new file mode 100644 index 00000000..b7a4fd13 --- /dev/null +++ b/src/public/py_object.c @@ -0,0 +1,37 @@ +#include "pocketpy/interpreter/vm.h" +#include "pocketpy/pocketpy.h" + +static bool _py_object__new__(int argc, py_Ref argv) { + assert(argc >= 1); + py_Type cls = argv[0].type; + py_newobject(py_retval(), cls, 0, 0); + return true; +} + +static bool _py_object__hash__(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + assert(argv->is_ptr); + py_newint(py_retval(), (py_i64)argv->_obj); + return true; +} + +static bool _py_object__eq__(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + bool res = py_isidentical(py_arg(0), py_arg(1)); + py_newbool(py_retval(), res); + return true; +} + +static bool _py_object__ne__(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + bool res = py_isidentical(py_arg(0), py_arg(1)); + py_newbool(py_retval(), !res); + return true; +} + +void pk_object__register() { + py_bindmagic(tp_object, __new__, _py_object__new__); + py_bindmagic(tp_object, __hash__, _py_object__hash__); + py_bindmagic(tp_object, __eq__, _py_object__eq__); + py_bindmagic(tp_object, __ne__, _py_object__ne__); +} \ No newline at end of file diff --git a/src/public/py_ops.c b/src/public/py_ops.c index 9c1f6bc9..759514cb 100644 --- a/src/public/py_ops.c +++ b/src/public/py_ops.c @@ -43,7 +43,22 @@ int py_bool(const py_Ref val) { } } -bool py_hash(const py_Ref val, int64_t* out) { return 0; } +bool py_hash(const py_Ref val, int64_t* out) { + py_Type t = val->type; + pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data; + do { + py_Ref _hash = &types[t].magic[__hash__]; + py_Ref _eq = &types[t].magic[__eq__]; + if(!py_isnil(_hash) && !py_isnil(_eq)) { + bool ok = py_call(_hash, 1, val); + if(!ok) return false; + *out = py_toint(py_retval()); + return true; + } + t = types[t].base; + } while(t); + return TypeError("unhashable type: '%t'", val->type); +} int py_getattr(const py_Ref self, py_Name name, py_Ref out) { return -1; }