py/compile: Refine SyntaxError for repeated use of global/nonlocal.
This commit is contained in:
parent
3a2171e406
commit
558a016e2c
10
py/compile.c
10
py/compile.c
@ -1355,9 +1355,8 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
|
||||
if (!added) {
|
||||
// TODO this is not compliant with CPython
|
||||
compile_syntax_error(comp, pn, "identifier already used");
|
||||
if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
|
||||
compile_syntax_error(comp, pn, "identifier redefined as global");
|
||||
return;
|
||||
}
|
||||
id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
|
||||
@ -1382,9 +1381,8 @@ STATIC void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
|
||||
bool added;
|
||||
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
|
||||
if (!added) {
|
||||
// TODO this is not compliant with CPython
|
||||
compile_syntax_error(comp, pn, "identifier already used");
|
||||
if (!added && id_info->kind != ID_INFO_KIND_FREE) {
|
||||
compile_syntax_error(comp, pn, "identifier redefined as nonlocal");
|
||||
return;
|
||||
}
|
||||
id_info_t *id_info2 = scope_find_local_in_parent(comp->scope_cur, qst);
|
||||
|
21
tests/basics/scope.py
Normal file
21
tests/basics/scope.py
Normal file
@ -0,0 +1,21 @@
|
||||
# test scoping rules
|
||||
|
||||
# explicit global variable
|
||||
a = 1
|
||||
def f():
|
||||
global a
|
||||
global a, a # should be able to redefine as global
|
||||
a = 2
|
||||
f()
|
||||
print(a)
|
||||
|
||||
# explicit nonlocal variable
|
||||
def f():
|
||||
a = 1
|
||||
def g():
|
||||
nonlocal a
|
||||
nonlocal a, a # should be able to redefine as nonlocal
|
||||
a = 2
|
||||
g()
|
||||
return a
|
||||
print(f())
|
@ -77,8 +77,7 @@ test_syntax("return")
|
||||
test_syntax("yield")
|
||||
test_syntax("nonlocal a")
|
||||
|
||||
# errors on uPy but shouldn't
|
||||
#test_syntax("global a; global a")
|
||||
# error on uPy, warning on CPy
|
||||
#test_syntax("def f():\n a = 1\n global a")
|
||||
|
||||
# default except must be last
|
||||
@ -109,3 +108,12 @@ test_syntax("def f(a, a): pass")
|
||||
|
||||
# nonlocal must exist in outer function/class scope
|
||||
test_syntax("def f():\n def g():\n nonlocal a")
|
||||
|
||||
# param can't be redefined as global
|
||||
test_syntax('def f(x):\n global x')
|
||||
|
||||
# param can't be redefined as nonlocal
|
||||
test_syntax('def f(x):\n nonlocal x')
|
||||
|
||||
# can define variable to be both nonlocal and global
|
||||
test_syntax('def f():\n nonlocal x\n global x')
|
||||
|
Loading…
x
Reference in New Issue
Block a user