diff --git a/src/cffi.h b/src/cffi.h index ca9b6f3f..1fd0f371 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -2,30 +2,36 @@ #include "common.h" #include "vm.h" +#include #include namespace pkpy { template -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()); + return call(vm, args, std::make_index_sequence()); } - template - PyVar call(VM* vm, Args& args, std::index_sequence) { - Ret ret = func(py_cast(vm, args[Is])...); + template + std::enable_if_t, PyVar> call(VM* vm, Args& args, std::index_sequence) { + func(py_cast(vm, args[Is])...); + return vm->None; + } + + template + std::enable_if_t, PyVar> call(VM* vm, Args& args, std::index_sequence) { + __Ret ret = func(py_cast(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 \ No newline at end of file diff --git a/src/common.h b/src/common.h index f5bdf49e..6b8a8d2f 100644 --- a/src/common.h +++ b/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 diff --git a/src/pocketpy.h b/src/pocketpy.h index 1cce096f..5ef4a8c4 100644 --- a/src/pocketpy.h +++ b/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("attr(__name__)) + "'>"))); _vm->bind_static_method<-1>("range", "__new__", [](VM* vm, Args& args) { Range r; diff --git a/src/vm.h b/src/vm.h index 60a41622..c439d732 100644 --- a/src/vm.h +++ b/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 inline std::enable_if_t, Args>, PyVar> call(const PyVar& obj, const StrName name, ArgT&& args){ - return call(getattr(obj, name), std::forward(args), no_arg(), false); + return call(getattr(obj, name, true, true), std::forward(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 void setattr(PyVar& obj, StrName name, T&& value); template @@ -388,17 +388,6 @@ template<> i64 py_cast(VM* vm, const PyVar& obj){ template<> i64 _py_cast(VM* vm, const PyVar& obj){ return obj.bits >> 2; } - -#ifndef PKPY_USE_32_BITS -template<> int py_cast(VM* vm, const PyVar& obj){ - vm->check_type(obj, vm->tp_int); - return obj.bits >> 2; -} -template<> int _py_cast(VM* vm, const PyVar& obj){ - return obj.bits >> 2; -} -#endif - template<> f64 py_cast(VM* vm, const PyVar& obj){ vm->check_type(obj, vm->tp_float); i64 bits = obj.bits; @@ -411,6 +400,27 @@ template<> f64 _py_cast(VM* vm, const PyVar& obj){ return __8B(bits)._float; } +#ifndef PKPY_USE_32_BITS +template<> int py_cast(VM* vm, const PyVar& obj){ + vm->check_type(obj, vm->tp_int); + return obj.bits >> 2; +} +template<> int _py_cast(VM* vm, const PyVar& obj){ + return obj.bits >> 2; +} +template<> float py_cast(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<> float _py_cast(VM* vm, const PyVar& obj){ + i64 bits = obj.bits; + bits = (bits >> 2) << 2; + return __8B(bits)._float; +} +#endif + template std::enable_if_t, PyVar> py_var(VM* vm, T _val){ f64 val = static_cast(_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("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; iattr(__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{