mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 21:10:19 +00:00
...
This commit is contained in:
parent
468f7a3c22
commit
849c6aabb5
@ -1,6 +1,7 @@
|
||||
---
|
||||
icon: dot
|
||||
order: 100
|
||||
title: Basic Features
|
||||
---
|
||||
|
||||
# basic
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
---
|
||||
icon: dot
|
||||
title: Goto Statement
|
||||
---
|
||||
|
||||
# goto/label
|
||||
@ -25,7 +26,3 @@ for i in range(10):
|
||||
|
||||
label .exit
|
||||
```
|
||||
|
||||
!!!
|
||||
If we detect an illegal divert, you will get an `UnexpectedError` or the behaviour is undefined.
|
||||
!!!
|
||||
|
||||
10
docs/features/ub.md
Normal file
10
docs/features/ub.md
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
icon: dot
|
||||
title: Undefined Behaviour
|
||||
---
|
||||
|
||||
These are the undefined behaviours of pkpy. The behaviour of pkpy is undefined if you do the following things.
|
||||
|
||||
1. Delete a builtin object. For example, `del int.__add__`.
|
||||
2. Call an unbound method with the wrong type of `self`. For example, `int.__add__('1', 2)`.
|
||||
3. Use goto statement to jump out of a context block.
|
||||
@ -83,11 +83,12 @@ __NEXT_STEP:;
|
||||
TARGET(LOAD_FUNCTION) {
|
||||
FuncDecl_ decl = co->func_decls[byte.arg];
|
||||
bool is_simple = decl->starred_arg==-1 && decl->kwargs.size()==0 && !decl->code->is_generator;
|
||||
int argc = decl->args.size();
|
||||
PyObject* obj;
|
||||
if(decl->nested){
|
||||
obj = VAR(Function({decl, is_simple, frame->_module, frame->_locals.to_namedict()}));
|
||||
obj = VAR(Function({decl, is_simple, argc, frame->_module, frame->_locals.to_namedict()}));
|
||||
}else{
|
||||
obj = VAR(Function({decl, is_simple, frame->_module}));
|
||||
obj = VAR(Function({decl, is_simple, argc, frame->_module}));
|
||||
}
|
||||
PUSH(obj);
|
||||
} DISPATCH();
|
||||
|
||||
@ -63,8 +63,9 @@ struct ValueStackImpl {
|
||||
// We allocate extra MAX_SIZE/128 places to keep `_sp` valid when `is_overflow() == true`.
|
||||
PyObject* _begin[MAX_SIZE + MAX_SIZE/128];
|
||||
PyObject** _sp;
|
||||
PyObject** _max_end;
|
||||
|
||||
ValueStackImpl(): _sp(_begin) {}
|
||||
ValueStackImpl(): _sp(_begin), _max_end(_begin + MAX_SIZE) {}
|
||||
|
||||
PyObject*& top(){ return _sp[-1]; }
|
||||
PyObject* top() const { return _sp[-1]; }
|
||||
@ -90,7 +91,7 @@ struct ValueStackImpl {
|
||||
_sp = sp;
|
||||
}
|
||||
void clear() { _sp = _begin; }
|
||||
bool is_overflow() const { return _sp >= _begin + MAX_SIZE; }
|
||||
bool is_overflow() const { return _sp >= _max_end; }
|
||||
|
||||
ValueStackImpl(const ValueStackImpl&) = delete;
|
||||
ValueStackImpl(ValueStackImpl&&) = delete;
|
||||
|
||||
@ -47,6 +47,7 @@ using FuncDecl_ = shared_ptr<FuncDecl>;
|
||||
struct Function{
|
||||
FuncDecl_ decl;
|
||||
bool is_simple;
|
||||
int argc; // cached argc
|
||||
PyObject* _module;
|
||||
NameDict_ _closure;
|
||||
};
|
||||
|
||||
17
src/vm.h
17
src/vm.h
@ -1001,12 +1001,11 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
|
||||
|
||||
const Function& fn = CAST(Function&, callable);
|
||||
const CodeObject* co = fn.decl->code.get();
|
||||
PyObject* _module = fn._module != nullptr ? fn._module : callstack.top()._module;
|
||||
|
||||
if(args.size() < fn.decl->args.size()){
|
||||
if(args.size() < fn.argc){
|
||||
vm->TypeError(fmt(
|
||||
"expected ",
|
||||
fn.decl->args.size(),
|
||||
fn.argc,
|
||||
" positional arguments, but got ",
|
||||
args.size(),
|
||||
" (", fn.decl->code->name, ')'
|
||||
@ -1015,11 +1014,11 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
|
||||
|
||||
// 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
|
||||
if(fn.is_simple && kwargs.size()==0){
|
||||
if(args.size() > fn.decl->args.size()) TypeError("too many positional arguments");
|
||||
int spaces = co->varnames.size() - fn.decl->args.size();
|
||||
if(fn.is_simple){
|
||||
if(args.size() > fn.argc) TypeError("too many positional arguments");
|
||||
int spaces = co->varnames.size() - fn.argc;
|
||||
for(int j=0; j<spaces; j++) PUSH(nullptr);
|
||||
callstack.emplace(&s_data, p0, co, _module, callable, FastLocals(co, args.begin()));
|
||||
callstack.emplace(&s_data, p0, co, fn._module, callable, FastLocals(co, args.begin()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1062,7 +1061,7 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
|
||||
if(co->is_generator){
|
||||
PyObject* ret = PyIter(Generator(
|
||||
this,
|
||||
Frame(&s_data, nullptr, co, _module, callable),
|
||||
Frame(&s_data, nullptr, co, fn._module, callable),
|
||||
ArgsView(buffer, buffer + co->varnames.size())
|
||||
));
|
||||
return ret;
|
||||
@ -1070,7 +1069,7 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
|
||||
|
||||
// copy buffer to stack
|
||||
for(int i=0; i<co->varnames.size(); i++) PUSH(buffer[i]);
|
||||
callstack.emplace(&s_data, p0, co, _module, callable);
|
||||
callstack.emplace(&s_data, p0, co, fn._module, callable);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user