summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/ast.c35
-rw-r--r--Python/bltinmodule.c69
-rw-r--r--Python/compile.c64
-rw-r--r--Python/mystrtoul.c64
-rw-r--r--Python/peephole.c53
-rw-r--r--Python/structmember.c42
-rw-r--r--Python/symtable.c46
7 files changed, 207 insertions, 166 deletions
diff --git a/Python/ast.c b/Python/ast.c
index b313ef2..c611436 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -376,10 +376,6 @@ set_context(expr_ty e, expr_context_ty ctx, const node *n)
switch (e->kind) {
case Attribute_kind:
- if (ctx == Store &&
- !PyUnicode_CompareWithASCIIString(e->v.Attribute.attr, "None")) {
- return ast_error(n, "assignment to None");
- }
e->v.Attribute.ctx = ctx;
break;
case Subscript_kind:
@@ -600,10 +596,6 @@ compiler_arg(struct compiling *c, const node *n)
assert(TYPE(n) == tfpdef || TYPE(n) == vfpdef);
ch = CHILD(n, 0);
- if (!strcmp(STR(ch), "None")) {
- ast_error(ch, "assignment to None");
- return NULL;
- }
name = NEW_IDENTIFIER(ch);
if (!name)
return NULL;
@@ -641,10 +633,6 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
case tfpdef:
if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) {
expression = ast_for_expr(c, CHILD(n, i + 2));
- if (!expression) {
- ast_error(ch, "assignment to None");
- goto error;
- }
asdl_seq_SET(kwdefaults, j, expression);
i += 2; /* '=' and test */
}
@@ -663,10 +651,6 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
annotation = NULL;
}
ch = CHILD(ch, 0);
- if (!strcmp(STR(ch), "None")) {
- ast_error(ch, "assignment to None");
- goto error;
- }
arg = arg(NEW_IDENTIFIER(ch), annotation, c->c_arena);
if (!arg) {
ast_error(ch, "expecting name");
@@ -817,10 +801,6 @@ ast_for_arguments(struct compiling *c, const node *n)
if (res == -1) goto error;
i = res; /* res has new position to process */
}
- else if (!strcmp(STR(CHILD(ch, 0)), "None")) {
- ast_error(CHILD(ch, 0), "assignment to None");
- goto error;
- }
else {
vararg = NEW_IDENTIFIER(CHILD(ch, 0));
if (NCH(ch) > 1) {
@@ -841,10 +821,6 @@ ast_for_arguments(struct compiling *c, const node *n)
case DOUBLESTAR:
ch = CHILD(n, i+1); /* tfpdef */
assert(TYPE(ch) == tfpdef || TYPE(ch) == vfpdef);
- if (!strcmp(STR(CHILD(ch, 0)), "None")) {
- ast_error(CHILD(ch, 0), "assignment to None");
- goto error;
- }
kwarg = NEW_IDENTIFIER(CHILD(ch, 0));
if (NCH(ch) > 1) {
/* there is an annotation on the kwarg */
@@ -971,10 +947,6 @@ ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
name = NEW_IDENTIFIER(CHILD(n, name_i));
if (!name)
return NULL;
- else if (!strcmp(STR(CHILD(n, name_i)), "None")) {
- ast_error(CHILD(n, name_i), "assignment to None");
- return NULL;
- }
args = ast_for_arguments(c, CHILD(n, name_i + 1));
if (!args)
return NULL;
@@ -2913,11 +2885,6 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
REQ(n, classdef);
- if (!strcmp(STR(CHILD(n, 1)), "None")) {
- ast_error(n, "assignment to None");
- return NULL;
- }
-
if (NCH(n) == 4) { /* class NAME ':' suite */
s = ast_for_suite(c, CHILD(n, 3));
if (!s)
@@ -3039,8 +3006,6 @@ parsenumber(const char *s)
#ifndef WITHOUT_COMPLEX
imflag = *end == 'j' || *end == 'J';
#endif
- if (*end == 'l' || *end == 'L')
- return PyLong_FromString((char *)s, (char **)0, 0);
if (s[0] == '0') {
x = (long) PyOS_strtoul((char *)s, (char **)&end, 0);
if (x < 0 && errno == 0) {
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 3b43ff9..a2e48b1 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -31,7 +31,8 @@ static PyObject *filtertuple (PyObject *, PyObject *);
static PyObject *
builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *res;
+ PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *cell;
+ PyObject *cls = NULL;
Py_ssize_t nargs, nbases;
assert(args != NULL);
@@ -112,22 +113,25 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
}
- res = PyObject_CallFunctionObjArgs(func, ns, NULL);
- if (res != NULL) {
+ cell = PyObject_CallFunctionObjArgs(func, ns, NULL);
+ if (cell != NULL) {
PyObject *margs;
- Py_DECREF(res);
- res = NULL;
margs = Py_BuildValue("OOO", name, bases, ns);
if (margs != NULL) {
- res = PyEval_CallObjectWithKeywords(meta, margs, mkw);
+ cls = PyEval_CallObjectWithKeywords(meta, margs, mkw);
Py_DECREF(margs);
}
+ if (cls != NULL && PyCell_Check(cell)) {
+ Py_INCREF(cls);
+ PyCell_SET(cell, cls);
+ }
+ Py_DECREF(cell);
}
Py_DECREF(ns);
Py_DECREF(meta);
Py_XDECREF(mkw);
Py_DECREF(bases);
- return res;
+ return cls;
}
PyDoc_STRVAR(build_class_doc,
@@ -245,6 +249,18 @@ Return True if bool(x) is True for any x in the iterable.");
static PyObject *
+builtin_bin(PyObject *self, PyObject *v)
+{
+ return PyNumber_ToBase(v, 2);
+}
+
+PyDoc_STRVAR(bin_doc,
+"bin(number) -> string\n\
+\n\
+Return the binary representation of an integer or long integer.");
+
+
+static PyObject *
builtin_filter(PyObject *self, PyObject *args)
{
PyObject *func, *seq, *result, *it, *arg;
@@ -1192,24 +1208,7 @@ the same hash value. The reverse is not necessarily true, but likely.");
static PyObject *
builtin_hex(PyObject *self, PyObject *v)
{
- PyNumberMethods *nb;
- PyObject *res;
-
- if ((nb = v->ob_type->tp_as_number) == NULL ||
- nb->nb_hex == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "hex() argument can't be converted to hex");
- return NULL;
- }
- res = (*nb->nb_hex)(v);
- if (res && !PyString_Check(res) && !PyUnicode_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "__hex__ returned non-string (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
+ return PyNumber_ToBase(v, 16);
}
PyDoc_STRVAR(hex_doc,
@@ -1392,24 +1391,7 @@ With two or more arguments, return the largest argument.");
static PyObject *
builtin_oct(PyObject *self, PyObject *v)
{
- PyNumberMethods *nb;
- PyObject *res;
-
- if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
- nb->nb_oct == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "oct() argument can't be converted to oct");
- return NULL;
- }
- res = (*nb->nb_oct)(v);
- if (res && !PyString_Check(res) && !PyUnicode_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "__oct__ returned non-string (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
+ return PyNumber_ToBase(v, 8);
}
PyDoc_STRVAR(oct_doc,
@@ -1949,6 +1931,7 @@ static PyMethodDef builtin_methods[] = {
{"abs", builtin_abs, METH_O, abs_doc},
{"all", builtin_all, METH_O, all_doc},
{"any", builtin_any, METH_O, any_doc},
+ {"bin", builtin_bin, METH_O, bin_doc},
{"chr", builtin_chr, METH_VARARGS, chr_doc},
{"chr8", builtin_chr8, METH_VARARGS, chr8_doc},
{"cmp", builtin_cmp, METH_VARARGS, cmp_doc},
diff --git a/Python/compile.c b/Python/compile.c
index fde4591..0f5fd2d 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -373,10 +373,12 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset)
while (PyDict_Next(src, &pos, &k, &v)) {
/* XXX this should probably be a macro in symtable.h */
+ long vi;
assert(PyInt_Check(v));
- scope = (PyInt_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK;
+ vi = PyInt_AS_LONG(v);
+ scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK;
- if (scope == scope_type || PyInt_AS_LONG(v) & flag) {
+ if (scope == scope_type || vi & flag) {
PyObject *tuple, *item = PyInt_FromLong(i);
if (item == NULL) {
Py_DECREF(dest);
@@ -1125,7 +1127,8 @@ compiler_body(struct compiler *c, asdl_seq *stmts)
if (!asdl_seq_LEN(stmts))
return 1;
st = (stmt_ty)asdl_seq_GET(stmts, 0);
- if (compiler_isdocstring(st)) {
+ if (compiler_isdocstring(st) && Py_OptimizeFlag < 2) {
+ /* don't generate docstrings if -OO */
i = 1;
VISIT(c, expr, st->v.Expr.value);
if (!compiler_nameop(c, __doc__, Store))
@@ -1251,7 +1254,8 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, int args)
else /* (reftype == FREE) */
arg = compiler_lookup_arg(c->u->u_freevars, name);
if (arg == -1) {
- printf("lookup %s in %s %d %d\n"
+ fprintf(stderr,
+ "lookup %s in %s %d %d\n"
"freevars of %s: %s\n",
PyObject_REPR(name),
PyString_AS_STRING(c->u->u_name),
@@ -1474,7 +1478,6 @@ compiler_function(struct compiler *c, stmt_ty s)
static int
compiler_class(struct compiler *c, stmt_ty s)
{
- static PyObject *build_class = NULL;
static PyObject *locals = NULL;
PyCodeObject *co;
PyObject *str;
@@ -1485,13 +1488,7 @@ compiler_class(struct compiler *c, stmt_ty s)
if (!compiler_decorators(c, decos))
return 0;
-
/* initialize statics */
- if (build_class == NULL) {
- build_class = PyUnicode_FromString("__build_class__");
- if (build_class == NULL)
- return 0;
- }
if (locals == NULL) {
locals = PyUnicode_FromString("__locals__");
if (locals == NULL)
@@ -1501,14 +1498,16 @@ compiler_class(struct compiler *c, stmt_ty s)
/* ultimately generate code for:
<name> = __build_class__(<func>, <name>, *<bases>, **<keywords>)
where:
- <func> is a function/closure created from the class body
+ <func> is a function/closure created from the class body;
+ it has a single argument (__locals__) where the dict
+ (or MutableSequence) representing the locals is passed
<name> is the class name
<bases> is the positional arguments and *varargs argument
<keywords> is the keyword arguments and **kwds argument
This borrows from compiler_call.
*/
- /* 0. Create a fake variable named __locals__ */
+ /* 0. Create a fake argument named __locals__ */
ste = PySymtable_Lookup(c->c_st, s);
if (ste == NULL)
return 0;
@@ -1528,11 +1527,11 @@ compiler_class(struct compiler *c, stmt_ty s)
c->u->u_private = s->v.ClassDef.name;
/* force it to have one mandatory argument */
c->u->u_argcount = 1;
- /* load the first argument ... */
+ /* load the first argument (__locals__) ... */
ADDOP_I(c, LOAD_FAST, 0);
/* ... and store it into f_locals */
ADDOP_IN_SCOPE(c, STORE_LOCALS);
- /* load __name__ ... */
+ /* load (global) __name__ ... */
str = PyUnicode_InternFromString("__name__");
if (!str || !compiler_nameop(c, str, Load)) {
Py_XDECREF(str);
@@ -1553,8 +1552,24 @@ compiler_class(struct compiler *c, stmt_ty s)
compiler_exit_scope(c);
return 0;
}
- /* return None */
- ADDOP_O(c, LOAD_CONST, Py_None, consts);
+ /* return the (empty) __class__ cell */
+ str = PyUnicode_InternFromString("__class__");
+ if (str == NULL) {
+ compiler_exit_scope(c);
+ return 0;
+ }
+ i = compiler_lookup_arg(c->u->u_cellvars, str);
+ Py_DECREF(str);
+ if (i == -1) {
+ /* This happens when nobody references the cell */
+ PyErr_Clear();
+ /* Return None */
+ ADDOP_O(c, LOAD_CONST, Py_None, consts);
+ }
+ else {
+ /* Return the cell where to store __class__ */
+ ADDOP_I(c, LOAD_CLOSURE, i);
+ }
ADDOP_IN_SCOPE(c, RETURN_VALUE);
/* create the code object */
co = assemble(c, 1);
@@ -2421,7 +2436,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
return compiler_error(c, "can not assign to __debug__");
}
-mangled = _Py_Mangle(c->u->u_private, name);
+ mangled = _Py_Mangle(c->u->u_private, name);
if (!mangled)
return 0;
@@ -2947,6 +2962,7 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k)
static int
expr_constant(expr_ty e)
{
+ char *id;
switch (e->kind) {
case Ellipsis_kind:
return 1;
@@ -2955,11 +2971,13 @@ expr_constant(expr_ty e)
case Str_kind:
return PyObject_IsTrue(e->v.Str.s);
case Name_kind:
- /* __debug__ is not assignable, so we can optimize
- * it away in if and while statements */
- if (PyUnicode_CompareWithASCIIString(e->v.Name.id,
- "__debug__") == 0)
- return ! Py_OptimizeFlag;
+ /* optimize away names that can't be reassigned */
+ id = _PyUnicode_AsDefaultEncodedString(e->v.Name.id, NULL);
+ if (strcmp(id, "True") == 0) return 1;
+ if (strcmp(id, "False") == 0) return 0;
+ if (strcmp(id, "None") == 0) return 0;
+ if (strcmp(id, "__debug__") == 0)
+ return ! Py_OptimizeFlag;
/* fall through */
default:
return -1;
diff --git a/Python/mystrtoul.c b/Python/mystrtoul.c
index f007057..cf23051 100644
--- a/Python/mystrtoul.c
+++ b/Python/mystrtoul.c
@@ -91,7 +91,7 @@ static int digitlimit[] = {
** This is a general purpose routine for converting
** an ascii string to an integer in an arbitrary base.
** Leading white space is ignored. If 'base' is zero
-** it looks for a leading 0, 0x or 0X to tell which
+** it looks for a leading 0b, 0o or 0x to tell which
** base. If these are absent it defaults to 10.
** Base must be 0 or between 2 and 36 (inclusive).
** If 'ptr' is non-NULL it will contain a pointer to
@@ -110,29 +110,57 @@ PyOS_strtoul(register char *str, char **ptr, int base)
while (*str && isspace(Py_CHARMASK(*str)))
++str;
- /* check for leading 0 or 0x for auto-base or base 16 */
+ /* check for leading 0b, 0o or 0x for auto-base or base 16 */
switch (base) {
- case 0: /* look for leading 0, 0x or 0X */
- if (*str == '0') {
+ case 0: /* look for leading 0b, 0o or 0x */
+ if (*str == '0') {
+ ++str;
+ if (*str == 'x' || *str == 'X') {
+ ++str;
+ base = 16;
+ } else if (*str == 'o' || *str == 'O') {
++str;
- if (*str == 'x' || *str == 'X') {
+ base = 8;
+ } else if (*str == 'b' || *str == 'B') {
+ ++str;
+ base = 2;
+ } else {
+ /* skip all zeroes... */
+ while (*str == '0')
+ ++str;
+ while (isspace(Py_CHARMASK(*str)))
++str;
- base = 16;
- }
- else
- base = 8;
+ if (ptr)
+ *ptr = str;
+ return 0;
}
- else
- base = 10;
- break;
+ }
+ else
+ base = 10;
+ break;
- case 16: /* skip leading 0x or 0X */
- if (*str == '0') {
+ /* even with explicit base, skip leading 0? prefix */
+ case 16:
+ if (*str == '0') {
+ ++str;
+ if (*str == 'x' || *str == 'X')
++str;
- if (*str == 'x' || *str == 'X')
- ++str;
- }
- break;
+ }
+ break;
+ case 8:
+ if (*str == '0') {
+ ++str;
+ if (*str == 'o' || *str == 'O')
+ ++str;
+ }
+ break;
+ case 2:
+ if(*str == '0') {
+ ++str;
+ if (*str == 'b' || *str == 'B')
+ ++str;
+ }
+ break;
}
/* catch silly bases */
diff --git a/Python/peephole.c b/Python/peephole.c
index 7c4640c..d012d39 100644
--- a/Python/peephole.c
+++ b/Python/peephole.c
@@ -257,6 +257,37 @@ markblocks(unsigned char *code, int len)
return blocks;
}
+/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
+ Returns: 0 if no change, 1 if change, -1 if error */
+static int
+load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
+{
+ Py_ssize_t j;
+ PyObject *obj;
+ if (name == NULL)
+ return 0;
+ if (strcmp(name, "None") == 0)
+ obj = Py_None;
+ else if (strcmp(name, "True") == 0)
+ obj = Py_True;
+ else if (strcmp(name, "False") == 0)
+ obj = Py_False;
+ else
+ return 0;
+ for (j = 0; j < PyList_GET_SIZE(consts); j++) {
+ if (PyList_GET_ITEM(consts, j) == obj)
+ break;
+ }
+ if (j == PyList_GET_SIZE(consts)) {
+ if (PyList_Append(consts, obj) < 0)
+ return -1;
+ }
+ assert(PyList_GET_ITEM(consts, j) == obj);
+ codestr[i] = LOAD_CONST;
+ SETARG(codestr, i, j);
+ return 1;
+}
+
/* Perform basic peephole optimizations to components of a code object.
The consts object should still be in list form to allow new constants
to be appended.
@@ -302,7 +333,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
/* Avoid situations where jump retargeting could overflow */
assert(PyString_Check(code));
- codelen = PyString_Size(code);
+ codelen = PyString_GET_SIZE(code);
if (codelen > 32700)
goto exitUnchanged;
@@ -371,25 +402,17 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
codestr[i+3] = NOP;
break;
- /* Replace LOAD_GLOBAL/LOAD_NAME None
- with LOAD_CONST None */
+ /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
+ with LOAD_CONST None/True/False */
case LOAD_NAME:
case LOAD_GLOBAL:
j = GETARG(codestr, i);
name = PyString_AsString(PyTuple_GET_ITEM(names, j));
- if (name == NULL || strcmp(name, "None") != 0)
+ h = load_global(codestr, i, name, consts);
+ if (h < 0)
+ goto exitUnchanged;
+ else if (h == 0)
continue;
- for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) {
- if (PyList_GET_ITEM(consts, j) == Py_None)
- break;
- }
- if (j == PyList_GET_SIZE(consts)) {
- if (PyList_Append(consts, Py_None) == -1)
- goto exitUnchanged;
- }
- assert(PyList_GET_ITEM(consts, j) == Py_None);
- codestr[i] = LOAD_CONST;
- SETARG(codestr, i, j);
cumlc = lastlc + 1;
break;
diff --git a/Python/structmember.c b/Python/structmember.c
index b6cf2ac..1de2238 100644
--- a/Python/structmember.c
+++ b/Python/structmember.c
@@ -289,31 +289,25 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
}
break;
#ifdef HAVE_LONG_LONG
- case T_LONGLONG:
- if (!PyLong_Check(v)) {
- PyErr_BadArgument();
+ case T_LONGLONG:{
+ PY_LONG_LONG value;
+ *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
+ if ((value == -1) && PyErr_Occurred())
return -1;
- } else {
- PY_LONG_LONG value;
- *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
- if ((value == -1) && PyErr_Occurred()) {
- return -1;
- }
- }
- break;
- case T_ULONGLONG:
- if (!PyLong_Check(v)) {
- PyErr_BadArgument();
- return -1;
- } else {
- unsigned PY_LONG_LONG value;
- *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
- if ((value == (unsigned PY_LONG_LONG)-1) &&
- PyErr_Occurred()) {
- return -1;
- }
- }
- break;
+ break;
+ }
+ case T_ULONGLONG:{
+ unsigned PY_LONG_LONG value;
+ /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
+ doesn't ??? */
+ if (PyLong_Check(v))
+ *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
+ else
+ *(unsigned PY_LONG_LONG*)addr = value = PyInt_AsLong(v);
+ if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
+ return -1;
+ break;
+ }
#endif /* HAVE_LONG_LONG */
default:
PyErr_Format(PyExc_SystemError,
diff --git a/Python/symtable.c b/Python/symtable.c
index 68c1821..30e97d6 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -183,7 +183,7 @@ static int symtable_visit_annotations(struct symtable *st, stmt_ty s);
static identifier top = NULL, lambda = NULL, genexpr = NULL,
- listcomp = NULL, setcomp = NULL;
+ listcomp = NULL, setcomp = NULL, __class__ = NULL;
#define GET_IDENTIFIER(VAR) \
((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR)))
@@ -317,7 +317,7 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
/* Analyze raw symbol information to determine scope of each name.
- The next several functions are helpers for PySymtable_Analyze(),
+ The next several functions are helpers for symtable_analyze(),
which determines whether a name is local, global, or free. In addition,
it determines which local variables are cell variables; they provide
bindings that are used for free variables in enclosed blocks.
@@ -464,10 +464,13 @@ 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 'restrict' 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)
+analyze_cells(PyObject *scopes, PyObject *free, const char *restrict)
{
PyObject *name, *v, *v_cell;
int success = 0;
@@ -484,6 +487,9 @@ analyze_cells(PyObject *scopes, PyObject *free)
continue;
if (!PySet_Contains(free, name))
continue;
+ if (restrict != NULL &&
+ PyUnicode_CompareWithASCIIString(name, restrict))
+ 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.
@@ -589,7 +595,7 @@ update_symbols(PyObject *symbols, PyObject *scopes,
}
Py_DECREF(v_new);
}
- /* It's a cell, or already a free variable in this scope */
+ /* It's a cell, or already free in this scope */
Py_DECREF(name);
continue;
}
@@ -675,8 +681,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
goto error;
}
- /* Populate global and bound sets to be passed to children.
- */
+ /* Populate global and bound sets to be passed to children. */
if (ste->ste_type != ClassBlock) {
/* Add function locals to bound set */
if (ste->ste_type == FunctionBlock) {
@@ -695,6 +700,14 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
goto error;
Py_DECREF(newglobal);
}
+ else {
+ /* Special-case __class__ */
+ if (!GET_IDENTIFIER(__class__))
+ goto error;
+ assert(PySet_Contains(local, __class__) == 1);
+ if (PySet_Add(newbound, __class__) < 0)
+ goto error;
+ }
/* Recursively call analyze_block() on each child block */
for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {
@@ -709,8 +722,12 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
ste->ste_child_free = 1;
}
- /* Check if any local variables need to be converted to cell variables */
- if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree))
+ /* Check if any local variables must be converted to cell variables */
+ if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree,
+ NULL))
+ goto error;
+ else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree,
+ "__class__"))
goto error;
/* Records the results of the analysis in the symbol table entry */
if (!update_symbols(ste->ste_symbols, scopes, bound, newfree,
@@ -1027,6 +1044,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
(void *)s, s->lineno))
return 0;
+ if (!GET_IDENTIFIER(__class__) ||
+ !symtable_add_def(st, __class__, DEF_LOCAL)) {
+ symtable_exit_block(st, s);
+ return 0;
+ }
tmp = st->st_private;
st->st_private = s->v.ClassDef.name;
VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s);
@@ -1294,6 +1316,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
if (!symtable_add_def(st, e->v.Name.id,
e->v.Name.ctx == Load ? USE : DEF_LOCAL))
return 0;
+ /* Special-case super: it counts as a use of __class__ */
+ if (e->v.Name.ctx == Load &&
+ st->st_cur->ste_type == FunctionBlock &&
+ !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) {
+ if (!GET_IDENTIFIER(__class__) ||
+ !symtable_add_def(st, __class__, USE))
+ return 0;
+ }
break;
/* child nodes of List and Tuple will have expr_context set */
case List_kind: