blueloveTH před 1 rokem
rodič
revize
7feb3047e9

+ 1 - 0
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();

+ 22 - 6
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;

+ 27 - 21
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, "<class '%t'>", 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__

+ 2 - 10
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);
 }
 

+ 38 - 38
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 {

+ 37 - 0
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__);
+}

+ 16 - 1
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; }