summaryrefslogtreecommitdiffstats
path: root/Python/symtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/symtable.c')
-rw-r--r--Python/symtable.c187
1 files changed, 121 insertions, 66 deletions
diff --git a/Python/symtable.c b/Python/symtable.c
index 1e13b790..da164aa 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -37,24 +37,14 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
ste->ste_table = st;
ste->ste_id = k; /* ste owns reference to k */
- ste->ste_name = name;
Py_INCREF(name);
+ ste->ste_name = name;
ste->ste_symbols = NULL;
ste->ste_varnames = NULL;
ste->ste_children = NULL;
- ste->ste_symbols = PyDict_New();
- if (ste->ste_symbols == NULL)
- goto fail;
-
- ste->ste_varnames = PyList_New(0);
- if (ste->ste_varnames == NULL)
- goto fail;
-
- ste->ste_children = PyList_New(0);
- if (ste->ste_children == NULL)
- goto fail;
+ ste->ste_directives = NULL;
ste->ste_type = block;
ste->ste_unoptimized = 0;
@@ -75,6 +65,15 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
ste->ste_child_free = 0;
ste->ste_generator = 0;
ste->ste_returns_value = 0;
+ ste->ste_needs_class_closure = 0;
+
+ ste->ste_symbols = PyDict_New();
+ ste->ste_varnames = PyList_New(0);
+ ste->ste_children = PyList_New(0);
+ if (ste->ste_symbols == NULL
+ || ste->ste_varnames == NULL
+ || ste->ste_children == NULL)
+ goto fail;
if (PyDict_SetItem(st->st_blocks, ste->ste_id, (PyObject *)ste) < 0)
goto fail;
@@ -102,6 +101,7 @@ ste_dealloc(PySTEntryObject *ste)
Py_XDECREF(ste->ste_symbols);
Py_XDECREF(ste->ste_varnames);
Py_XDECREF(ste->ste_children);
+ Py_XDECREF(ste->ste_directives);
PyObject_Del(ste);
}
@@ -188,7 +188,7 @@ static int symtable_visit_withitem(struct symtable *st, withitem_ty item);
static identifier top = NULL, lambda = NULL, genexpr = NULL,
listcomp = NULL, setcomp = NULL, dictcomp = NULL,
- __class__ = NULL, __locals__ = NULL;
+ __class__ = NULL;
#define GET_IDENTIFIER(VAR) \
((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR)))
@@ -233,7 +233,7 @@ symtable_new(void)
#define COMPILER_STACK_FRAME_SCALE 3
struct symtable *
-PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
+PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
{
struct symtable *st = symtable_new();
asdl_seq *seq;
@@ -242,7 +242,12 @@ PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
int recursion_limit = Py_GetRecursionLimit();
if (st == NULL)
- return st;
+ return NULL;
+ if (filename == NULL) {
+ PySymtable_Free(st);
+ return NULL;
+ }
+ Py_INCREF(filename);
st->st_filename = filename;
st->st_future = future;
@@ -306,9 +311,23 @@ PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
return NULL;
}
+struct symtable *
+PySymtable_Build(mod_ty mod, const char *filename_str, PyFutureFeatures *future)
+{
+ PyObject *filename;
+ struct symtable *st;
+ filename = PyUnicode_DecodeFSDefault(filename_str);
+ if (filename == NULL)
+ return NULL;
+ st = PySymtable_BuildObject(mod, filename, future);
+ Py_DECREF(filename);
+ return st;
+}
+
void
PySymtable_Free(struct symtable *st)
{
+ Py_XDECREF(st->st_filename);
Py_XDECREF(st->st_blocks);
Py_XDECREF(st->st_stack);
PyMem_Free((void *)st);
@@ -346,6 +365,24 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
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_SyntaxLocationObject(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.
@@ -420,16 +457,13 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
PyErr_Format(PyExc_SyntaxError,
"name '%U' is parameter and global",
name);
- PyErr_SyntaxLocationEx(ste->ste_table->st_filename,
- ste->ste_lineno, ste->ste_col_offset);
-
- return 0;
+ return error_at_directive(ste, name);
}
if (flags & DEF_NONLOCAL) {
PyErr_Format(PyExc_SyntaxError,
"name '%U' is nonlocal and global",
name);
- return 0;
+ return error_at_directive(ste, name);
}
SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
if (PySet_Add(global, name) < 0)
@@ -443,19 +477,19 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
PyErr_Format(PyExc_SyntaxError,
"name '%U' is parameter and nonlocal",
name);
- return 0;
+ return error_at_directive(ste, name);
}
if (!bound) {
PyErr_Format(PyExc_SyntaxError,
"nonlocal declaration not allowed at module level");
- return 0;
+ return error_at_directive(ste, name);
}
if (!PySet_Contains(bound, name)) {
PyErr_Format(PyExc_SyntaxError,
"no binding for nonlocal '%U' found",
name);
- return 0;
+ return error_at_directive(ste, name);
}
SET_SCOPE(scopes, name, FREE);
ste->ste_free = 1;
@@ -500,13 +534,10 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
Note that the current block's free variables are included in free.
That's safe because no name can be free and local in the same scope.
-
- The 'restricted' argument may be set to a string to restrict the analysis
- to the one variable whose name equals that string (e.g. "__class__").
*/
static int
-analyze_cells(PyObject *scopes, PyObject *free, const char *restricted)
+analyze_cells(PyObject *scopes, PyObject *free)
{
PyObject *name, *v, *v_cell;
int success = 0;
@@ -523,9 +554,6 @@ analyze_cells(PyObject *scopes, PyObject *free, const char *restricted)
continue;
if (!PySet_Contains(free, name))
continue;
- if (restricted != NULL &&
- PyUnicode_CompareWithASCIIString(name, restricted))
- continue;
/* Replace LOCAL with CELL for this name, and remove
from free. It is safe to replace the value of name
in the dict, because it will not cause a resize.
@@ -541,6 +569,20 @@ analyze_cells(PyObject *scopes, PyObject *free, const char *restricted)
return success;
}
+static int
+drop_class_free(PySTEntryObject *ste, PyObject *free)
+{
+ int res;
+ if (!GET_IDENTIFIER(__class__))
+ return 0;
+ res = PySet_Discard(free, __class__);
+ if (res < 0)
+ return 0;
+ if (res)
+ ste->ste_needs_class_closure = 1;
+ return 1;
+}
+
/* Check for illegal statements in unoptimized namespaces */
static int
check_unoptimized(const PySTEntryObject* ste) {
@@ -564,8 +606,9 @@ check_unoptimized(const PySTEntryObject* ste) {
break;
}
- PyErr_SyntaxLocationEx(ste->ste_table->st_filename, ste->ste_opt_lineno,
- ste->ste_opt_col_offset);
+ PyErr_SyntaxLocationObject(ste->ste_table->st_filename,
+ ste->ste_opt_lineno,
+ ste->ste_opt_col_offset);
return 0;
}
@@ -771,7 +814,6 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
/* Special-case __class__ */
if (!GET_IDENTIFIER(__class__))
goto error;
- assert(PySet_Contains(local, __class__) == 1);
if (PySet_Add(newbound, __class__) < 0)
goto error;
}
@@ -804,11 +846,9 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
Py_DECREF(temp);
/* Check if any local variables must be converted to cell variables */
- if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree,
- NULL))
+ if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree))
goto error;
- else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree,
- "__class__"))
+ else if (ste->ste_type == ClassBlock && !drop_class_free(ste, newfree))
goto error;
/* Records the results of the analysis in the symbol table entry */
if (!update_symbols(ste->ste_symbols, scopes, bound, newfree,
@@ -899,15 +939,20 @@ symtable_analyze(struct symtable *st)
static int
symtable_warn(struct symtable *st, char *msg, int lineno)
{
- if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename,
- lineno, NULL, NULL) < 0) {
+ PyObject *message = PyUnicode_FromString(msg);
+ if (message == NULL)
+ return 0;
+ if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, message, st->st_filename,
+ lineno, NULL, NULL) < 0) {
+ Py_DECREF(message);
if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
PyErr_SetString(PyExc_SyntaxError, msg);
- PyErr_SyntaxLocationEx(st->st_filename, st->st_cur->ste_lineno,
- st->st_cur->ste_col_offset);
+ PyErr_SyntaxLocationObject(st->st_filename, st->st_cur->ste_lineno,
+ st->st_cur->ste_col_offset);
}
return 0;
}
+ Py_DECREF(message);
return 1;
}
@@ -990,9 +1035,9 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag)
if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {
/* Is it better to use 'mangled' or 'name' here? */
PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name);
- PyErr_SyntaxLocationEx(st->st_filename,
- st->st_cur->ste_lineno,
- st->st_cur->ste_col_offset);
+ PyErr_SyntaxLocationObject(st->st_filename,
+ st->st_cur->ste_lineno,
+ st->st_cur->ste_col_offset);
goto error;
}
val |= flag;
@@ -1102,6 +1147,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
symtable_visit_stmt(struct symtable *st, stmt_ty s)
{
if (++st->recursion_depth > st->recursion_limit) {
@@ -1146,13 +1210,6 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
(void *)s, s->lineno, s->col_offset))
VISIT_QUIT(st, 0);
- if (!GET_IDENTIFIER(__class__) ||
- !symtable_add_def(st, __class__, DEF_LOCAL) ||
- !GET_IDENTIFIER(__locals__) ||
- !symtable_add_def(st, __locals__, DEF_PARAM)) {
- symtable_exit_block(st, s);
- VISIT_QUIT(st, 0);
- }
tmp = st->st_private;
st->st_private = s->v.ClassDef.name;
VISIT_SEQ(st, stmt, s->v.ClassDef.body);
@@ -1240,14 +1297,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
asdl_seq *seq = s->v.Global.names;
for (i = 0; i < asdl_seq_LEN(seq); i++) {
identifier name = (identifier)asdl_seq_GET(seq, i);
- long cur;
- if (st->st_cur->ste_type == ClassBlock &&
- !PyUnicode_CompareWithASCIIString(name, "__class__")) {
- PyErr_SetString(PyExc_SyntaxError, "cannot make __class__ global");
- PyErr_SyntaxLocationEx(st->st_filename, s->lineno, s->col_offset);
- return 0;
- }
- cur = symtable_lookup(st, name);
+ long cur = symtable_lookup(st, name);
if (cur < 0)
VISIT_QUIT(st, 0);
if (cur & (DEF_LOCAL | USE)) {
@@ -1268,6 +1318,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
}
if (!symtable_add_def(st, name, DEF_GLOBAL))
VISIT_QUIT(st, 0);
+ if (!symtable_record_directive(st, name, s))
+ VISIT_QUIT(st, 0);
}
break;
}
@@ -1297,6 +1349,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
}
if (!symtable_add_def(st, name, DEF_NONLOCAL))
VISIT_QUIT(st, 0);
+ if (!symtable_record_directive(st, name, s))
+ VISIT_QUIT(st, 0);
}
break;
}
@@ -1407,6 +1461,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
case Str_kind:
case Bytes_kind:
case Ellipsis_kind:
+ case NameConstant_kind:
/* Nothing to do here. */
break;
/* The following exprs can be assignment targets. */
@@ -1499,10 +1554,10 @@ symtable_visit_annotations(struct symtable *st, stmt_ty s)
if (a->args && !symtable_visit_argannotations(st, a->args))
return 0;
- if (a->varargannotation)
- VISIT(st, expr, a->varargannotation);
- if (a->kwargannotation)
- VISIT(st, expr, a->kwargannotation);
+ if (a->vararg && a->vararg->annotation)
+ VISIT(st, expr, a->vararg->annotation);
+ if (a->kwarg && a->kwarg->annotation)
+ VISIT(st, expr, a->kwarg->annotation);
if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs))
return 0;
if (s->v.FunctionDef.returns)
@@ -1521,12 +1576,12 @@ symtable_visit_arguments(struct symtable *st, arguments_ty a)
if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs))
return 0;
if (a->vararg) {
- if (!symtable_add_def(st, a->vararg, DEF_PARAM))
+ if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM))
return 0;
st->st_cur->ste_varargs = 1;
}
if (a->kwarg) {
- if (!symtable_add_def(st, a->kwarg, DEF_PARAM))
+ if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM))
return 0;
st->st_cur->ste_varkeywords = 1;
}
@@ -1587,7 +1642,7 @@ symtable_visit_alias(struct symtable *st, alias_ty a)
int lineno = st->st_cur->ste_lineno;
int col_offset = st->st_cur->ste_col_offset;
PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING);
- PyErr_SyntaxLocationEx(st->st_filename, lineno, col_offset);
+ PyErr_SyntaxLocationObject(st->st_filename, lineno, col_offset);
Py_DECREF(store_name);
return 0;
}