point errors related to nonlocals and globals to the statement declaring them (closes #10189)
This commit is contained in:
parent
a889d801ed
commit
d9c8702c0f
|
@ -39,6 +39,7 @@ typedef struct _symtable_entry {
|
||||||
PyObject *ste_name; /* string: name of current block */
|
PyObject *ste_name; /* string: name of current block */
|
||||||
PyObject *ste_varnames; /* list of function parameters */
|
PyObject *ste_varnames; /* list of function parameters */
|
||||||
PyObject *ste_children; /* list of child blocks */
|
PyObject *ste_children; /* list of child blocks */
|
||||||
|
PyObject *ste_directives;/* locations of global and nonlocal statements */
|
||||||
_Py_block_ty ste_type; /* module, class, or function */
|
_Py_block_ty ste_type; /* module, class, or function */
|
||||||
int ste_unoptimized; /* false if namespace is optimized */
|
int ste_unoptimized; /* false if namespace is optimized */
|
||||||
int ste_nested; /* true if block is nested */
|
int ste_nested; /* true if block is nested */
|
||||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #10189: Improve the error reporting of SyntaxErrors related to global
|
||||||
|
and nonlocal statements.
|
||||||
|
|
||||||
- Issue #16086: PyTypeObject.tp_flags and PyType_Spec.flags are now unsigned
|
- Issue #16086: PyTypeObject.tp_flags and PyType_Spec.flags are now unsigned
|
||||||
(unsigned long and unsigned int) to avoid an undefined behaviour with
|
(unsigned long and unsigned int) to avoid an undefined behaviour with
|
||||||
Py_TPFLAGS_TYPE_SUBCLASS ((1 << 31). PyType_GetFlags() result type is
|
Py_TPFLAGS_TYPE_SUBCLASS ((1 << 31). PyType_GetFlags() result type is
|
||||||
|
|
|
@ -56,6 +56,8 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
|
||||||
if (ste->ste_children == NULL)
|
if (ste->ste_children == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
ste->ste_directives = NULL;
|
||||||
|
|
||||||
ste->ste_type = block;
|
ste->ste_type = block;
|
||||||
ste->ste_unoptimized = 0;
|
ste->ste_unoptimized = 0;
|
||||||
ste->ste_nested = 0;
|
ste->ste_nested = 0;
|
||||||
|
@ -102,6 +104,7 @@ ste_dealloc(PySTEntryObject *ste)
|
||||||
Py_XDECREF(ste->ste_symbols);
|
Py_XDECREF(ste->ste_symbols);
|
||||||
Py_XDECREF(ste->ste_varnames);
|
Py_XDECREF(ste->ste_varnames);
|
||||||
Py_XDECREF(ste->ste_children);
|
Py_XDECREF(ste->ste_children);
|
||||||
|
Py_XDECREF(ste->ste_directives);
|
||||||
PyObject_Del(ste);
|
PyObject_Del(ste);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,6 +322,24 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
|
||||||
return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK;
|
return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
error_at_directive(PySTEntryObject *ste, PyObject *name)
|
||||||
|
{
|
||||||
|
Py_ssize_t i;
|
||||||
|
PyObject *data;
|
||||||
|
assert(ste->ste_directives);
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
data = PyList_GET_ITEM(ste->ste_directives, i);
|
||||||
|
assert(PyTuple_CheckExact(data));
|
||||||
|
if (PyTuple_GET_ITEM(data, 0) == name)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PyErr_SyntaxLocationEx(ste->ste_table->st_filename,
|
||||||
|
PyLong_AsLong(PyTuple_GET_ITEM(data, 1)),
|
||||||
|
PyLong_AsLong(PyTuple_GET_ITEM(data, 2)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Analyze raw symbol information to determine scope of each name.
|
/* Analyze raw symbol information to determine scope of each name.
|
||||||
|
|
||||||
|
@ -393,16 +414,13 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"name '%U' is parameter and global",
|
"name '%U' is parameter and global",
|
||||||
name);
|
name);
|
||||||
PyErr_SyntaxLocationEx(ste->ste_table->st_filename,
|
return error_at_directive(ste, name);
|
||||||
ste->ste_lineno, ste->ste_col_offset);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if (flags & DEF_NONLOCAL) {
|
if (flags & DEF_NONLOCAL) {
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"name '%U' is nonlocal and global",
|
"name '%U' is nonlocal and global",
|
||||||
name);
|
name);
|
||||||
return 0;
|
return error_at_directive(ste, name);
|
||||||
}
|
}
|
||||||
SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
|
SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
|
||||||
if (PySet_Add(global, name) < 0)
|
if (PySet_Add(global, name) < 0)
|
||||||
|
@ -416,19 +434,19 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"name '%U' is parameter and nonlocal",
|
"name '%U' is parameter and nonlocal",
|
||||||
name);
|
name);
|
||||||
return 0;
|
return error_at_directive(ste, name);
|
||||||
}
|
}
|
||||||
if (!bound) {
|
if (!bound) {
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"nonlocal declaration not allowed at module level");
|
"nonlocal declaration not allowed at module level");
|
||||||
return 0;
|
return error_at_directive(ste, name);
|
||||||
}
|
}
|
||||||
if (!PySet_Contains(bound, name)) {
|
if (!PySet_Contains(bound, name)) {
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"no binding for nonlocal '%U' found",
|
"no binding for nonlocal '%U' found",
|
||||||
name);
|
name);
|
||||||
|
|
||||||
return 0;
|
return error_at_directive(ste, name);
|
||||||
}
|
}
|
||||||
SET_SCOPE(scopes, name, FREE);
|
SET_SCOPE(scopes, name, FREE);
|
||||||
ste->ste_free = 1;
|
ste->ste_free = 1;
|
||||||
|
@ -1068,6 +1086,25 @@ symtable_new_tmpname(struct symtable *st)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
symtable_record_directive(struct symtable *st, identifier name, stmt_ty s)
|
||||||
|
{
|
||||||
|
PyObject *data;
|
||||||
|
int res;
|
||||||
|
if (!st->st_cur->ste_directives) {
|
||||||
|
st->st_cur->ste_directives = PyList_New(0);
|
||||||
|
if (!st->st_cur->ste_directives)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
data = Py_BuildValue("(Oii)", name, s->lineno, s->col_offset);
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
res = PyList_Append(st->st_cur->ste_directives, data);
|
||||||
|
Py_DECREF(data);
|
||||||
|
return res == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
{
|
{
|
||||||
|
@ -1223,6 +1260,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
}
|
}
|
||||||
if (!symtable_add_def(st, name, DEF_GLOBAL))
|
if (!symtable_add_def(st, name, DEF_GLOBAL))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (!symtable_record_directive(st, name, s))
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1252,6 +1291,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
}
|
}
|
||||||
if (!symtable_add_def(st, name, DEF_NONLOCAL))
|
if (!symtable_add_def(st, name, DEF_NONLOCAL))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (!symtable_record_directive(st, name, s))
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue