[pypy-commit] pypy py3.6: The ast module now has a "Constant" node that AST optimizers can use.

amauryfa pypy.commits at gmail.com
Sun Dec 10 16:35:28 EST 2017


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.6
Changeset: r93353:cadf41717a3f
Date: 2017-12-10 17:47 +0100
http://bitbucket.org/pypy/pypy/changeset/cadf41717a3f/

Log:	The ast module now has a "Constant" node that AST optimizers can
	use. Use it in place of PyPy's specific "Const".

diff --git a/pypy/interpreter/astcompiler/ast.py b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -1743,6 +1743,8 @@
             return NameConstant.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Ellipsis):
             return Ellipsis.from_object(space, w_node)
+        if space.isinstance_w(w_node, get(space).w_Constant):
+            return Constant.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Attribute):
             return Attribute.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Subscript):
@@ -1755,8 +1757,6 @@
             return List.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Tuple):
             return Tuple.from_object(space, w_node)
-        if space.isinstance_w(w_node, get(space).w_Const):
-            return Const.from_object(space, w_node)
         raise oefmt(space.w_TypeError,
                 "Expected expr node, got %T", w_node)
 State.ast_type('expr', 'AST', None, ['lineno', 'col_offset'])
@@ -2841,6 +2841,43 @@
 State.ast_type('Ellipsis', 'expr', [])
 
 
+class Constant(expr):
+
+    def __init__(self, value, lineno, col_offset):
+        self.value = value
+        expr.__init__(self, lineno, col_offset)
+
+    def walkabout(self, visitor):
+        visitor.visit_Constant(self)
+
+    def mutate_over(self, visitor):
+        return visitor.visit_Constant(self)
+
+    def to_object(self, space):
+        w_node = space.call_function(get(space).w_Constant)
+        w_value = self.value  # constant
+        space.setattr(w_node, space.newtext('value'), w_value)
+        w_lineno = space.newint(self.lineno)  # int
+        space.setattr(w_node, space.newtext('lineno'), w_lineno)
+        w_col_offset = space.newint(self.col_offset)  # int
+        space.setattr(w_node, space.newtext('col_offset'), w_col_offset)
+        return w_node
+
+    @staticmethod
+    def from_object(space, w_node):
+        w_value = get_field(space, w_node, 'value', False)
+        w_lineno = get_field(space, w_node, 'lineno', False)
+        w_col_offset = get_field(space, w_node, 'col_offset', False)
+        _value = w_value
+        if _value is None:
+            raise_required_value(space, w_node, 'value')
+        _lineno = space.int_w(w_lineno)
+        _col_offset = space.int_w(w_col_offset)
+        return Constant(_value, _lineno, _col_offset)
+
+State.ast_type('Constant', 'expr', ['value'])
+
+
 class Attribute(expr):
 
     def __init__(self, value, attr, ctx, lineno, col_offset):
@@ -3137,43 +3174,6 @@
 State.ast_type('Tuple', 'expr', ['elts', 'ctx'])
 
 
-class Const(expr):
-
-    def __init__(self, obj, lineno, col_offset):
-        self.obj = obj
-        expr.__init__(self, lineno, col_offset)
-
-    def walkabout(self, visitor):
-        visitor.visit_Const(self)
-
-    def mutate_over(self, visitor):
-        return visitor.visit_Const(self)
-
-    def to_object(self, space):
-        w_node = space.call_function(get(space).w_Const)
-        w_obj = self.obj  # object
-        space.setattr(w_node, space.newtext('obj'), w_obj)
-        w_lineno = space.newint(self.lineno)  # int
-        space.setattr(w_node, space.newtext('lineno'), w_lineno)
-        w_col_offset = space.newint(self.col_offset)  # int
-        space.setattr(w_node, space.newtext('col_offset'), w_col_offset)
-        return w_node
-
-    @staticmethod
-    def from_object(space, w_node):
-        w_obj = get_field(space, w_node, 'obj', False)
-        w_lineno = get_field(space, w_node, 'lineno', False)
-        w_col_offset = get_field(space, w_node, 'col_offset', False)
-        _obj = w_obj
-        if _obj is None:
-            raise_required_value(space, w_node, 'obj')
-        _lineno = space.int_w(w_lineno)
-        _col_offset = space.int_w(w_col_offset)
-        return Const(_obj, _lineno, _col_offset)
-
-State.ast_type('Const', 'expr', ['obj'])
-
-
 class expr_context(AST):
     @staticmethod
     def from_object(space, w_node):
@@ -4140,6 +4140,8 @@
         return self.default_visitor(node)
     def visit_Ellipsis(self, node):
         return self.default_visitor(node)
+    def visit_Constant(self, node):
+        return self.default_visitor(node)
     def visit_Attribute(self, node):
         return self.default_visitor(node)
     def visit_Subscript(self, node):
@@ -4152,8 +4154,6 @@
         return self.default_visitor(node)
     def visit_Tuple(self, node):
         return self.default_visitor(node)
-    def visit_Const(self, node):
-        return self.default_visitor(node)
     def visit_Slice(self, node):
         return self.default_visitor(node)
     def visit_ExtSlice(self, node):
@@ -4380,6 +4380,9 @@
     def visit_Ellipsis(self, node):
         pass
 
+    def visit_Constant(self, node):
+        pass
+
     def visit_Attribute(self, node):
         node.value.walkabout(self)
 
@@ -4399,9 +4402,6 @@
     def visit_Tuple(self, node):
         self.visit_sequence(node.elts)
 
-    def visit_Const(self, node):
-        pass
-
     def visit_Slice(self, node):
         if node.lower:
             node.lower.walkabout(self)
diff --git a/pypy/interpreter/astcompiler/asthelpers.py b/pypy/interpreter/astcompiler/asthelpers.py
--- a/pypy/interpreter/astcompiler/asthelpers.py
+++ b/pypy/interpreter/astcompiler/asthelpers.py
@@ -128,7 +128,7 @@
     _description = "dict comprehension"
 
 
-class __extend__(ast.Dict, ast.Set, ast.Str, ast.Bytes, ast.Num, ast.Const):
+class __extend__(ast.Dict, ast.Set, ast.Str, ast.Bytes, ast.Num, ast.Constant):
 
     _description = "literal"
 
@@ -150,18 +150,18 @@
     _description = "conditional expression"
 
 
-class __extend__(ast.Const):
+class __extend__(ast.Constant):
 
     constant = True
 
     def as_node_list(self, space):
         try:
-            values_w = space.unpackiterable(self.obj)
+            values_w = space.unpackiterable(self.value)
         except OperationError:
             return None
         line = self.lineno
         column = self.col_offset
-        return [ast.Const(w_obj, line, column) for w_obj in values_w]
+        return [ast.Constant(w_obj, line, column) for w_obj in values_w]
 
 
 class __extend__(ast.Str):
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -1039,9 +1039,9 @@
         self.update_position(b.lineno)
         self.load_const(b.s)
 
-    def visit_Const(self, const):
+    def visit_Constant(self, const):
         self.update_position(const.lineno)
-        self.load_const(const.obj)
+        self.load_const(const.value)
 
     def visit_Ellipsis(self, e):
         self.load_const(self.space.w_Ellipsis)
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -63,10 +63,10 @@
         return True
 
 
-class __extend__(ast.Const):
+class __extend__(ast.Constant):
 
     def as_constant(self):
-        return self.obj
+        return self.value
 
 class __extend__(ast.NameConstant):
 
@@ -208,7 +208,7 @@
                     else:
                         if self.space.int_w(w_len) > 20:
                             return binop
-                    return ast.Const(w_const, binop.lineno, binop.col_offset)
+                    return ast.Constant(w_const, binop.lineno, binop.col_offset)
         return binop
 
     def visit_UnaryOp(self, unary):
@@ -229,7 +229,7 @@
             except OperationError:
                 pass
             else:
-                return ast.Const(w_const, unary.lineno, unary.col_offset)
+                return ast.Constant(w_const, unary.lineno, unary.col_offset)
         elif op == ast.Not:
             compare = unary.operand
             if isinstance(compare, ast.Compare) and len(compare.ops) == 1:
@@ -265,7 +265,7 @@
         w_const = rep.value.as_constant()
         if w_const is not None:
             w_repr = self.space.repr(w_const)
-            return ast.Const(w_repr, rep.lineno, rep.col_offset)
+            return ast.Constant(w_repr, rep.lineno, rep.col_offset)
         return rep
 
     def visit_Name(self, name):
@@ -282,7 +282,7 @@
         elif iden == "False":
             w_const = space.w_False
         if w_const is not None:
-            return ast.Const(w_const, name.lineno, name.col_offset)
+            return ast.NameConstant(w_const, name.lineno, name.col_offset)
         return name
 
     def visit_Tuple(self, tup):
@@ -303,7 +303,7 @@
         else:
             consts_w = []
         w_consts = self.space.newtuple(consts_w)
-        return ast.Const(w_consts, tup.lineno, tup.col_offset)
+        return ast.Constant(w_consts, tup.lineno, tup.col_offset)
 
     def visit_Subscript(self, subs):
         if subs.ctx == ast.Load:
@@ -340,6 +340,6 @@
                         # See test_const_fold_unicode_subscr
                         return subs
 
-                    return ast.Const(w_const, subs.lineno, subs.col_offset)
+                    return ast.Constant(w_const, subs.lineno, subs.col_offset)
 
         return subs
diff --git a/pypy/interpreter/astcompiler/tools/Python.asdl b/pypy/interpreter/astcompiler/tools/Python.asdl
--- a/pypy/interpreter/astcompiler/tools/Python.asdl
+++ b/pypy/interpreter/astcompiler/tools/Python.asdl
@@ -1,4 +1,8 @@
--- ASDL's six builtin types are identifier, int, string, bytes, object, singleton
+-- ASDL's 7 builtin types are:
+-- identifier, int, string, bytes, object, singleton, constant
+--
+-- singleton: None, True or False
+-- constant can be None, whereas None means "no value" for object.
 
 module Python
 {
@@ -75,6 +79,7 @@
          | Bytes(bytes s)
          | NameConstant(singleton value)
          | Ellipsis
+         | Constant(constant value)
 
          -- the following expression can appear in assignment context
          | Attribute(expr value, identifier attr, expr_context ctx)
@@ -84,9 +89,6 @@
          | List(expr* elts, expr_context ctx)
          | Tuple(expr* elts, expr_context ctx)
 
-         -- PyPy modification
-         | Const(object obj)
-
           -- col_offset is the byte offset in the utf8 string the parser uses
           attributes (int lineno, int col_offset)
 
diff --git a/pypy/interpreter/astcompiler/tools/asdl.py b/pypy/interpreter/astcompiler/tools/asdl.py
--- a/pypy/interpreter/astcompiler/tools/asdl.py
+++ b/pypy/interpreter/astcompiler/tools/asdl.py
@@ -34,7 +34,7 @@
 # between the various node types.
 
 builtin_types = {'identifier', 'string', 'bytes', 'int', 'bool', 'object',
-                 'singleton'}
+                 'singleton', 'constant'}
 
 class AST:
     def __repr__(self):
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -130,7 +130,8 @@
     def get_value_converter(self, field, value):
         if field.type in self.data.simple_types:
             return "%s_to_class[%s - 1]().to_object(space)" % (field.type, value)
-        elif field.type in ("object", "singleton", "string", "bytes"):
+        elif field.type in ("object", "singleton", "constant",
+                            "string", "bytes"):
             return value
         elif field.type == "bool":
             return "space.newbool(%s)" % (value,)
@@ -155,7 +156,7 @@
     def get_value_extractor(self, field, value):
         if field.type in self.data.simple_types:
             return "%s.from_object(space, %s)" % (field.type, value)
-        elif field.type in ("object","singleton"):
+        elif field.type in ("object", "singleton", "constant"):
             return value
         elif field.type in ("string","bytes"):
             return "check_string(space, %s)" % (value,)
diff --git a/pypy/interpreter/astcompiler/validate.py b/pypy/interpreter/astcompiler/validate.py
--- a/pypy/interpreter/astcompiler/validate.py
+++ b/pypy/interpreter/astcompiler/validate.py
@@ -318,6 +318,9 @@
     def visit_Ellipsis(self, node):
         pass
 
+    def visit_Constant(self, node):
+        pass
+
     def visit_BoolOp(self, node):
         if self._len(node.values) < 2:
             raise ValidationError("BoolOp with less than 2 values")


More information about the pypy-commit mailing list