mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-25 14:00:18 +00:00
...
This commit is contained in:
parent
efb2385f3e
commit
be370e601c
114
src/cffi.h
114
src/cffi.h
@ -5,72 +5,72 @@
|
|||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
template<typename Ret, typename... Params>
|
// template<typename Ret, typename... Params>
|
||||||
struct NativeProxyFunc {
|
// struct NativeProxyFunc {
|
||||||
static constexpr int N = sizeof...(Params);
|
// static constexpr int N = sizeof...(Params);
|
||||||
using _Fp = Ret(*)(Params...);
|
// using _Fp = Ret(*)(Params...);
|
||||||
_Fp func;
|
// _Fp func;
|
||||||
NativeProxyFunc(_Fp func) : func(func) {}
|
// NativeProxyFunc(_Fp func) : func(func) {}
|
||||||
|
|
||||||
PyObject* operator()(VM* vm, ArgsView args) {
|
// PyObject* operator()(VM* vm, ArgsView args) {
|
||||||
if (args.size() != N) {
|
// if (args.size() != N) {
|
||||||
vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(args.size()));
|
// vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(args.size()));
|
||||||
}
|
// }
|
||||||
return call<Ret>(vm, args, std::make_index_sequence<N>());
|
// return call<Ret>(vm, args, std::make_index_sequence<N>());
|
||||||
}
|
// }
|
||||||
|
|
||||||
template<typename __Ret, size_t... Is>
|
// template<typename __Ret, size_t... Is>
|
||||||
std::enable_if_t<std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
// std::enable_if_t<std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
||||||
func(py_cast<Params>(vm, args[Is])...);
|
// func(py_cast<Params>(vm, args[Is])...);
|
||||||
return vm->None;
|
// return vm->None;
|
||||||
}
|
// }
|
||||||
|
|
||||||
template<typename __Ret, size_t... Is>
|
// template<typename __Ret, size_t... Is>
|
||||||
std::enable_if_t<!std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
// std::enable_if_t<!std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
||||||
__Ret ret = func(py_cast<Params>(vm, args[Is])...);
|
// __Ret ret = func(py_cast<Params>(vm, args[Is])...);
|
||||||
return VAR(std::move(ret));
|
// return VAR(std::move(ret));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
template<typename Ret, typename T, typename... Params>
|
// template<typename Ret, typename T, typename... Params>
|
||||||
struct NativeProxyMethod {
|
// struct NativeProxyMethod {
|
||||||
static constexpr int N = sizeof...(Params);
|
// static constexpr int N = sizeof...(Params);
|
||||||
using _Fp = Ret(T::*)(Params...);
|
// using _Fp = Ret(T::*)(Params...);
|
||||||
_Fp func;
|
// _Fp func;
|
||||||
NativeProxyMethod(_Fp func) : func(func) {}
|
// NativeProxyMethod(_Fp func) : func(func) {}
|
||||||
|
|
||||||
PyObject* operator()(VM* vm, ArgsView args) {
|
// PyObject* operator()(VM* vm, ArgsView args) {
|
||||||
int actual_size = args.size() - 1;
|
// int actual_size = args.size() - 1;
|
||||||
if (actual_size != N) {
|
// if (actual_size != N) {
|
||||||
vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(actual_size));
|
// vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(actual_size));
|
||||||
}
|
// }
|
||||||
return call<Ret>(vm, args, std::make_index_sequence<N>());
|
// return call<Ret>(vm, args, std::make_index_sequence<N>());
|
||||||
}
|
// }
|
||||||
|
|
||||||
template<typename __Ret, size_t... Is>
|
// template<typename __Ret, size_t... Is>
|
||||||
std::enable_if_t<std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
// std::enable_if_t<std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
||||||
T& self = py_cast<T&>(vm, args[0]);
|
// T& self = py_cast<T&>(vm, args[0]);
|
||||||
(self.*func)(py_cast<Params>(vm, args[Is+1])...);
|
// (self.*func)(py_cast<Params>(vm, args[Is+1])...);
|
||||||
return vm->None;
|
// return vm->None;
|
||||||
}
|
// }
|
||||||
|
|
||||||
template<typename __Ret, size_t... Is>
|
// template<typename __Ret, size_t... Is>
|
||||||
std::enable_if_t<!std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
// std::enable_if_t<!std::is_void_v<__Ret>, PyObject*> call(VM* vm, ArgsView args, std::index_sequence<Is...>) {
|
||||||
T& self = py_cast<T&>(vm, args[0]);
|
// T& self = py_cast<T&>(vm, args[0]);
|
||||||
__Ret ret = (self.*func)(py_cast<Params>(vm, args[Is+1])...);
|
// __Ret ret = (self.*func)(py_cast<Params>(vm, args[Is+1])...);
|
||||||
return VAR(std::move(ret));
|
// return VAR(std::move(ret));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
template<typename Ret, typename... Params>
|
// template<typename Ret, typename... Params>
|
||||||
auto native_proxy_callable(Ret(*func)(Params...)) {
|
// auto native_proxy_callable(Ret(*func)(Params...)) {
|
||||||
return NativeProxyFunc<Ret, Params...>(func);
|
// return NativeProxyFunc<Ret, Params...>(func);
|
||||||
}
|
// }
|
||||||
|
|
||||||
template<typename Ret, typename T, typename... Params>
|
// template<typename Ret, typename T, typename... Params>
|
||||||
auto native_proxy_callable(Ret(T::*func)(Params...)) {
|
// auto native_proxy_callable(Ret(T::*func)(Params...)) {
|
||||||
return NativeProxyMethod<Ret, T, Params...>(func);
|
// return NativeProxyMethod<Ret, T, Params...>(func);
|
||||||
}
|
// }
|
||||||
|
|
||||||
struct VoidP{
|
struct VoidP{
|
||||||
PY_CLASS(VoidP, c, void_p)
|
PY_CLASS(VoidP, c, void_p)
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|||||||
@ -12,18 +12,14 @@ struct Function;
|
|||||||
class VM;
|
class VM;
|
||||||
|
|
||||||
typedef PyObject* (*NativeFuncC)(VM*, ArgsView);
|
typedef PyObject* (*NativeFuncC)(VM*, ArgsView);
|
||||||
typedef std::function<PyObject*(VM*, ArgsView)> NativeFuncCpp;
|
|
||||||
|
|
||||||
typedef shared_ptr<CodeObject> CodeObject_;
|
typedef shared_ptr<CodeObject> CodeObject_;
|
||||||
|
|
||||||
struct NativeFunc {
|
struct NativeFunc {
|
||||||
NativeFuncC f;
|
NativeFuncC f;
|
||||||
NativeFuncCpp f_cpp;
|
|
||||||
int argc; // DONOT include self
|
int argc; // DONOT include self
|
||||||
bool method;
|
bool method;
|
||||||
|
|
||||||
NativeFunc(NativeFuncC f, int argc, bool method) : f(f), argc(argc), method(method) {}
|
NativeFunc(NativeFuncC f, int argc, bool method) : f(f), argc(argc), method(method) {}
|
||||||
NativeFunc(NativeFuncCpp f, int argc, bool method) : f(nullptr), f_cpp(f), argc(argc), method(method) {}
|
|
||||||
PyObject* operator()(VM* vm, ArgsView args) const;
|
PyObject* operator()(VM* vm, ArgsView args) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
109
src/pocketpy.h
109
src/pocketpy.h
@ -723,31 +723,36 @@ struct Random{
|
|||||||
gen.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
gen.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 randint(i64 a, i64 b) {
|
|
||||||
std::uniform_int_distribution<i64> dis(a, b);
|
|
||||||
return dis(gen);
|
|
||||||
}
|
|
||||||
|
|
||||||
f64 random() {
|
|
||||||
std::uniform_real_distribution<f64> dis(0.0, 1.0);
|
|
||||||
return dis(gen);
|
|
||||||
}
|
|
||||||
|
|
||||||
f64 uniform(f64 a, f64 b) {
|
|
||||||
std::uniform_real_distribution<f64> dis(a, b);
|
|
||||||
return dis(gen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void seed(i64 seed) {
|
|
||||||
gen.seed(seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind_static_method<0>(type, "__new__", CPP_LAMBDA(VAR_T(Random)));
|
vm->bind_static_method<0>(type, "__new__", CPP_LAMBDA(VAR_T(Random)));
|
||||||
vm->bind_cpp_method<1>(type, "seed", native_proxy_callable(&Random::seed));
|
|
||||||
vm->bind_cpp_method<2>(type, "randint", native_proxy_callable(&Random::randint));
|
vm->bind_method<1>(type, "seed", [](VM* vm, ArgsView args) {
|
||||||
vm->bind_cpp_method<0>(type, "random", native_proxy_callable(&Random::random));
|
Random& self = CAST(Random&, args[0]);
|
||||||
vm->bind_cpp_method<2>(type, "uniform", native_proxy_callable(&Random::uniform));
|
self.gen.seed(CAST(i64, args[1]));
|
||||||
|
return vm->None;
|
||||||
|
});
|
||||||
|
|
||||||
|
vm->bind_method<2>(type, "randint", [](VM* vm, ArgsView args) {
|
||||||
|
Random& self = CAST(Random&, args[0]);
|
||||||
|
i64 a = CAST(i64, args[1]);
|
||||||
|
i64 b = CAST(i64, args[2]);
|
||||||
|
std::uniform_int_distribution<i64> dis(a, b);
|
||||||
|
return VAR(dis(self.gen));
|
||||||
|
});
|
||||||
|
|
||||||
|
vm->bind_method<0>(type, "random", [](VM* vm, ArgsView args) {
|
||||||
|
Random& self = CAST(Random&, args[0]);
|
||||||
|
std::uniform_real_distribution<f64> dis(0.0, 1.0);
|
||||||
|
return VAR(dis(self.gen));
|
||||||
|
});
|
||||||
|
|
||||||
|
vm->bind_method<2>(type, "uniform", [](VM* vm, ArgsView args) {
|
||||||
|
Random& self = CAST(Random&, args[0]);
|
||||||
|
f64 a = CAST(f64, args[1]);
|
||||||
|
f64 b = CAST(f64, args[2]);
|
||||||
|
std::uniform_real_distribution<f64> dis(a, b);
|
||||||
|
return VAR(dis(self.gen));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -929,62 +934,4 @@ extern "C" {
|
|||||||
s_out->str(""); s_err->str("");
|
s_out->str(""); s_err->str("");
|
||||||
return strdup(ss.str().c_str());
|
return strdup(ss.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef pkpy::i64 (*f_int_t)(char*);
|
|
||||||
typedef pkpy::f64 (*f_float_t)(char*);
|
|
||||||
typedef bool (*f_bool_t)(char*);
|
|
||||||
typedef char* (*f_str_t)(char*);
|
|
||||||
typedef void (*f_None_t)(char*);
|
|
||||||
|
|
||||||
static f_int_t f_int = nullptr;
|
|
||||||
static f_float_t f_float = nullptr;
|
|
||||||
static f_bool_t f_bool = nullptr;
|
|
||||||
static f_str_t f_str = nullptr;
|
|
||||||
static f_None_t f_None = nullptr;
|
|
||||||
|
|
||||||
__EXPORT
|
|
||||||
/// Setup the callback functions.
|
|
||||||
void pkpy_setup_callbacks(f_int_t _f_int, f_float_t _f_float, f_bool_t _f_bool, f_str_t _f_str, f_None_t _f_None){
|
|
||||||
f_int = _f_int;
|
|
||||||
f_float = _f_float;
|
|
||||||
f_bool = _f_bool;
|
|
||||||
f_str = _f_str;
|
|
||||||
f_None = _f_None;
|
|
||||||
}
|
|
||||||
|
|
||||||
__EXPORT
|
|
||||||
/// Bind a function to a virtual machine.
|
|
||||||
char* pkpy_vm_bind(pkpy::VM* vm, const char* mod, const char* name, int ret_code){
|
|
||||||
if(!f_int || !f_float || !f_bool || !f_str || !f_None) return nullptr;
|
|
||||||
static int kGlobalBindId = 0;
|
|
||||||
for(int i=0; mod[i]; i++) if(mod[i] == ' ') return nullptr;
|
|
||||||
for(int i=0; name[i]; i++) if(name[i] == ' ') return nullptr;
|
|
||||||
std::string f_header = std::string(mod) + '.' + name + '#' + std::to_string(kGlobalBindId++);
|
|
||||||
pkpy::PyObject* obj = vm->_modules.contains(mod) ? vm->_modules[mod] : vm->new_module(mod);
|
|
||||||
vm->bind_cpp_func<-1>(obj, name, [ret_code, f_header](pkpy::VM* vm, pkpy::ArgsView args){
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << f_header;
|
|
||||||
for(int i=0; i<args.size(); i++){
|
|
||||||
ss << ' ';
|
|
||||||
pkpy::PyObject* x = vm->call_method(args[i], pkpy::__json__);
|
|
||||||
ss << pkpy::CAST(pkpy::Str&, x);
|
|
||||||
}
|
|
||||||
char* packet = strdup(ss.str().c_str());
|
|
||||||
switch(ret_code){
|
|
||||||
case 'i': return VAR(f_int(packet));
|
|
||||||
case 'f': return VAR(f_float(packet));
|
|
||||||
case 'b': return VAR(f_bool(packet));
|
|
||||||
case 's': {
|
|
||||||
char* p = f_str(packet);
|
|
||||||
if(p == nullptr) return vm->None;
|
|
||||||
return VAR(p); // no need to free(p)
|
|
||||||
}
|
|
||||||
case 'N': f_None(packet); return vm->None;
|
|
||||||
}
|
|
||||||
free(packet);
|
|
||||||
FATAL_ERROR();
|
|
||||||
return vm->None;
|
|
||||||
});
|
|
||||||
return strdup(f_header.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
18
src/vm.h
18
src/vm.h
@ -384,10 +384,6 @@ public:
|
|||||||
void bind_method(PyObject*, Str, NativeFuncC);
|
void bind_method(PyObject*, Str, NativeFuncC);
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
void bind_func(PyObject*, Str, NativeFuncC);
|
void bind_func(PyObject*, Str, NativeFuncC);
|
||||||
template<int ARGC>
|
|
||||||
void bind_cpp_method(PyObject*, Str, NativeFuncCpp);
|
|
||||||
template<int ARGC>
|
|
||||||
void bind_cpp_func(PyObject*, Str, NativeFuncCpp);
|
|
||||||
void _error(Exception);
|
void _error(Exception);
|
||||||
PyObject* _run_top_frame();
|
PyObject* _run_top_frame();
|
||||||
void post_init();
|
void post_init();
|
||||||
@ -398,8 +394,7 @@ inline PyObject* NativeFunc::operator()(VM* vm, ArgsView args) const{
|
|||||||
if(argc != -1 && args_size != argc) {
|
if(argc != -1 && args_size != argc) {
|
||||||
vm->TypeError(fmt("expected ", argc, " arguments, but got ", args_size));
|
vm->TypeError(fmt("expected ", argc, " arguments, but got ", args_size));
|
||||||
}
|
}
|
||||||
if(f != nullptr) return f(vm, args);
|
return f(vm, args);
|
||||||
return f_cpp(vm, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CodeObject::optimize(VM* vm){
|
inline void CodeObject::optimize(VM* vm){
|
||||||
@ -1050,22 +1045,11 @@ void VM::bind_method(PyObject* obj, Str name, NativeFuncC fn) {
|
|||||||
obj->attr().set(name, VAR(NativeFunc(fn, ARGC, true)));
|
obj->attr().set(name, VAR(NativeFunc(fn, ARGC, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int ARGC>
|
|
||||||
void VM::bind_cpp_method(PyObject* obj, Str name, NativeFuncCpp fn) {
|
|
||||||
check_type(obj, tp_type);
|
|
||||||
obj->attr().set(name, VAR(NativeFunc(fn, ARGC, true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
void VM::bind_func(PyObject* obj, Str name, NativeFuncC fn) {
|
void VM::bind_func(PyObject* obj, Str name, NativeFuncC fn) {
|
||||||
obj->attr().set(name, VAR(NativeFunc(fn, ARGC, false)));
|
obj->attr().set(name, VAR(NativeFunc(fn, ARGC, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int ARGC>
|
|
||||||
void VM::bind_cpp_func(PyObject* obj, Str name, NativeFuncCpp fn) {
|
|
||||||
obj->attr().set(name, VAR(NativeFunc(fn, ARGC, false)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void VM::_error(Exception e){
|
inline void VM::_error(Exception e){
|
||||||
if(callstack.empty()){
|
if(callstack.empty()){
|
||||||
e.is_re = false;
|
e.is_re = false;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user