blueloveTH il y a 3 ans
Parent
commit
978e04cdfd
4 fichiers modifiés avec 54 ajouts et 30 suppressions
  1. 21 7
      src/cffi.h
  2. 3 3
      src/common.h
  3. 1 0
      src/pocketpy.h
  4. 29 20
      src/vm.h

+ 21 - 7
src/cffi.h

@@ -2,30 +2,36 @@
 
 #include "common.h"
 #include "vm.h"
+#include <type_traits>
 #include <vector>
 
 namespace pkpy {
 
 template<typename Ret, typename... Params>
-struct ProxyFunction {
+struct NativeProxyFunc {
     using T = Ret(*)(Params...);
     static constexpr int N = sizeof...(Params);
     T func;
-    ProxyFunction(T func) : func(func) {}
+    NativeProxyFunc(T func) : func(func) {}
 
     PyVar operator()(VM* vm, Args& args) {
         if (args.size() != N) vm->TypeError("invalid number of arguments");
-        return call(vm, args, std::make_index_sequence<N>());
+        return call<Ret>(vm, args, std::make_index_sequence<N>());
     }
 
-    template<size_t... Is>
-    PyVar call(VM* vm, Args& args, std::index_sequence<Is...>) {
-        Ret ret = func(py_cast<Params>(vm, args[Is])...);
+    template<typename __Ret, size_t... Is>
+    std::enable_if_t<std::is_void_v<__Ret>, PyVar> call(VM* vm, Args& args, std::index_sequence<Is...>) {
+        func(py_cast<Params>(vm, args[Is])...);
+        return vm->None;
+    }
+
+    template<typename __Ret, size_t... Is>
+    std::enable_if_t<!std::is_void_v<__Ret>, PyVar> call(VM* vm, Args& args, std::index_sequence<Is...>) {
+        __Ret ret = func(py_cast<Params>(vm, args[Is])...);
         return VAR(std::move(ret));
     }
 };
 
-
 struct TypeInfo;
 
 struct MemberInfo{
@@ -304,4 +310,12 @@ void add_module_c(VM* vm){
     });
 }
 
+PyVar py_var(VM* vm, void* p){
+    return VAR_T(Pointer, (char*)p, &_type_infos["void"]);
+}
+
+PyVar py_var(VM* vm, char* p){
+    return VAR_T(Pointer, (char*)p, &_type_infos["char"]);
+}
+
 }   // namespace pkpy

+ 3 - 3
src/common.h

@@ -75,9 +75,9 @@ struct Type {
 #define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
 #endif
 
-const float kLocalsLoadFactor = 0.67;
-const float kInstAttrLoadFactor = 0.67;
-const float kTypeAttrLoadFactor = 0.5;
+const float kLocalsLoadFactor = 0.67f;
+const float kInstAttrLoadFactor = 0.67f;
+const float kTypeAttrLoadFactor = 0.5f;
 
 // do extra check for debug
 // #define PK_EXTRA_CHECK

+ 1 - 0
src/pocketpy.h

@@ -159,6 +159,7 @@ void init_builtins(VM* _vm) {
     _vm->bind_method<1>("object", "__ne__", CPP_LAMBDA(VAR(args[0] != args[1])));
 
     _vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(vm->_t(args[0])));
+    _vm->bind_method<0>("type", "__repr__", CPP_LAMBDA(VAR("<class '" + OBJ_GET(Str, args[0]->attr(__name__)) + "'>")));
 
     _vm->bind_static_method<-1>("range", "__new__", [](VM* vm, Args& args) {
         Range r;

+ 29 - 20
src/vm.h

@@ -73,7 +73,7 @@ public:
     }
 
     PyVar asStr(const PyVar& obj){
-        PyVarOrNull f = getattr(obj, __str__, false);
+        PyVarOrNull f = getattr(obj, __str__, false, true);
         if(f != nullptr) return call(f);
         return asRepr(obj);
     }
@@ -87,7 +87,7 @@ public:
 
     PyVar asIter(const PyVar& obj){
         if(is_type(obj, tp_native_iterator)) return obj;
-        PyVarOrNull iter_f = getattr(obj, __iter__, false);
+        PyVarOrNull iter_f = getattr(obj, __iter__, false, true);
         if(iter_f != nullptr) return call(iter_f);
         TypeError(OBJ_NAME(_t(obj)).escape(true) + " object is not iterable");
         return nullptr;
@@ -122,11 +122,11 @@ public:
     template<typename ArgT>
     inline std::enable_if_t<std::is_same_v<std::decay_t<ArgT>, Args>, PyVar>
     call(const PyVar& obj, const StrName name, ArgT&& args){
-        return call(getattr(obj, name), std::forward<ArgT>(args), no_arg(), false);
+        return call(getattr(obj, name, true, true), std::forward<ArgT>(args), no_arg(), false);
     }
 
     inline PyVar call(const PyVar& obj, StrName name){
-        return call(getattr(obj, name), no_arg(), no_arg(), false);
+        return call(getattr(obj, name, true, true), no_arg(), no_arg(), false);
     }
 
 
@@ -305,7 +305,7 @@ public:
     void init_builtin_types();
     PyVar call(const PyVar& _callable, Args args, const Args& kwargs, bool opCall);
     void unpack_args(Args& args);
-    PyVarOrNull getattr(const PyVar& obj, StrName name, bool throw_err=true);
+    PyVarOrNull getattr(const PyVar& obj, StrName name, bool throw_err=true, bool class_only=false);
     template<typename T>
     void setattr(PyVar& obj, StrName name, T&& value);
     template<int ARGC>
@@ -388,6 +388,17 @@ template<> i64 py_cast<i64>(VM* vm, const PyVar& obj){
 template<> i64 _py_cast<i64>(VM* vm, const PyVar& obj){
     return obj.bits >> 2;
 }
+template<> f64 py_cast<f64>(VM* vm, const PyVar& obj){
+    vm->check_type(obj, vm->tp_float);
+    i64 bits = obj.bits;
+    bits = (bits >> 2) << 2;
+    return __8B(bits)._float;
+}
+template<> f64 _py_cast<f64>(VM* vm, const PyVar& obj){
+    i64 bits = obj.bits;
+    bits = (bits >> 2) << 2;
+    return __8B(bits)._float;
+}
 
 #ifndef PKPY_USE_32_BITS
 template<> int py_cast<int>(VM* vm, const PyVar& obj){
@@ -397,19 +408,18 @@ template<> int py_cast<int>(VM* vm, const PyVar& obj){
 template<> int _py_cast<int>(VM* vm, const PyVar& obj){
     return obj.bits >> 2;
 }
-#endif
-
-template<> f64 py_cast<f64>(VM* vm, const PyVar& obj){
+template<> float py_cast<float>(VM* vm, const PyVar& obj){
     vm->check_type(obj, vm->tp_float);
     i64 bits = obj.bits;
     bits = (bits >> 2) << 2;
     return __8B(bits)._float;
 }
-template<> f64 _py_cast<f64>(VM* vm, const PyVar& obj){
+template<> float _py_cast<float>(VM* vm, const PyVar& obj){
     i64 bits = obj.bits;
     bits = (bits >> 2) << 2;
     return __8B(bits)._float;
 }
+#endif
 
 template<typename T>
 std::enable_if_t<std::is_floating_point_v<T>, PyVar> py_var(VM* vm, T _val){
@@ -466,7 +476,7 @@ const PyVar& VM::asBool(const PyVar& obj){
     if(obj == None) return False;
     if(is_type(obj, tp_int)) return VAR(CAST(i64, obj) != 0);
     if(is_type(obj, tp_float)) return VAR(CAST(f64, obj) != 0.0);
-    PyVarOrNull len_fn = getattr(obj, __len__, false);
+    PyVarOrNull len_fn = getattr(obj, __len__, false, true);
     if(len_fn != nullptr){
         PyVar ret = call(len_fn);
         return VAR(CAST(i64, ret) > 0);
@@ -497,7 +507,6 @@ i64 VM::hash(const PyVar& obj){
 }
 
 PyVar VM::asRepr(const PyVar& obj){
-    if(is_type(obj, tp_type)) return VAR("<class '" + OBJ_GET(Str, obj->attr(__name__)) + "'>");
     return call(obj, __repr__);
 }
 
@@ -654,7 +663,7 @@ PyVar VM::call(const PyVar& _callable, Args args, const Args& kwargs, bool opCal
             obj = call(*new_f, std::move(args), kwargs, false);
         }else{
             obj = new_object(_callable, DummyInstance());
-            PyVarOrNull init_f = getattr(obj, __init__, false);
+            PyVarOrNull init_f = getattr(obj, __init__, false, true);
             if (init_f != nullptr) call(init_f, std::move(args), kwargs, false);
         }
         return obj;
@@ -739,7 +748,7 @@ void VM::unpack_args(Args& args){
     args = Args::from_list(std::move(unpacked));
 }
 
-PyVarOrNull VM::getattr(const PyVar& obj, StrName name, bool throw_err) {
+PyVarOrNull VM::getattr(const PyVar& obj, StrName name, bool throw_err, bool class_only) {
     PyVar* val;
     PyObject* cls;
 
@@ -754,10 +763,12 @@ PyVarOrNull VM::getattr(const PyVar& obj, StrName name, bool throw_err) {
         cls = _t(*root).get();
         for(int i=0; i<depth; i++) cls = cls->attr(__base__).get();
 
-        val = (*root)->attr().try_get(name);
-        if(val != nullptr) return *val;    
+        if(!class_only){
+            val = (*root)->attr().try_get(name);
+            if(val != nullptr) return *val; 
+        }
     }else{
-        if(!obj.is_tagged() && obj->is_attr_valid()){
+        if(!class_only && !obj.is_tagged() && obj->is_attr_valid()){
             val = obj->attr().try_get(name);
             if(val != nullptr) return *val;
         }
@@ -767,10 +778,8 @@ PyVarOrNull VM::getattr(const PyVar& obj, StrName name, bool throw_err) {
     while(cls != None.get()) {
         val = cls->attr().try_get(name);
         if(val != nullptr){
-            PyVarOrNull descriptor = getattr(*val, __get__, false);
-            if(descriptor != nullptr){
-                return call(descriptor, one_arg(obj));
-            }
+            PyVarOrNull descriptor = getattr(*val, __get__, false, true);
+            if(descriptor != nullptr) return call(descriptor, one_arg(obj));
             if(is_type(*val, tp_function) || is_type(*val, tp_native_function)){
                 return VAR(BoundMethod(obj, *val));
             }else{