diff options
Diffstat (limited to 'Python/symtable.c')
| -rw-r--r-- | Python/symtable.c | 187 | 
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;          } | 
