mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +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) \
|
#define AttributeError(self, n) \
|
||||||
py_exception(tp_AttributeError, "'%t' object has no attribute '%n'", (self)->type, (n))
|
py_exception(tp_AttributeError, "'%t' object has no attribute '%n'", (self)->type, (n))
|
||||||
#define UnboundLocalError(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 StopIteration() PY_RAISE;
|
||||||
PK_API bool KeyError(py_Ref key) 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
|
// we know this is a local variable
|
||||||
Ctx__emit_(ctx, OP_LOAD_FAST, index, self->line);
|
Ctx__emit_(ctx, OP_LOAD_FAST, index, self->line);
|
||||||
} else {
|
} else {
|
||||||
Opcode op;
|
Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
|
||||||
// otherwise, if we are running dynamically, force `OP_LOAD_NAME`
|
if(self->scope == NAME_GLOBAL) {
|
||||||
if(ctx->co->src->is_dynamic) {
|
if(ctx->co->src->is_dynamic) {
|
||||||
op = OP_LOAD_NAME;
|
op = OP_LOAD_NAME;
|
||||||
// `OP_LOAD_NAME` won't handle `OP_LOAD_CLASS_GLOBAL`
|
} else {
|
||||||
// so `exec()` will raise an error for @property.setter
|
if(ctx->is_compiling_class) {
|
||||||
} else {
|
// if we are compiling a class, we should use `OP_LOAD_CLASS_GLOBAL`
|
||||||
op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
|
// this is for @property.setter
|
||||||
if(ctx->is_compiling_class && self->scope == NAME_GLOBAL) {
|
op = OP_LOAD_CLASS_GLOBAL;
|
||||||
// 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);
|
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);
|
assert(module->type == tp_module);
|
||||||
|
|
||||||
py_StackRef sp = vm->stack.sp;
|
py_StackRef sp = vm->stack.sp;
|
||||||
assert(globals != NULL);
|
assert(globals != NULL && locals != NULL);
|
||||||
|
|
||||||
|
// check globals
|
||||||
if(globals->type == tp_namedict) {
|
if(globals->type == tp_namedict) {
|
||||||
globals = py_getslot(globals, 0);
|
globals = py_getslot(globals, 0);
|
||||||
assert(globals->type == tp_module);
|
assert(globals->type == tp_module);
|
||||||
} else {
|
} 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);
|
Frame* frame = Frame__new(co, sp, module, globals, locals, true);
|
||||||
VM__push_frame(vm, frame);
|
VM__push_frame(vm, frame);
|
||||||
FrameResult res = VM__run_top_frame(vm);
|
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))) {
|
if(py_isnone(py_arg(1))) {
|
||||||
py_newglobals(py_pushtmp());
|
py_newglobals(py_pushtmp());
|
||||||
} else {
|
} else {
|
||||||
if(!py_checktype(py_arg(1), tp_dict)) return false;
|
|
||||||
py_push(py_arg(1));
|
py_push(py_arg(1));
|
||||||
}
|
}
|
||||||
// locals
|
// locals
|
||||||
pk_push_special_locals();
|
py_pushnil();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: {
|
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))) {
|
if(py_isnone(py_arg(1))) {
|
||||||
py_newglobals(py_pushtmp());
|
py_newglobals(py_pushtmp());
|
||||||
} else {
|
} else {
|
||||||
if(!py_checktype(py_arg(1), tp_dict)) return false;
|
|
||||||
py_push(py_arg(1));
|
py_push(py_arg(1));
|
||||||
}
|
}
|
||||||
// locals
|
// locals
|
||||||
if(py_isnone(py_arg(2))) {
|
if(py_isnone(py_arg(2))) {
|
||||||
pk_push_special_locals();
|
py_pushnil();
|
||||||
} else {
|
} else {
|
||||||
if(!py_checktype(py_arg(2), tp_dict)) return false;
|
|
||||||
py_push(py_arg(2));
|
py_push(py_arg(2));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -31,12 +31,10 @@ def f():
|
|||||||
)
|
)
|
||||||
assert b == 8
|
assert b == 8
|
||||||
|
|
||||||
class G: pass
|
|
||||||
|
|
||||||
def abc():
|
def abc():
|
||||||
g = G()
|
g = {}
|
||||||
exec('a=1', g.__dict__)
|
exec('a=1', g)
|
||||||
return g.a
|
return g['a']
|
||||||
|
|
||||||
res = abc()
|
res = abc()
|
||||||
assert (res==1), res
|
assert (res==1), res
|
||||||
@ -69,6 +67,11 @@ except NameError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# https://github.com/pocketpy/pocketpy/issues/339
|
# 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
|
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:
|
# With default locals:
|
||||||
exec("""
|
exec("""
|
||||||
import sys
|
import sys
|
||||||
assert locals() == globals()
|
|
||||||
assert "sys" in locals()
|
assert "sys" in locals()
|
||||||
assert "sys" in globals()
|
assert "sys" in globals()
|
||||||
def main():
|
def main():
|
||||||
assert locals() != globals()
|
|
||||||
assert "sys" not in locals() # not the same locals as the outer scope
|
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()`
|
assert "sys" in globals() # but now be can access `sys` via `globals()`
|
||||||
main()
|
main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user