This commit is contained in:
blueloveTH 2023-05-03 14:20:18 +08:00
parent 468f7a3c22
commit 849c6aabb5
7 changed files with 27 additions and 17 deletions

View File

@ -1,6 +1,7 @@
---
icon: dot
order: 100
title: Basic Features
---
# basic

View File

@ -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
View 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.

View File

@ -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();

View File

@ -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;

View File

@ -47,6 +47,7 @@ using FuncDecl_ = shared_ptr<FuncDecl>;
struct Function{
FuncDecl_ decl;
bool is_simple;
int argc; // cached argc
PyObject* _module;
NameDict_ _closure;
};

View File

@ -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;
}