Commit 558a016e authored by Damien George's avatar Damien George
Browse files

py/compile: Refine SyntaxError for repeated use of global/nonlocal.

parent 3a2171e4
......@@ -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);
......
# 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')
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment