]> granicus.if.org Git - python/commitdiff
create NameConstant AST class for None, True, and False literals (closes #16619)
authorBenjamin Peterson <benjamin@python.org>
Thu, 6 Dec 2012 22:41:04 +0000 (17:41 -0500)
committerBenjamin Peterson <benjamin@python.org>
Thu, 6 Dec 2012 22:41:04 +0000 (17:41 -0500)
15 files changed:
Include/Python-ast.h
Include/asdl.h
Lib/ast.py
Lib/test/test_ast.py
Lib/test/test_syntax.py
Misc/NEWS
Parser/Python.asdl
Parser/asdl.py
Parser/asdl_c.py
Python/Python-ast.c
Python/ast.c
Python/compile.c
Python/peephole.c
Python/symtable.c
Tools/parser/unparse.py

index 7ad6cb370b794cfae7343db7cef5f5651448b8fd..9d88d5d616a52b5cd13533db8c23b15e49c6c4e7 100644 (file)
@@ -182,8 +182,9 @@ enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
                   SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11,
                   Yield_kind=12, YieldFrom_kind=13, Compare_kind=14,
                   Call_kind=15, Num_kind=16, Str_kind=17, Bytes_kind=18,
-                  Ellipsis_kind=19, Attribute_kind=20, Subscript_kind=21,
-                  Starred_kind=22, Name_kind=23, List_kind=24, Tuple_kind=25};
+                  NameConstant_kind=19, Ellipsis_kind=20, Attribute_kind=21,
+                  Subscript_kind=22, Starred_kind=23, Name_kind=24,
+                  List_kind=25, Tuple_kind=26};
 struct _expr {
         enum _expr_kind kind;
         union {
@@ -278,6 +279,10 @@ struct _expr {
                         bytes s;
                 } Bytes;
                 
+                struct {
+                        singleton value;
+                } NameConstant;
+                
                 struct {
                         expr_ty value;
                         identifier attr;
@@ -509,6 +514,9 @@ expr_ty _Py_Num(object n, int lineno, int col_offset, PyArena *arena);
 expr_ty _Py_Str(string s, int lineno, int col_offset, PyArena *arena);
 #define Bytes(a0, a1, a2, a3) _Py_Bytes(a0, a1, a2, a3)
 expr_ty _Py_Bytes(bytes s, int lineno, int col_offset, PyArena *arena);
+#define NameConstant(a0, a1, a2, a3) _Py_NameConstant(a0, a1, a2, a3)
+expr_ty _Py_NameConstant(singleton value, int lineno, int col_offset, PyArena
+                         *arena);
 #define Ellipsis(a0, a1, a2) _Py_Ellipsis(a0, a1, a2)
 expr_ty _Py_Ellipsis(int lineno, int col_offset, PyArena *arena);
 #define Attribute(a0, a1, a2, a3, a4, a5) _Py_Attribute(a0, a1, a2, a3, a4, a5)
index 6bf618f3e9665670dc3d27568d7714d8b75b329e..0789ad870beae4098f019e1bc4e7c40ac91ce86b 100644 (file)
@@ -5,6 +5,7 @@ typedef PyObject * identifier;
 typedef PyObject * string;
 typedef PyObject * bytes;
 typedef PyObject * object;
+typedef PyObject * singleton;
 
 /* It would be nice if the code generated by asdl_c.py was completely
    independent of Python, but it is a goal the requires too much work
index 13f59f9dfa2ca2248f94bab4bafcfe31883b5e93..02c3b2867fa85546d96c9a873d0428930b323e08 100644 (file)
@@ -42,7 +42,6 @@ def literal_eval(node_or_string):
     Python literal structures: strings, bytes, numbers, tuples, lists, dicts,
     sets, booleans, and None.
     """
-    _safe_names = {'None': None, 'True': True, 'False': False}
     if isinstance(node_or_string, str):
         node_or_string = parse(node_or_string, mode='eval')
     if isinstance(node_or_string, Expression):
@@ -61,9 +60,8 @@ def literal_eval(node_or_string):
         elif isinstance(node, Dict):
             return dict((_convert(k), _convert(v)) for k, v
                         in zip(node.keys, node.values))
-        elif isinstance(node, Name):
-            if node.id in _safe_names:
-                return _safe_names[node.id]
+        elif isinstance(node, NameConstant):
+            return node.value
         elif isinstance(node, UnaryOp) and \
              isinstance(node.op, (UAdd, USub)) and \
              isinstance(node.operand, (Num, UnaryOp, BinOp)):
index dc24126b2194a0c63439703c865018cfe4208618..36907b4eaa65fb8c2ff91b19e52c69607aeae926 100644 (file)
@@ -928,6 +928,9 @@ class ASTValidatorTests(unittest.TestCase):
     def test_tuple(self):
         self._sequence(ast.Tuple)
 
+    def test_nameconstant(self):
+        self.expr(ast.NameConstant(4), "singleton must be True, False, or None")
+
     def test_stdlib_validates(self):
         stdlib = os.path.dirname(ast.__file__)
         tests = [fn for fn in os.listdir(stdlib) if fn.endswith(".py")]
@@ -959,13 +962,13 @@ def main():
 
 #### EVERYTHING BELOW IS GENERATED #####
 exec_results = [
-('Module', [('Expr', (1, 0), ('Name', (1, 0), 'None', ('Load',)))]),
+('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))]),
 ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, [], None, None, [], []), [('Pass', (1, 9))], [], None)]),
 ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', 'a', None)], None, None, [], None, None, [], []), [('Pass', (1, 10))], [], None)]),
 ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', 'a', None)], None, None, [], None, None, [('Num', (1, 8), 0)], []), [('Pass', (1, 12))], [], None)]),
 ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], 'args', None, [], None, None, [], []), [('Pass', (1, 14))], [], None)]),
 ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, [], 'kwargs', None, [], []), [('Pass', (1, 17))], [], None)]),
-('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', 'a', None), ('arg', 'b', None), ('arg', 'c', None), ('arg', 'd', None), ('arg', 'e', None)], 'args', None, [], 'kwargs', None, [('Num', (1, 11), 1), ('Name', (1, 16), 'None', ('Load',)), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])], []), [('Pass', (1, 52))], [], None)]),
+('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', 'a', None), ('arg', 'b', None), ('arg', 'c', None), ('arg', 'd', None), ('arg', 'e', None)], 'args', None, [], 'kwargs', None, [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])], []), [('Pass', (1, 52))], [], None)]),
 ('Module', [('ClassDef', (1, 0), 'C', [], [], None, None, [('Pass', (1, 8))], [])]),
 ('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], None, None, [('Pass', (1, 17))], [])]),
 ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, [], None, None, [], []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]),
@@ -1002,14 +1005,14 @@ single_results = [
 ('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]),
 ]
 eval_results = [
-('Expression', ('Name', (1, 0), 'None', ('Load',))),
+('Expression', ('NameConstant', (1, 0), None)),
 ('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])),
 ('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))),
 ('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))),
-('Expression', ('Lambda', (1, 0), ('arguments', [], None, None, [], None, None, [], []), ('Name', (1, 7), 'None', ('Load',)))),
+('Expression', ('Lambda', (1, 0), ('arguments', [], None, None, [], None, None, [], []), ('NameConstant', (1, 7), None))),
 ('Expression', ('Dict', (1, 0), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])),
 ('Expression', ('Dict', (1, 0), [], [])),
-('Expression', ('Set', (1, 0), [('Name', (1, 1), 'None', ('Load',))])),
+('Expression', ('Set', (1, 0), [('NameConstant', (1, 1), None)])),
 ('Expression', ('Dict', (1, 0), [('Num', (2, 6), 1)], [('Num', (4, 10), 2)])),
 ('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])),
 ('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])),
index 5926b69c93bc3dd6198d3b9131b445c8e09537b9..a9d36288195463986052aa6f3f98f213bc793e5e 100644 (file)
@@ -33,7 +33,7 @@ SyntaxError: invalid syntax
 
 >>> None = 1
 Traceback (most recent call last):
-SyntaxError: assignment to keyword
+SyntaxError: can't assign to keyword
 
 It's a syntax error to assign to the empty tuple.  Why isn't it an
 error to assign to the empty list?  It will always raise some error at
@@ -233,7 +233,7 @@ Traceback (most recent call last):
 SyntaxError: can't assign to generator expression
 >>> None += 1
 Traceback (most recent call last):
-SyntaxError: assignment to keyword
+SyntaxError: can't assign to keyword
 >>> f() += 1
 Traceback (most recent call last):
 SyntaxError: can't assign to function call
index 6f7308497d60fb959e6992bb2040607001c30b34..1f2687a12e12949eaa0e4f72af97b8673ed35c11 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@ What's New in Python 3.4.0 Alpha 1?
 Core and Builtins
 -----------------
 
+- Issue #16619: Create NameConstant AST class to represent None, True, and False
+  literals. As a result, these constants are never loaded at runtime from
+  builtins.
+
 - Issue #16455: On FreeBSD and Solaris, if the locale is C, the
   ASCII/surrogateescape codec is now used, instead of the locale encoding, to
   decode the command line arguments. This change fixes inconsistencies with
index c24d8406192aef341c2f50691b01375008a32f67..0d373b09d3237babbfe7c9c4a1b25c8e2bbb0793 100644 (file)
@@ -1,4 +1,4 @@
--- ASDL's five builtin types are identifier, int, string, bytes, object
+-- ASDL's six builtin types are identifier, int, string, bytes, object, singleton
 
 module Python
 {
@@ -69,8 +69,8 @@ module Python
          | Num(object n) -- a number as a PyObject.
          | Str(string s) -- need to specify raw, unicode, etc?
          | Bytes(bytes s)
+         | NameConstant(singleton value)
          | Ellipsis
-         -- other literals? bools?
 
          -- the following expression can appear in assignment context
          | Attribute(expr value, identifier attr, expr_context ctx)
index 08aa05b897c89ff0a6212aeceaf8160c4334fcf1..1f98ada992f07707f49e895d756ace537f0c4873 100644 (file)
@@ -222,7 +222,7 @@ class ASDLParser(spark.GenericParser, object):
         " field ::= Id ? "
         return Field(type[0], opt=True)
 
-builtin_types = ("identifier", "string", "bytes", "int", "object")
+builtin_types = ("identifier", "string", "bytes", "int", "object", "singleton")
 
 # below is a collection of classes to capture the AST of an AST :-)
 # not sure if any of the methods are useful yet, but I'm adding them
index a9e6626ab411c2021f1c9a31d1394e07d47b735e..9557ba0cf2cd33942e00506be5e6b264c0911542 100755 (executable)
@@ -820,6 +820,7 @@ static PyObject* ast2obj_object(void *o)
     Py_INCREF((PyObject*)o);
     return (PyObject*)o;
 }
+#define ast2obj_singleton ast2obj_object
 #define ast2obj_identifier ast2obj_object
 #define ast2obj_string ast2obj_object
 #define ast2obj_bytes ast2obj_object
@@ -831,6 +832,17 @@ static PyObject* ast2obj_int(long b)
 
 /* Conversion Python -> AST */
 
+static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena)
+{
+    if (obj != Py_None && obj != Py_True && obj != Py_False) {
+        PyErr_SetString(PyExc_ValueError,
+                        "AST singleton must be True, False, or None");
+        return 1;
+    }
+    *out = obj;
+    return 0;
+}
+
 static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
 {
     if (obj == Py_None)
index e6f1e58252e4511f91d01edada85cd6b66fbacd8..20b7acb8865764ff46486f4f730f4d3e34611547 100644 (file)
@@ -271,6 +271,10 @@ static PyTypeObject *Bytes_type;
 static char *Bytes_fields[]={
         "s",
 };
+static PyTypeObject *NameConstant_type;
+static char *NameConstant_fields[]={
+        "value",
+};
 static PyTypeObject *Ellipsis_type;
 static PyTypeObject *Attribute_type;
 _Py_IDENTIFIER(attr);
@@ -673,6 +677,7 @@ static PyObject* ast2obj_object(void *o)
     Py_INCREF((PyObject*)o);
     return (PyObject*)o;
 }
+#define ast2obj_singleton ast2obj_object
 #define ast2obj_identifier ast2obj_object
 #define ast2obj_string ast2obj_object
 #define ast2obj_bytes ast2obj_object
@@ -684,6 +689,17 @@ static PyObject* ast2obj_int(long b)
 
 /* Conversion Python -> AST */
 
+static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena)
+{
+    if (obj != Py_None && obj != Py_True && obj != Py_False) {
+        PyErr_SetString(PyExc_ValueError,
+                        "AST singleton must be True, False, or None");
+        return 1;
+    }
+    *out = obj;
+    return 0;
+}
+
 static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
 {
     if (obj == Py_None)
@@ -860,6 +876,9 @@ static int init_types(void)
         if (!Str_type) return 0;
         Bytes_type = make_type("Bytes", expr_type, Bytes_fields, 1);
         if (!Bytes_type) return 0;
+        NameConstant_type = make_type("NameConstant", expr_type,
+                                      NameConstant_fields, 1);
+        if (!NameConstant_type) return 0;
         Ellipsis_type = make_type("Ellipsis", expr_type, NULL, 0);
         if (!Ellipsis_type) return 0;
         Attribute_type = make_type("Attribute", expr_type, Attribute_fields, 3);
@@ -1920,6 +1939,25 @@ Bytes(bytes s, int lineno, int col_offset, PyArena *arena)
         return p;
 }
 
+expr_ty
+NameConstant(singleton value, int lineno, int col_offset, PyArena *arena)
+{
+        expr_ty p;
+        if (!value) {
+                PyErr_SetString(PyExc_ValueError,
+                                "field value is required for NameConstant");
+                return NULL;
+        }
+        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+        if (!p)
+                return NULL;
+        p->kind = NameConstant_kind;
+        p->v.NameConstant.value = value;
+        p->lineno = lineno;
+        p->col_offset = col_offset;
+        return p;
+}
+
 expr_ty
 Ellipsis(int lineno, int col_offset, PyArena *arena)
 {
@@ -2028,6 +2066,7 @@ Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, PyArena
      *arena)
 {
         expr_ty p;
+        assert(PyUnicode_CompareWithASCIIString(id, "True") && PyUnicode_CompareWithASCIIString(id, "False") && PyUnicode_CompareWithASCIIString(id, "None"));
         if (!id) {
                 PyErr_SetString(PyExc_ValueError,
                                 "field id is required for Name");
@@ -2948,6 +2987,15 @@ ast2obj_expr(void* _o)
                         goto failed;
                 Py_DECREF(value);
                 break;
+        case NameConstant_kind:
+                result = PyType_GenericNew(NameConstant_type, NULL, NULL);
+                if (!result) goto failed;
+                value = ast2obj_singleton(o->v.NameConstant.value);
+                if (!value) goto failed;
+                if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
+                        goto failed;
+                Py_DECREF(value);
+                break;
         case Ellipsis_kind:
                 result = PyType_GenericNew(Ellipsis_type, NULL, NULL);
                 if (!result) goto failed;
@@ -5688,6 +5736,29 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
                 if (*out == NULL) goto failed;
                 return 0;
         }
+        isinstance = PyObject_IsInstance(obj, (PyObject*)NameConstant_type);
+        if (isinstance == -1) {
+                return 1;
+        }
+        if (isinstance) {
+                singleton value;
+
+                if (_PyObject_HasAttrId(obj, &PyId_value)) {
+                        int res;
+                        tmp = _PyObject_GetAttrId(obj, &PyId_value);
+                        if (tmp == NULL) goto failed;
+                        res = obj2ast_singleton(tmp, &value, arena);
+                        if (res != 0) goto failed;
+                        Py_XDECREF(tmp);
+                        tmp = NULL;
+                } else {
+                        PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from NameConstant");
+                        return 1;
+                }
+                *out = NameConstant(value, lineno, col_offset, arena);
+                if (*out == NULL) goto failed;
+                return 0;
+        }
         isinstance = PyObject_IsInstance(obj, (PyObject*)Ellipsis_type);
         if (isinstance == -1) {
                 return 1;
@@ -7008,6 +7079,8 @@ PyInit__ast(void)
             NULL;
         if (PyDict_SetItemString(d, "Bytes", (PyObject*)Bytes_type) < 0) return
             NULL;
+        if (PyDict_SetItemString(d, "NameConstant",
+            (PyObject*)NameConstant_type) < 0) return NULL;
         if (PyDict_SetItemString(d, "Ellipsis", (PyObject*)Ellipsis_type) < 0)
             return NULL;
         if (PyDict_SetItemString(d, "Attribute", (PyObject*)Attribute_type) <
index 7657b22459f44df23774b6a76560ddc93e5552a5..50603033d56b7d8525d8831aa7364b71d17495f8 100644 (file)
@@ -282,6 +282,7 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
         return validate_exprs(exp->v.Tuple.elts, ctx, 0);
     /* These last cases don't have any checking. */
     case Name_kind:
+    case NameConstant_kind:
     case Ellipsis_kind:
         return 1;
     default:
@@ -903,7 +904,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
             break;
         case Name_kind:
             if (ctx == Store) {
-                if (forbidden_name(c, e->v.Name.id, n, 1))
+                if (forbidden_name(c, e->v.Name.id, n, 0))
                     return 0; /* forbidden_name() calls ast_error() */
             }
             e->v.Name.ctx = ctx;
@@ -955,6 +956,9 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
         case Bytes_kind:
             expr_name = "literal";
             break;
+        case NameConstant_kind:
+            expr_name = "keyword";
+            break;
         case Ellipsis_kind:
             expr_name = "Ellipsis";
             break;
@@ -1819,11 +1823,21 @@ ast_for_atom(struct compiling *c, const node *n)
 
     switch (TYPE(ch)) {
     case NAME: {
-        /* All names start in Load context, but may later be
-           changed. */
-        PyObject *name = NEW_IDENTIFIER(ch);
+        PyObject *name;
+        const char *s = STR(ch);
+        size_t len = strlen(s);
+        if (len >= 4 && len <= 5) {
+            if (!strcmp(s, "None"))
+                return NameConstant(Py_None, LINENO(n), n->n_col_offset, c->c_arena);
+            if (!strcmp(s, "True"))
+                return NameConstant(Py_True, LINENO(n), n->n_col_offset, c->c_arena);
+            if (!strcmp(s, "False"))
+                return NameConstant(Py_False, LINENO(n), n->n_col_offset, c->c_arena);
+        }
+        name = new_identifier(s, c);
         if (!name)
             return NULL;
+        /* All names start in Load context, but may later be changed. */
         return Name(name, Load, LINENO(n), n->n_col_offset, c->c_arena);
     }
     case STRING: {
index 3cf71ef09e2d27b3e93fbd16be1558f406d4aca7..3e960ccbfec0757c8ed42d613d23e61b3af7b13b 100644 (file)
@@ -3194,12 +3194,18 @@ expr_constant(struct compiler *c, expr_ty e)
     case Name_kind:
         /* optimize away names that can't be reassigned */
         id = PyUnicode_AsUTF8(e->v.Name.id);
-        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 ! c->c_optimize;
-        /* fall through */
+        if (id && strcmp(id, "__debug__") == 0)
+            return !c->c_optimize;
+        return -1;
+    case NameConstant_kind: {
+        PyObject *o = e->v.NameConstant.value;
+        if (o == Py_None)
+            return 0;
+        else if (o == Py_True)
+            return 1;
+        else if (o == Py_False)
+            return 0;
+    }
     default:
         return -1;
     }
@@ -3375,6 +3381,9 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
     case Ellipsis_kind:
         ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts);
         break;
+    case NameConstant_kind:
+        ADDOP_O(c, LOAD_CONST, e->v.NameConstant.value, consts);
+        break;
     /* The following exprs can be assignment targets. */
     case Attribute_kind:
         if (e->v.Attribute.ctx != AugStore)
index 5d536779acf894558c6fb593a3f8493a4c6e0960..e6877bb3e6a5ba7527476c36403361e02f501873 100644 (file)
@@ -327,37 +327,6 @@ markblocks(unsigned char *code, Py_ssize_t 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.
@@ -392,7 +361,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
     Py_ssize_t const_stack_size = 0;
     int in_consts = 0;  /* whether we are in a LOAD_CONST sequence */
     unsigned int *blocks = NULL;
-    char *name;
 
     /* Bail out if an exception is set */
     if (PyErr_Occurred())
@@ -475,20 +443,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
                 codestr[i+3] = NOP;
                 break;
 
-                /* 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 = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
-                h = load_global(codestr, i, name, consts);
-                if (h < 0)
-                    goto exitError;
-                else if (h == 0)
-                    continue;
-                CONST_STACK_PUSH_OP(i);
-                break;
-
                 /* Skip over LOAD_CONST trueconst
                    POP_JUMP_IF_FALSE xx. This improves
                    "while 1" performance. */
index 8d941f0d549ec2ee93ef68dc587a09544afa12c4..d16bfbcad340626595fea3eab134a04a9ec75ee3 100644 (file)
@@ -1437,6 +1437,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. */
index b55e2c6235ad1947844e48f3614b634adc0eff07..28b2d5bc019ba112d7e3f701f128047552048178 100644 (file)
@@ -307,6 +307,9 @@ class Unparser:
     def _Name(self, t):
         self.write(t.id)
 
+    def _NameConstant(self, t):
+        self.write(repr(t.value))
+
     def _Num(self, t):
         # Substitute overflowing decimal literal for AST infinities.
         self.write(repr(t.n).replace("inf", INFSTR))