diff options
Diffstat (limited to 'Python/symtable.c')
| -rw-r--r-- | Python/symtable.c | 118 | 
1 files changed, 76 insertions, 42 deletions
| diff --git a/Python/symtable.c b/Python/symtable.c index 48495f7..758aefb 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -56,6 +56,8 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,      if (ste->ste_children == NULL)          goto fail; +    ste->ste_directives = NULL; +      ste->ste_type = block;      ste->ste_unoptimized = 0;      ste->ste_nested = 0; @@ -75,6 +77,7 @@ 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;      if (PyDict_SetItem(st->st_blocks, ste->ste_id, (PyObject *)ste) < 0)          goto fail; @@ -102,6 +105,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 +192,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))) @@ -342,6 +346,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_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. @@ -416,16 +438,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) @@ -439,19 +458,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; @@ -496,13 +515,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; @@ -519,9 +535,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. @@ -537,6 +550,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) { @@ -767,7 +794,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;      } @@ -800,11 +826,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, @@ -1098,6 +1122,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) { @@ -1142,13 +1185,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); @@ -1236,14 +1272,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)) { @@ -1264,6 +1293,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;      } @@ -1293,6 +1324,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;      } @@ -1403,6 +1436,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. */ @@ -1495,10 +1529,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) @@ -1517,12 +1551,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;      } | 
