mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
fix bugs
This commit is contained in:
parent
bf7bfa938c
commit
4ead475cd1
@ -536,7 +536,7 @@ PK_API void py_clearexc(py_StackRef p0);
|
||||
#define AttributeError(self, n) \
|
||||
py_exception(tp_AttributeError, "'%t' object has no attribute '%n'", (self)->type, (n))
|
||||
#define UnboundLocalError(n) \
|
||||
py_exception(tp_UnboundLocalError, "local variable '%n' referenced before assignment", (n))
|
||||
py_exception(tp_UnboundLocalError, "cannot access local variable '%n' where it is not associated with a value", (n))
|
||||
|
||||
PK_API bool StopIteration() PY_RAISE;
|
||||
PK_API bool KeyError(py_Ref key) PY_RAISE;
|
||||
|
@ -105,18 +105,16 @@ void NameExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||
// we know this is a local variable
|
||||
Ctx__emit_(ctx, OP_LOAD_FAST, index, self->line);
|
||||
} else {
|
||||
Opcode op;
|
||||
// otherwise, if we are running dynamically, force `OP_LOAD_NAME`
|
||||
if(ctx->co->src->is_dynamic) {
|
||||
op = OP_LOAD_NAME;
|
||||
// `OP_LOAD_NAME` won't handle `OP_LOAD_CLASS_GLOBAL`
|
||||
// so `exec()` will raise an error for @property.setter
|
||||
} else {
|
||||
op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
|
||||
if(ctx->is_compiling_class && self->scope == NAME_GLOBAL) {
|
||||
// if we are compiling a class, we should use `OP_LOAD_CLASS_GLOBAL`
|
||||
// this is for @property.setter
|
||||
op = OP_LOAD_CLASS_GLOBAL;
|
||||
Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
|
||||
if(self->scope == NAME_GLOBAL) {
|
||||
if(ctx->co->src->is_dynamic) {
|
||||
op = OP_LOAD_NAME;
|
||||
} else {
|
||||
if(ctx->is_compiling_class) {
|
||||
// if we are compiling a class, we should use `OP_LOAD_CLASS_GLOBAL`
|
||||
// this is for @property.setter
|
||||
op = OP_LOAD_CLASS_GLOBAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ctx__emit_(ctx, op, self->name, self->line);
|
||||
|
@ -68,14 +68,23 @@ bool pk_execdyn(CodeObject* co, py_Ref module, py_Ref globals, py_Ref locals) {
|
||||
assert(module->type == tp_module);
|
||||
|
||||
py_StackRef sp = vm->stack.sp;
|
||||
assert(globals != NULL);
|
||||
assert(globals != NULL && locals != NULL);
|
||||
|
||||
// check globals
|
||||
if(globals->type == tp_namedict) {
|
||||
globals = py_getslot(globals, 0);
|
||||
assert(globals->type == tp_module);
|
||||
} else {
|
||||
assert(globals->type == tp_dict);
|
||||
if(!py_istype(globals, tp_dict)) { return TypeError("globals must be a dict object"); }
|
||||
}
|
||||
// check locals
|
||||
switch(locals->type) {
|
||||
case tp_locals: break;
|
||||
case tp_dict: break;
|
||||
case tp_nil: break;
|
||||
default: return TypeError("locals must be a dict object");
|
||||
}
|
||||
|
||||
Frame* frame = Frame__new(co, sp, module, globals, locals, true);
|
||||
VM__push_frame(vm, frame);
|
||||
FrameResult res = VM__run_top_frame(vm);
|
||||
|
@ -554,11 +554,10 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
|
||||
if(py_isnone(py_arg(1))) {
|
||||
py_newglobals(py_pushtmp());
|
||||
} else {
|
||||
if(!py_checktype(py_arg(1), tp_dict)) return false;
|
||||
py_push(py_arg(1));
|
||||
}
|
||||
// locals
|
||||
pk_push_special_locals();
|
||||
py_pushnil();
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
@ -566,14 +565,12 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
|
||||
if(py_isnone(py_arg(1))) {
|
||||
py_newglobals(py_pushtmp());
|
||||
} else {
|
||||
if(!py_checktype(py_arg(1), tp_dict)) return false;
|
||||
py_push(py_arg(1));
|
||||
}
|
||||
// locals
|
||||
if(py_isnone(py_arg(2))) {
|
||||
pk_push_special_locals();
|
||||
py_pushnil();
|
||||
} else {
|
||||
if(!py_checktype(py_arg(2), tp_dict)) return false;
|
||||
py_push(py_arg(2));
|
||||
}
|
||||
break;
|
||||
|
@ -31,12 +31,10 @@ def f():
|
||||
)
|
||||
assert b == 8
|
||||
|
||||
class G: pass
|
||||
|
||||
def abc():
|
||||
g = G()
|
||||
exec('a=1', g.__dict__)
|
||||
return g.a
|
||||
g = {}
|
||||
exec('a=1', g)
|
||||
return g['a']
|
||||
|
||||
res = abc()
|
||||
assert (res==1), res
|
||||
@ -69,6 +67,11 @@ except NameError:
|
||||
pass
|
||||
|
||||
# https://github.com/pocketpy/pocketpy/issues/339
|
||||
code = '\nprint(x)\ndef f():\n print(x)\nf()\n'
|
||||
res = []
|
||||
|
||||
code = '\nres.append(x)\ndef f():\n res.append(x)\nf()\n'
|
||||
x = 33
|
||||
exec(code, {'x': 42})
|
||||
exec(code, {'x': 42})
|
||||
assert res == [42, 42]
|
||||
assert x == 33
|
||||
|
||||
|
@ -32,11 +32,9 @@ assert "sys" not in globals()
|
||||
# With default locals:
|
||||
exec("""
|
||||
import sys
|
||||
assert locals() == globals()
|
||||
assert "sys" in locals()
|
||||
assert "sys" in globals()
|
||||
def main():
|
||||
assert locals() != globals()
|
||||
assert "sys" not in locals() # not the same locals as the outer scope
|
||||
assert "sys" in globals() # but now be can access `sys` via `globals()`
|
||||
main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user