blueloveTH před 1 rokem
rodič
revize
6e1550213c

+ 5 - 3
include/pocketpy/pocketpy.h

@@ -208,12 +208,14 @@ bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop);
 void py_assign(py_Ref dst, const py_Ref src);
 
 /************* Stack Operations *************/
-/// Returns a reference to the i-th object from the top of the stack.
+/// Return a reference to the i-th object from the top of the stack.
 /// i should be negative, e.g. (-1) means TOS.
 py_StackRef py_peek(int i);
-/// Pushes the object to the stack.
+/// Push the object to the stack.
 void py_push(const py_Ref src);
-/// Pops an object from the stack.
+/// Push a nil object to the stack.
+void py_pushnil();
+/// Pop an object from the stack.
 void py_pop();
 /// Shrink the stack by n.
 void py_shrink(int n);

+ 1 - 0
include/pocketpy/xmacros/magics.h

@@ -9,6 +9,7 @@ MAGIC_METHOD(__iter__)
 MAGIC_METHOD(__next__)
 MAGIC_METHOD(__neg__)
 MAGIC_METHOD(__invert__)
+MAGIC_METHOD(__bool__)
 // logical operators
 MAGIC_METHOD(__contains__)
 /////////////////////////////

+ 28 - 4
src/public/py_ops.c

@@ -4,7 +4,7 @@
 
 bool py_isidentical(const py_Ref lhs, const py_Ref rhs) {
     if(lhs->type != rhs->type) return false;
-    switch(lhs->type){
+    switch(lhs->type) {
         case tp_int: return lhs->_i64 == rhs->_i64;
         case tp_float: return lhs->_f64 == rhs->_f64;
         case tp_bool: return lhs->_bool == rhs->_bool;
@@ -14,10 +14,34 @@ bool py_isidentical(const py_Ref lhs, const py_Ref rhs) {
         case tp_ellipsis: return true;
         // fallback to pointer comparison
         default: return lhs->is_ptr && rhs->is_ptr && lhs->_obj == rhs->_obj;
-    }    
+    }
 }
 
-int py_bool(const py_Ref val) { return 1; }
+int py_bool(const py_Ref val) {
+    switch(val->type) {
+        case tp_bool: return val->_bool;
+        case tp_int: return val->_i64 != 0;
+        case tp_float: return val->_f64 != 0;
+        case tp_none_type: return 0;
+        default: {
+            py_Ref tmp = py_tpfindmagic(val->type, __bool__);
+            if(tmp) {
+                bool ok = py_call(tmp, 1, val);
+                if(!ok) return -1;
+                return py_tobool(py_retval());
+            } else {
+                tmp = py_tpfindmagic(val->type, __len__);
+                if(tmp) {
+                    bool ok = py_call(tmp, 1, val);
+                    if(!ok) return -1;
+                    return py_toint(py_retval());
+                } else {
+                    return 1;  // True
+                }
+            }
+        }
+    }
+}
 
 bool py_hash(const py_Ref val, int64_t* out) { return 0; }
 
@@ -37,7 +61,7 @@ bool py_delitem(py_Ref self, const py_Ref key) { return -1; }
     int py_##name(const py_Ref lhs, const py_Ref rhs) {                                            \
         bool ok = py_binaryop(lhs, rhs, op, rop);                                                  \
         if(!ok) return -1;                                                                         \
-        return py_tobool(py_retval());                                                         \
+        return py_tobool(py_retval());                                                             \
     }
 
 COMPARE_OP_IMPL(eq, __eq__, __eq__)

+ 5 - 0
src/public/stack_ops.c

@@ -64,6 +64,11 @@ void py_push(const py_Ref src){
     *vm->stack.sp++ = *src;
 }
 
+void py_pushnil(){
+    pk_VM* vm = pk_current_vm;
+    py_newnil(vm->stack.sp++);
+}
+
 py_Ref py_pushtmp(){
     pk_VM* vm = pk_current_vm;
     py_newnil(vm->stack.sp++);

+ 14 - 6
src/public/vm.c

@@ -184,11 +184,22 @@ bool py_exec(const char* source) { return pk_VM__exec(pk_current_vm, source, "<e
 
 bool py_eval(const char* source) { return pk_VM__exec(pk_current_vm, source, "<eval>", EVAL_MODE); }
 
-bool py_exec2(const char* source, const char* filename, enum CompileMode mode){
+bool py_exec2(const char* source, const char* filename, enum CompileMode mode) {
     return pk_VM__exec(pk_current_vm, source, filename, mode);
 }
 
-bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; }
+bool py_call(py_Ref f, int argc, py_Ref argv) {
+    if(f->type == tp_nativefunc) {
+        return f->_cfunc(argc, argv);
+    } else {
+        pk_VM* vm = pk_current_vm;
+        py_push(f);
+        py_pushnil();
+        for(int i = 0; i < argc; i++)
+            py_push(py_offset(argv, i));
+        return pk_VM__vectorcall(vm, argc, 0, false) == RES_ERROR;
+    }
+}
 
 bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
 
@@ -285,9 +296,6 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv) {
     assert(argc >= 1);
     assert(py_ismagicname(name));
     py_Ref tmp = py_tpfindmagic(argv->type, name);
-    if(!tmp){
-        return AttributeError(argv, name);
-    }
-    if(tmp->type == tp_nativefunc) return tmp->_cfunc(argc, argv);
+    if(!tmp) return AttributeError(argv, name);
     return py_call(tmp, argc, argv);
 }