blueloveTH 1 éve
szülő
commit
4860c08e03
6 módosított fájl, 165 hozzáadás és 150 törlés
  1. 22 11
      include/pocketpy/pocketpy.h
  2. 63 64
      src/interpreter/ceval.c
  3. 51 51
      src/interpreter/py_number.c
  4. 16 17
      src/public/py_ops.c
  5. 5 4
      src/public/values.c
  6. 8 3
      src/public/vm.c

+ 22 - 11
include/pocketpy/pocketpy.h

@@ -10,12 +10,18 @@ typedef uint16_t py_Name;
 typedef int16_t py_Type;
 typedef py_TValue* py_Ref;
 typedef struct py_Str py_Str;
-typedef int (*py_CFunction)(int argc, py_Ref argv);
 
 typedef struct py_Error {
     py_Type type;
 } 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.
+/// @return true if the function is successful.
+typedef bool (*py_CFunction)(int argc, py_TValue* argv, py_TValue* out);
+
 typedef enum BindType {
     BindType_FUNCTION,
     BindType_STATICMETHOD,
@@ -64,6 +70,8 @@ void py_newnativefunc2(py_Ref out,
                        const char* docstring,
                        const py_Ref upvalue);
 
+void py_newnotimplemented(py_Ref out);
+
 /// Create a new object.
 /// @param out output reference.
 /// @param type type of the object.
@@ -79,7 +87,6 @@ void py_pushstrn(const char*, int);
 
 void py_pushnone();
 void py_pushnull();
-void py_push_notimplemented();
 
 /************* Type Cast *************/
 int64_t py_toint(const py_Ref);
@@ -101,7 +108,7 @@ bool py_istype(const py_Ref, py_Type);
 // bool py_issubclass(py_Type derived, py_Type base);
 
 /************* References *************/
-#define py_arg(i)   (py_Ref)((char*)argv+((i)<<4))
+#define py_arg(i)       (py_Ref)((char*)argv+((i)<<4))
 
 py_Ref py_getreg(int i);
 void py_setreg(int i, const py_Ref val);
@@ -120,9 +127,9 @@ bool py_getattr(const py_Ref self, py_Name name, py_Ref out);
 /// Gets the unbound method of the object.
 bool py_getunboundmethod(const py_Ref self, py_Name name, bool fallback, py_Ref out, py_Ref out_self);
 /// Sets the attribute of the object.
-int py_setattr(py_Ref self, py_Name name, const py_Ref val);
+bool py_setattr(py_Ref self, py_Name name, const py_Ref val);
 /// Deletes the attribute of the object.
-int py_delattr(py_Ref self, py_Name name);
+bool py_delattr(py_Ref self, py_Name name);
 
 /// Equivalent to `*dst = *src`.
 void py_assign(py_Ref dst, const py_Ref src);
@@ -163,14 +170,18 @@ void py_Error__print(py_Error*);
 /************* Operators *************/
 int py_eq(const py_Ref, const py_Ref);
 int py_le(const py_Ref, const py_Ref);
-int py_hash(const py_Ref, int64_t* out);
+bool py_hash(const py_Ref, int64_t* out);
+
+bool py_str(const py_Ref, py_Ref out);
+bool py_repr(const py_Ref, py_Ref out);
 
-int py_str(const py_Ref);
-int py_repr(const py_Ref);
+/// A stack operation that calls a function.
+/// It consumes `argc + kwargc` arguments from the stack.
+/// The result will be set to `vm->last_retval`.
+int pk_vectorcall(int argc, int kwargc, bool op_call);
 
-int py_vectorcall(int argc, int kwargc);
-int py_call(py_Ref f, ...);
-int py_callmethod(py_Ref self, py_Name name, ...);
+bool py_call(py_Ref f, ...);
+bool py_callmethod(py_Ref self, py_Name name, ...);
 
 #define py_isnull(self) ((self)->type == 0)
 

+ 63 - 64
src/interpreter/ceval.c

@@ -38,28 +38,19 @@ int NameError(py_Name name) { return -1; }
 #define POPX() (*--self->stack.sp)
 #define SP() (self->stack.sp)
 
-static void pack_stack_values(int n) {
-    assert(n > 1);
-    pk_VM* self = pk_current_vm;
-    py_TValue tmp;
-    py_newtuple(&tmp, n);
-    for(int i = 0; i < n; i++)
-        py_tuple__setitem(&tmp, i, SP() - n + i);
-    STACK_SHRINK(n);
-    PUSH(&tmp);
-}
-
-// n == 1 is the most likely result
-#define HANDLE_RETVAL(n)                                                                           \
-    if(n != 1) {                                                                                   \
-        if(n == 0) {                                                                               \
-            PUSH(&self->None);                                                                     \
-        } else if(n > 1) {                                                                         \
-            pack_stack_values(n);                                                                  \
-        } else {                                                                                   \
-            goto __ERROR;                                                                          \
+#define vectorcall_opcall(n)                                                                       \
+    do {                                                                                           \
+        pk_FrameResult res = pk_vectorcall(n, 0, true);                                            \
+        switch(res) {                                                                              \
+            case RES_RETURN: PUSH(&self->last_retval); break;                                      \
+            case RES_CALL:                                                                         \
+                frame = self->top_frame;                                                           \
+                PUSH(&self->last_retval);                                                          \
+                goto __NEXT_FRAME;                                                                 \
+            case RES_ERROR: goto __ERROR;                                                          \
+            default: PK_UNREACHABLE();                                                             \
         }                                                                                          \
-    }
+    } while(0)
 
 pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
     Frame* frame = self->top_frame;
@@ -113,10 +104,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             }
             case OP_PRINT_EXPR:
                 if(TOP()->type != tp_none_type) {
-                    int err = py_repr(TOP());
-                    if(err) goto __ERROR;
-                    self->_stdout("%s\n", py_tostr(TOP()));
-                    POP();
+                    py_TValue tmp;
+                    if(py_repr(TOP(), &tmp)) self->_stdout("%s\n", py_tostr(&tmp));
                 }
                 POP();
                 DISPATCH();
@@ -258,11 +247,21 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             }
             case OP_LOAD_SUBSCR: {
                 // [a, b] -> a[b]
-                int n = py_callmethod(SECOND(), __getitem__, TOP());
-                HANDLE_RETVAL(n);
-                // [a, b, retval]
-                *THIRD() = *TOP();  // [retval, b, retval]
-                STACK_SHRINK(2);    // [retval]
+                pk_TypeInfo* ti = pk_tpinfo(SECOND());
+                if(ti->m__getitem__) {
+                    if(!ti->m__getitem__(2, SECOND(), SECOND())) goto __ERROR;
+                } else {
+                    if(!py_callmethod(SECOND(), __getitem__, TOP())) goto __ERROR;
+                    // // [a, b] -> [?, a, b]
+                    // PUSH(TOP());           // [a, b, b]
+                    // *SECOND() = *THIRD();  // [a, a, b]
+                    // bool ok = py_getunboundmethod(SECOND(), __getitem__, false, THIRD(),
+                    // SECOND()); if(!ok) {
+                    //     // __getitem__ not found
+                    //     goto __ERROR;
+                    // }
+                    // py_vectorcall(2, 0, );
+                }
                 DISPATCH();
             }
             case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH();
@@ -300,17 +299,18 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             }
             case OP_STORE_SUBSCR: {
                 // [val, a, b] -> a[b] = val
-                py_TValue* backup = SP();
+                pk_TypeInfo* ti = pk_tpinfo(SECOND());
                 PUSH(THIRD());  // [val, a, b, val]
-                bool ok = py_getunboundmethod(THIRD(), __setitem__, false, FOURTH(), THIRD());
-                if(!ok) {
-                    // __setitem__ not found
-                    goto __ERROR;
+                if(ti->m__setitem__) {
+                    if(!ti->m__setitem__(3, THIRD(), FOURTH())) goto __ERROR;
+                    STACK_SHRINK(3);  // [retval]
+                } else {
+                    bool ok = py_getunboundmethod(THIRD(), __setitem__, false, FOURTH(), THIRD());
+                    if(!ok) goto __ERROR;
+                    // [__setitem__, self, b, val]
+                    vectorcall_opcall(3);
+                    POP();  // discard retval
                 }
-                // [__setitem__, self, b, val]
-                int n = py_vectorcall(3, 0);
-                if(n < 0) goto __ERROR;
-                SP() = backup;  // discard retval if any
                 DISPATCH();
             }
             case OP_DELETE_FAST: {
@@ -359,32 +359,36 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             }
 
             case OP_DELETE_ATTR: {
-                int err = py_delattr(TOP(), byte.arg);
-                if(err) goto __ERROR;
-                POP();
+                if(!py_delattr(TOP(), byte.arg)) goto __ERROR;
                 DISPATCH();
             }
 
             case OP_DELETE_SUBSCR: {
                 // [a, b] -> del a[b]
-                py_Ref backup = SP();
-                int n = py_callmethod(SECOND(), __delitem__, TOP());
-                if(n < 0) { goto __ERROR; }
-                SP() = backup;  // discard retval if any
+                pk_TypeInfo* ti = pk_tpinfo(SECOND());
+                if(ti->m__delitem__) {
+                    if(!ti->m__delitem__(2, SECOND(), SECOND())) goto __ERROR;
+                    POP();
+                } else {
+                    PUSH(TOP());           // [a, b, b]
+                    *SECOND() = *THIRD();  // [a, a, b]
+                    bool ok = py_getunboundmethod(SECOND(), __delitem__, false, THIRD(), SECOND());
+                    // [__delitem__, self, b]
+                    if(!ok) goto __ERROR;
+                    vectorcall_opcall(2);
+                    POP();  // discard retval
+                }
                 DISPATCH();
             }
 
                 /*****************************************/
 
             case OP_BUILD_LONG: {
-                py_Ref _0 = py_getdict(&self->builtins, pk_id_long);
-                assert(_0 != NULL);
-                int n = py_call(_0, TOP());
-                if(n < 0) goto __ERROR;
-                assert(n == 1);
-                // [x, long(x)]
-                *SECOND() = *TOP();  // [long(x), long(x)]
-                POP();               // [long(x)]
+                // [x]
+                py_Ref f = py_getdict(&self->builtins, pk_id_long);
+                assert(f != NULL);
+                if(!py_call(f, TOP())) goto __ERROR;
+                *TOP() = self->last_retval;
                 DISPATCH();
             }
 
@@ -393,19 +397,15 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 assert(_0 != NULL);
                 py_TValue zero;
                 py_newint(&zero, 0);
-                int n = py_call(_0, &zero, TOP());
-                if(n < 0) goto __ERROR;
-                assert(n == 1);
-                // [x, complex(0, x)]
-                *SECOND() = *TOP();  // [complex(0, x), complex(0, x)]
-                POP();               // [complex(0, x)]
+                if(!py_call(_0, &zero, TOP())) goto __ERROR;
+                *TOP() = self->last_retval;
                 DISPATCH();
             }
             case OP_BUILD_BYTES: {
                 py_Str* s = py_touserdata(TOP());
                 unsigned char* p = (unsigned char*)malloc(s->size);
                 memcpy(p, py_Str__data(s), s->size);
-                py_newbytes(SP()++, p, s->size);
+                py_newbytes(TOP(), p, s->size);
                 DISPATCH();
             }
             case OP_BUILD_TUPLE: {
@@ -461,14 +461,13 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             // }
             /**************************** */
             case OP_RETURN_VALUE: {
-                py_TValue tmp = byte.arg == BC_NOARG ? POPX() : self->None;
+                self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None;
                 pk_VM__pop_frame(self);
                 if(frame == base_frame) {  // [ frameBase<- ]
-                    self->last_retval = tmp;
                     return RES_RETURN;
                 } else {
                     frame = self->top_frame;
-                    PUSH(&tmp);
+                    PUSH(&self->last_retval);
                     goto __NEXT_FRAME;
                 }
                 DISPATCH();

+ 51 - 51
src/interpreter/py_number.c

@@ -40,29 +40,29 @@
 // }
 
 #define DEF_NUM_BINARY_OP(name, op)                                                                \
-    static int _py_int##name(int argc, py_Ref argv) {                                              \
+    static bool _py_int##name(int argc, py_Ref argv, py_Ref out) {                                 \
         if(py_isint(&argv[1])) {                                                                   \
             int64_t lhs = py_toint(&argv[0]);                                                      \
             int64_t rhs = py_toint(&argv[1]);                                                      \
-            py_pushint(lhs op rhs);                                                                \
+            py_newint(out, lhs op rhs);                                                            \
         } else if(py_isfloat(&argv[1])) {                                                          \
             int64_t lhs = py_toint(&argv[0]);                                                      \
             double rhs = py_tofloat(&argv[1]);                                                     \
-            py_pushfloat(lhs op rhs);                                                              \
+            py_newfloat(out, lhs op rhs);                                                          \
         } else {                                                                                   \
-            py_push_notimplemented();                                                              \
+            py_newnotimplemented(out);                                                             \
         }                                                                                          \
-        return 1;                                                                                  \
+        return true;                                                                               \
     }                                                                                              \
-    static int _py_float##name(int argc, py_Ref argv) {                                            \
+    static bool _py_float##name(int argc, py_Ref argv, py_Ref out) {                               \
         double lhs = py_tofloat(&argv[0]);                                                         \
         double rhs;                                                                                \
         if(py_castfloat(&argv[1], &rhs)) {                                                         \
-            py_pushfloat(lhs op rhs);                                                              \
+            py_newfloat(out, lhs op rhs);                                                          \
         } else {                                                                                   \
-            py_push_notimplemented();                                                              \
+            py_newnotimplemented(out);                                                             \
         }                                                                                          \
-        return 1;                                                                                  \
+        return true;                                                                               \
     }
 
 DEF_NUM_BINARY_OP(__add__, +)
@@ -77,51 +77,51 @@ DEF_NUM_BINARY_OP(__ge__, >=)
 
 #undef DEF_NUM_BINARY_OP
 
-static int _py_int__neg__(int argc, py_Ref argv) {
+static bool _py_int__neg__(int argc, py_Ref argv, py_Ref out) {
     int64_t val = py_toint(&argv[0]);
-    py_pushint(-val);
-    return 1;
+    py_newint(out, -val);
+    return true;
 }
 
-static int _py_float__neg__(int argc, py_Ref argv) {
+static bool _py_float__neg__(int argc, py_Ref argv, py_Ref out) {
     double val = py_tofloat(&argv[0]);
-    py_pushfloat(-val);
-    return 1;
+    py_newfloat(out, -val);
+    return true;
 }
 
-static int _py_int__truediv__(int argc, py_Ref argv) {
+static bool _py_int__truediv__(int argc, py_Ref argv, py_Ref out) {
     int64_t lhs = py_toint(&argv[0]);
     double rhs;
     if(py_castfloat(&argv[1], &rhs)) {
-        py_pushfloat(lhs / rhs);
+        py_newfloat(out, lhs / rhs);
     } else {
-        py_push_notimplemented();
+        py_newnotimplemented(out);
     }
-    return 1;
+    return true;
 }
 
-static int _py_float__truediv__(int argc, py_Ref argv) {
+static bool _py_float__truediv__(int argc, py_Ref argv, py_Ref out) {
     double lhs = py_tofloat(&argv[0]);
     double rhs;
     if(py_castfloat(&argv[1], &rhs)) {
-        py_pushfloat(lhs / rhs);
+        py_newfloat(out, lhs / rhs);
     } else {
-        py_push_notimplemented();
+        py_newnotimplemented(out);
     }
-    return 1;
+    return true;
 }
 
-static int _py_number__pow__(int argc, py_Ref argv) {
+#define ZeroDivisionError(msg) false
+
+static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
     if(py_isint(&argv[0]) && py_isint(&argv[1])) {
         int64_t lhs = py_toint(&argv[0]);
         int64_t rhs = py_toint(&argv[1]);
         if(rhs < 0) {
             if(lhs == 0) {
-                // py_pusherror("0.0 cannot be raised to a negative power");
-                // TODO: ZeroDivisionError
-                return -1;
+                return ZeroDivisionError("0.0 cannot be raised to a negative power");
             } else {
-                py_pushfloat(pow(lhs, rhs));
+                py_newfloat(out, pow(lhs, rhs));
             }
         } else {
             int64_t ret = 1;
@@ -130,51 +130,51 @@ static int _py_number__pow__(int argc, py_Ref argv) {
                 lhs *= lhs;
                 rhs >>= 1;
             }
-            py_pushint(ret);
+            py_newint(out, ret);
         }
     } else {
         double lhs, rhs;
         py_castfloat(&argv[0], &lhs);
         if(py_castfloat(&argv[1], &rhs)) {
-            py_pushfloat(pow(lhs, rhs));
+            py_newfloat(out, pow(lhs, rhs));
         } else {
-            py_push_notimplemented();
+            py_newnotimplemented(out);
         }
     }
-    return 1;
+    return true;
 }
 
-static int _py_int__floordiv__(int argc, py_Ref argv) {
+static bool _py_int__floordiv__(int argc, py_Ref argv, py_Ref out) {
     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_pushint(lhs / rhs);
+        py_newint(out, lhs / rhs);
     } else {
-        py_push_notimplemented();
+        py_newnotimplemented(out);
     }
-    return 1;
+    return true;
 }
 
-static int _py_int__mod__(int argc, py_Ref argv) {
+static bool _py_int__mod__(int argc, py_Ref argv, py_Ref out) {
     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_pushint(lhs % rhs);
+        if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
+        py_newint(out, lhs % rhs);
     } else {
-        py_push_notimplemented();
+        py_newnotimplemented(out);
     }
-    return 1;
+    return true;
 }
 
-static int _py_int__invert__(int argc, py_Ref argv) {
+static bool _py_int__invert__(int argc, py_Ref argv, py_Ref out) {
     int64_t val = py_toint(&argv[0]);
-    py_pushint(~val);
-    return 1;
+    py_newint(out, ~val);
+    return true;
 }
 
-static int _py_int__bit_length(int argc, py_Ref argv) {
+static bool _py_int__bit_length(int argc, py_Ref argv, py_Ref out) {
     int64_t x = py_toint(py_arg(0));
     if(x < 0) x = -x;
     int bits = 0;
@@ -182,20 +182,20 @@ static int _py_int__bit_length(int argc, py_Ref argv) {
         x >>= 1;
         bits++;
     }
-    py_pushint(bits);
-    return 1;
+    py_newint(out, bits);
+    return true;
 }
 
 #define DEF_INT_BITWISE_OP(name, op)                                                               \
-    static int _py_int##name(int argc, py_Ref argv) {                                              \
+    static bool _py_int##name(int argc, py_Ref argv, py_Ref out) {                                 \
         int64_t lhs = py_toint(&argv[0]);                                                          \
         if(py_isint(&argv[1])) {                                                                   \
             int64_t rhs = py_toint(&argv[1]);                                                      \
-            py_pushint(lhs op rhs);                                                                \
+            py_newint(out, lhs op rhs);                                                            \
         } else {                                                                                   \
-            py_push_notimplemented();                                                              \
+            py_newnotimplemented(out);                                                             \
         }                                                                                          \
-        return 1;                                                                                  \
+        return true;                                                                               \
     }
 
 DEF_INT_BITWISE_OP(__and__, &)

+ 16 - 17
src/public/py_ops.c

@@ -5,24 +5,23 @@ 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_hash(const py_Ref val, int64_t* out) { return 0; }
-
-int py_str(const py_Ref val) { return 0; }
-
-int py_repr(const py_Ref val) {
-    const pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, val->type);
-    if(ti->m__repr__) return ti->m__repr__(1, val);
-    return py_callmethod(val, __repr__);
+bool py_hash(const py_Ref val, int64_t* out) { return 0; }
+
+bool py_str(const py_Ref val, py_Ref out) { return 0; }
+
+bool py_repr(const py_Ref val, py_Ref out) {
+    const pk_TypeInfo* ti = pk_tpinfo(val);
+    if(ti->m__repr__) return ti->m__repr__(1, val, out);
+    bool ok = py_callmethod(val, __repr__);
+    if(ok) {
+        *out = pk_current_vm->last_retval;
+        return true;
+    }
+    return false;
 }
 
-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; }
 
-int py_setattr(py_Ref self, py_Name name, const py_Ref val){
-    return -1;
-}
+bool py_setattr(py_Ref self, py_Name name, const py_Ref val) { return -1; }
 
-int py_delattr(py_Ref self, py_Name name){
-    return -1;
-}
+bool py_delattr(py_Ref self, py_Name name) { return -1; }

+ 5 - 4
src/public/values.c

@@ -80,6 +80,11 @@ void py_newnativefunc2(py_Ref out,
                        const char* docstring,
                        const py_Ref upvalue) {}
 
+void py_newnotimplemented(py_Ref out) {
+    pk_VM* vm = pk_current_vm;
+    *out = vm->NotImplemented;
+}
+
 void py_newobject(py_Ref out, py_Type type, int slots, int udsize){
     pk_ManagedHeap* heap = &pk_current_vm->heap;
     PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize);
@@ -103,7 +108,3 @@ void py_pushnone() { py_newnone(pk_current_vm->stack.sp++); }
 
 void py_pushnull() { py_newnull(pk_current_vm->stack.sp++); }
 
-void py_push_notimplemented() {
-    pk_VM* vm = pk_current_vm;
-    *vm->stack.sp++ = vm->NotImplemented;
-}

+ 8 - 3
src/public/vm.c

@@ -47,18 +47,23 @@ int py_eval(const char* source, py_Ref out) {
     PK_UNREACHABLE();
 }
 
-int py_call(py_Ref callable, ...){
+bool py_call(py_Ref callable, ...){
     return -1;
 }
 
-int py_callmethod(py_Ref self, py_Name name, ...){
+bool py_callmethod(py_Ref self, py_Name name, ...){
     return -1;
 }
 
-int py_vectorcall(int argc, int kwargc){
+int pk_vectorcall(int argc, int kwargc, bool op_call){
     return -1;
 }
 
 bool py_getunboundmethod(const py_Ref self, py_Name name, bool fallback, py_Ref out, py_Ref out_self){
     return -1;
+}
+
+pk_TypeInfo* pk_tpinfo(const py_Ref self){
+    pk_VM* vm = pk_current_vm;
+    return c11__at(pk_TypeInfo, &vm->types, self->type);
 }