This commit is contained in:
blueloveTH 2023-03-10 01:40:23 +08:00
parent 75d83787f4
commit 978e04cdfd
4 changed files with 61 additions and 37 deletions

View File

@ -2,30 +2,36 @@
#include "common.h" #include "common.h"
#include "vm.h" #include "vm.h"
#include <type_traits>
#include <vector> #include <vector>
namespace pkpy { namespace pkpy {
template<typename Ret, typename... Params> template<typename Ret, typename... Params>
struct ProxyFunction { struct NativeProxyFunc {
using T = Ret(*)(Params...); using T = Ret(*)(Params...);
static constexpr int N = sizeof...(Params); static constexpr int N = sizeof...(Params);
T func; T func;
ProxyFunction(T func) : func(func) {} NativeProxyFunc(T func) : func(func) {}
PyVar operator()(VM* vm, Args& args) { PyVar operator()(VM* vm, Args& args) {
if (args.size() != N) vm->TypeError("invalid number of arguments"); 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> template<typename __Ret, size_t... Is>
PyVar call(VM* vm, Args& args, std::index_sequence<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])...); 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)); return VAR(std::move(ret));
} }
}; };
struct TypeInfo; struct TypeInfo;
struct MemberInfo{ 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 } // namespace pkpy

View File

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

View File

@ -159,6 +159,7 @@ void init_builtins(VM* _vm) {
_vm->bind_method<1>("object", "__ne__", CPP_LAMBDA(VAR(args[0] != args[1]))); _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_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) { _vm->bind_static_method<-1>("range", "__new__", [](VM* vm, Args& args) {
Range r; Range r;

View File

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