mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
...
This commit is contained in:
parent
0338a8c71c
commit
22e74a16a3
@ -99,14 +99,13 @@ __NEXT_STEP:;
|
|||||||
TARGET(LOAD_FUNCTION) {
|
TARGET(LOAD_FUNCTION) {
|
||||||
FuncDecl_ decl = co->func_decls[byte.arg];
|
FuncDecl_ decl = co->func_decls[byte.arg];
|
||||||
bool is_simple = decl->starred_kwarg==-1 && decl->starred_arg==-1 && decl->kwargs.size()==0 && !decl->code->is_generator;
|
bool is_simple = decl->starred_kwarg==-1 && decl->starred_arg==-1 && decl->kwargs.size()==0 && !decl->code->is_generator;
|
||||||
int argc = decl->args.size();
|
|
||||||
PyObject* obj;
|
PyObject* obj;
|
||||||
if(decl->nested){
|
if(decl->nested){
|
||||||
NameDict_ captured = frame->_locals.to_namedict();
|
NameDict_ captured = frame->_locals.to_namedict();
|
||||||
obj = VAR(Function({decl, is_simple, argc, frame->_module, captured}));
|
obj = VAR(Function({decl, is_simple, frame->_module, captured}));
|
||||||
captured->set(decl->code->name, obj);
|
captured->set(decl->code->name, obj);
|
||||||
}else{
|
}else{
|
||||||
obj = VAR(Function({decl, is_simple, argc, frame->_module}));
|
obj = VAR(Function({decl, is_simple, frame->_module}));
|
||||||
}
|
}
|
||||||
PUSH(obj);
|
PUSH(obj);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
|
11
src/obj.h
11
src/obj.h
@ -30,8 +30,6 @@ struct NativeFunc {
|
|||||||
UserData _userdata;
|
UserData _userdata;
|
||||||
bool _has_userdata;
|
bool _has_userdata;
|
||||||
|
|
||||||
const char* signature;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void set_userdata(T data) {
|
void set_userdata(T data) {
|
||||||
static_assert(std::is_trivially_copyable_v<T>);
|
static_assert(std::is_trivially_copyable_v<T>);
|
||||||
@ -51,9 +49,8 @@ struct NativeFunc {
|
|||||||
return reinterpret_cast<const T&>(_userdata);
|
return reinterpret_cast<const T&>(_userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeFunc(NativeFuncC f, int argc, bool method, const char* sig=nullptr){
|
NativeFunc(NativeFuncC f, int argc, bool method){
|
||||||
this->f = f;
|
this->f = f;
|
||||||
this->signature = sig;
|
|
||||||
this->argc = argc;
|
this->argc = argc;
|
||||||
if(argc != -1) this->argc += (int)method;
|
if(argc != -1) this->argc += (int)method;
|
||||||
_lua_f = nullptr;
|
_lua_f = nullptr;
|
||||||
@ -63,6 +60,11 @@ struct NativeFunc {
|
|||||||
PyObject* operator()(VM* vm, ArgsView args) const;
|
PyObject* operator()(VM* vm, ArgsView args) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct NativeFuncEx{
|
||||||
|
NativeFuncC f;
|
||||||
|
};
|
||||||
|
|
||||||
typedef shared_ptr<CodeObject> CodeObject_;
|
typedef shared_ptr<CodeObject> CodeObject_;
|
||||||
|
|
||||||
struct FuncDecl {
|
struct FuncDecl {
|
||||||
@ -84,7 +86,6 @@ using FuncDecl_ = shared_ptr<FuncDecl>;
|
|||||||
struct Function{
|
struct Function{
|
||||||
FuncDecl_ decl;
|
FuncDecl_ decl;
|
||||||
bool is_simple;
|
bool is_simple;
|
||||||
int argc; // cached argc
|
|
||||||
PyObject* _module;
|
PyObject* _module;
|
||||||
NameDict_ _closure;
|
NameDict_ _closure;
|
||||||
};
|
};
|
||||||
|
79
src/vm.h
79
src/vm.h
@ -461,19 +461,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
PyObject* bind_func(Str type, Str name, NativeFuncC fn, const char* sig=nullptr) {
|
PyObject* bind_func(Str type, Str name, NativeFuncC fn) {
|
||||||
return bind_func<ARGC>(_find_type_object(type), name, fn, sig);
|
return bind_func<ARGC>(_find_type_object(type), name, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
PyObject* bind_method(Str type, Str name, NativeFuncC fn, const char* sig=nullptr) {
|
PyObject* bind_method(Str type, Str name, NativeFuncC fn) {
|
||||||
return bind_method<ARGC>(_find_type_object(type), name, fn, sig);
|
return bind_method<ARGC>(_find_type_object(type), name, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int ARGC, typename __T>
|
template<int ARGC, typename __T>
|
||||||
PyObject* bind_constructor(__T&& type, NativeFuncC fn, const char* sig=nullptr) {
|
PyObject* bind_constructor(__T&& type, NativeFuncC fn) {
|
||||||
static_assert(ARGC==-1 || ARGC>=1);
|
static_assert(ARGC==-1 || ARGC>=1);
|
||||||
return bind_func<ARGC>(std::forward<__T>(type), "__new__", fn, sig);
|
return bind_func<ARGC>(std::forward<__T>(type), "__new__", fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename __T>
|
template<typename T, typename __T>
|
||||||
@ -494,8 +494,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
PyObject* bind_builtin_func(Str name, NativeFuncC fn, const char* sig=nullptr) {
|
PyObject* bind_builtin_func(Str name, NativeFuncC fn) {
|
||||||
return bind_func<ARGC>(builtins, name, fn, sig);
|
return bind_func<ARGC>(builtins, name, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
int normalized_index(int index, int size){
|
int normalized_index(int index, int size){
|
||||||
@ -681,13 +681,15 @@ public:
|
|||||||
PyObject* format(Str, PyObject*);
|
PyObject* format(Str, PyObject*);
|
||||||
void setattr(PyObject* obj, StrName name, PyObject* value);
|
void setattr(PyObject* obj, StrName name, PyObject* value);
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
PyObject* bind_method(PyObject*, Str, NativeFuncC, const char* sig=nullptr);
|
PyObject* bind_method(PyObject*, Str, NativeFuncC);
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
PyObject* bind_func(PyObject*, Str, NativeFuncC, const char* sig=nullptr);
|
PyObject* bind_func(PyObject*, Str, NativeFuncC);
|
||||||
void _error(Exception);
|
void _error(Exception);
|
||||||
PyObject* _run_top_frame();
|
PyObject* _run_top_frame();
|
||||||
void post_init();
|
void post_init();
|
||||||
PyObject* _py_generator(Frame&& frame, ArgsView buffer);
|
PyObject* _py_generator(Frame&& frame, ArgsView buffer);
|
||||||
|
// new style binding api
|
||||||
|
PyObject* bind(PyObject*, const Str&, NativeFuncC);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline PyObject* NativeFunc::operator()(VM* vm, ArgsView args) const{
|
inline PyObject* NativeFunc::operator()(VM* vm, ArgsView args) const{
|
||||||
@ -1267,27 +1269,34 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
|
|
||||||
ArgsView kwargs(p1, s_data._sp);
|
ArgsView kwargs(p1, s_data._sp);
|
||||||
|
|
||||||
|
if(false){ // native_func_ex
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if(is_non_tagged_type(callable, tp_function)){
|
if(is_non_tagged_type(callable, tp_function)){
|
||||||
/*****************_py_call*****************/
|
/*****************_py_call*****************/
|
||||||
// callable must be a `function` object
|
// callable must be a `function` object
|
||||||
if(s_data.is_overflow()) StackOverflowError();
|
if(s_data.is_overflow()) StackOverflowError();
|
||||||
|
|
||||||
const Function& fn = CAST(Function&, callable);
|
const Function& fn = CAST(Function&, callable);
|
||||||
|
|
||||||
|
const FuncDecl_& decl = fn.decl;
|
||||||
|
int decl_argc = decl->args.size();
|
||||||
const CodeObject* co = fn.decl->code.get();
|
const CodeObject* co = fn.decl->code.get();
|
||||||
int co_nlocals = co->varnames.size();
|
int co_nlocals = co->varnames.size();
|
||||||
|
|
||||||
if(args.size() < fn.argc){
|
if(args.size() < decl_argc){
|
||||||
vm->TypeError(fmt(
|
vm->TypeError(fmt(
|
||||||
"expected ", fn.argc, " positional arguments, got ", args.size(),
|
"expected ", decl_argc, " positional arguments, got ", args.size(),
|
||||||
" (", fn.decl->code->name, ')'
|
" (", co->name, ')'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this function is simple, a.k.a, no kwargs and no *args and not a generator
|
// if this function is simple, a.k.a, no kwargs and no *args and not a generator
|
||||||
// we can use a fast path to avoid using buffer copy
|
// we can use a fast path to avoid using buffer copy
|
||||||
if(fn.is_simple){
|
if(fn.is_simple){
|
||||||
if(args.size() > fn.argc) TypeError("too many positional arguments");
|
if(args.size() > decl_argc) TypeError("too many positional arguments");
|
||||||
int spaces = co_nlocals - fn.argc;
|
int spaces = co_nlocals - decl_argc;
|
||||||
for(int j=0; j<spaces; j++) PUSH(PY_NULL);
|
for(int j=0; j<spaces; j++) PUSH(PY_NULL);
|
||||||
callstack.emplace(&s_data, p0, co, fn._module, callable, FastLocals(co, args.begin()));
|
callstack.emplace(&s_data, p0, co, fn._module, callable, FastLocals(co, args.begin()));
|
||||||
if(op_call) return PY_OP_CALL;
|
if(op_call) return PY_OP_CALL;
|
||||||
@ -1298,30 +1307,30 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
static THREAD_LOCAL PyObject* buffer[PK_MAX_CO_VARNAMES];
|
static THREAD_LOCAL PyObject* buffer[PK_MAX_CO_VARNAMES];
|
||||||
|
|
||||||
// prepare args
|
// prepare args
|
||||||
for(int index: fn.decl->args) buffer[index] = args[i++];
|
for(int index: decl->args) buffer[index] = args[i++];
|
||||||
// set extra varnames to nullptr
|
// set extra varnames to nullptr
|
||||||
for(int j=i; j<co_nlocals; j++) buffer[j] = PY_NULL;
|
for(int j=i; j<co_nlocals; j++) buffer[j] = PY_NULL;
|
||||||
// prepare kwdefaults
|
// prepare kwdefaults
|
||||||
for(auto& kv: fn.decl->kwargs) buffer[kv.key] = kv.value;
|
for(auto& kv: decl->kwargs) buffer[kv.key] = kv.value;
|
||||||
|
|
||||||
// handle *args
|
// handle *args
|
||||||
if(fn.decl->starred_arg != -1){
|
if(decl->starred_arg != -1){
|
||||||
ArgsView vargs(args.begin() + i, args.end());
|
ArgsView vargs(args.begin() + i, args.end());
|
||||||
buffer[fn.decl->starred_arg] = VAR(vargs.to_tuple());
|
buffer[decl->starred_arg] = VAR(vargs.to_tuple());
|
||||||
i += vargs.size();
|
i += vargs.size();
|
||||||
}else{
|
}else{
|
||||||
// kwdefaults override
|
// kwdefaults override
|
||||||
for(auto& kv: fn.decl->kwargs){
|
for(auto& kv: decl->kwargs){
|
||||||
if(i >= args.size()) break;
|
if(i >= args.size()) break;
|
||||||
buffer[kv.key] = args[i++];
|
buffer[kv.key] = args[i++];
|
||||||
}
|
}
|
||||||
if(i < args.size()) TypeError(fmt("too many arguments", " (", fn.decl->code->name, ')'));
|
if(i < args.size()) TypeError(fmt("too many arguments", " (", decl->code->name, ')'));
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* vkwargs;
|
PyObject* vkwargs;
|
||||||
if(fn.decl->starred_kwarg != -1){
|
if(decl->starred_kwarg != -1){
|
||||||
vkwargs = VAR(Dict(this));
|
vkwargs = VAR(Dict(this));
|
||||||
buffer[fn.decl->starred_kwarg] = vkwargs;
|
buffer[decl->starred_kwarg] = vkwargs;
|
||||||
}else{
|
}else{
|
||||||
vkwargs = nullptr;
|
vkwargs = nullptr;
|
||||||
}
|
}
|
||||||
@ -1519,20 +1528,36 @@ inline void VM::setattr(PyObject* obj, StrName name, PyObject* value){
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
PyObject* VM::bind_method(PyObject* obj, Str name, NativeFuncC fn, const char* sig) {
|
PyObject* VM::bind_method(PyObject* obj, Str name, NativeFuncC fn) {
|
||||||
check_non_tagged_type(obj, tp_type);
|
check_non_tagged_type(obj, tp_type);
|
||||||
PyObject* nf = VAR(NativeFunc(fn, ARGC, true, sig));
|
PyObject* nf = VAR(NativeFunc(fn, ARGC, true));
|
||||||
obj->attr().set(name, nf);
|
obj->attr().set(name, nf);
|
||||||
return nf;
|
return nf;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int ARGC>
|
template<int ARGC>
|
||||||
PyObject* VM::bind_func(PyObject* obj, Str name, NativeFuncC fn, const char* sig) {
|
PyObject* VM::bind_func(PyObject* obj, Str name, NativeFuncC fn) {
|
||||||
PyObject* nf = VAR(NativeFunc(fn, ARGC, false, sig));
|
PyObject* nf = VAR(NativeFunc(fn, ARGC, false));
|
||||||
obj->attr().set(name, nf);
|
obj->attr().set(name, nf);
|
||||||
return nf;
|
return nf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline PyObject* VM::bind(PyObject* obj, const Str& sig, NativeFuncC fn){
|
||||||
|
CodeObject_ co;
|
||||||
|
try{
|
||||||
|
// fn(a, b, *c, d=1) -> None
|
||||||
|
co = compile("def " + sig + " : pass", "<bind>", EXEC_MODE);
|
||||||
|
}catch(Exception& e){
|
||||||
|
throw std::runtime_error(("invalid signature: " + sig).str());
|
||||||
|
}
|
||||||
|
if(co->func_decls.size() != 1){
|
||||||
|
throw std::runtime_error("expected 1 function declaration");
|
||||||
|
}
|
||||||
|
FuncDecl_ decl = co->func_decls[0];
|
||||||
|
// return VAR(NativeFuncEx(fn, argc, false, sig));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
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