Author: Armin Rigo <ar...@tunes.org> Branch: py3.5 Changeset: r87081:19e8fc8dcfd0 Date: 2016-09-13 17:39 +0200 http://bitbucket.org/pypy/pypy/changeset/19e8fc8dcfd0/
Log: Use ast.NameConstant instead of ast.Name for None/True/False (that class was not used so far) diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py --- a/pypy/interpreter/astcompiler/astbuilder.py +++ b/pypy/interpreter/astcompiler/astbuilder.py @@ -1194,9 +1194,19 @@ first_child = atom_node.get_child(0) first_child_type = first_child.type if first_child_type == tokens.NAME: - name = self.new_identifier(first_child.get_value()) - return ast.Name(name, ast.Load, first_child.get_lineno(), - first_child.get_column()) + name = first_child.get_value() + if name == "None": + w_singleton = self.space.w_None + elif name == "True": + w_singleton = self.space.w_True + elif name == "False": + w_singleton = self.space.w_False + else: + name = self.new_identifier(name) + return ast.Name(name, ast.Load, first_child.get_lineno(), + first_child.get_column()) + return ast.NameConstant(w_singleton, first_child.get_lineno(), + first_child.get_column()) elif first_child_type == tokens.STRING: space = self.space encoding = self.compile_info.encoding 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 @@ -22,15 +22,19 @@ class __extend__(ast.expr): constant = False + _description = None def as_node_list(self, space): return None def set_context(self, ctx): + d = self._description + if d is None: + d = "%r" % (self,) if ctx == ast.Del: - msg = "can't delete %s" % (self._description,) + msg = "can't delete %s" % (d,) else: - msg = "can't assign to %s" % (self._description,) + msg = "can't assign to %s" % (d,) raise UnacceptableExpressionContext(self, msg) @@ -174,3 +178,9 @@ _description = "Ellipsis" constant = True + + +class __extend__(ast.NameConstant): + + _description = "name constant" + constant = True 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 @@ -1271,6 +1271,10 @@ self.update_position(name.lineno) self.name_op(name.id, name.ctx) + def visit_NameConstant(self, node): + self.update_position(node.lineno) + self.load_const(node.single) + def visit_keyword(self, keyword): if keyword.arg is not None: self.load_const(self.space.wrap(keyword.arg.decode('utf-8'))) 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 @@ -67,6 +67,11 @@ def as_constant(self): return self.obj +class __extend__(ast.NameConstant): + + def as_constant(self): + return self.single + class __extend__(ast.Index): def as_constant(self): return self.value.as_constant() diff --git a/pypy/interpreter/astcompiler/test/test_validate.py b/pypy/interpreter/astcompiler/test/test_validate.py --- a/pypy/interpreter/astcompiler/test/test_validate.py +++ b/pypy/interpreter/astcompiler/test/test_validate.py @@ -390,9 +390,21 @@ def test_tuple(self): self._sequence(ast.Tuple) + def test_nameconstant(self): + node = ast.NameConstant("True", 0, 0) + self.expr(node, "singleton must be True, False, or None") + def test_stdlib_validates(self): stdlib = os.path.join(os.path.dirname(ast.__file__), '../../../lib-python/3') - tests = ["os.py", "test/test_grammar.py", "test/test_unpack_ex.py"] + if 1: # enable manually for a complete test + tests = [fn for fn in os.listdir(stdlib) if fn.endswith('.py')] + tests += ['test/'+fn for fn in os.listdir(stdlib+'/test') + if fn.endswith('.py') + and not fn.startswith('bad')] + tests.sort() + else: + tests = ["os.py", "test/test_grammar.py", "test/test_unpack_ex.py"] + # for module in tests: fn = os.path.join(stdlib, module) print 'compiling', fn 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 @@ -1,6 +1,6 @@ """A visitor to validate an AST object.""" -from pypy.interpreter.error import OperationError, oefmt +from pypy.interpreter.error import oefmt from pypy.interpreter.astcompiler import ast from rpython.tool.pairtype import pair, pairtype from pypy.interpreter.baseobjspace import W_Root @@ -440,3 +440,10 @@ def visit_Index(self, node): self._validate_expr(node.value) + + def visit_NameConstant(self, node): + space = self.space + if (node.single is not space.w_None and + node.single is not space.w_True and + node.single is not space.w_False): + raise ValidationError("singleton must be True, False, or None") diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py --- a/pypy/interpreter/test/test_compiler.py +++ b/pypy/interpreter/test/test_compiler.py @@ -689,10 +689,11 @@ except NameError: pass ''' - code = self.compiler.compile(snippet, '<tmp>', 'exec', 0) + e = py.test.raises(OperationError, self.compiler.compile, + snippet, '<tmp>', 'exec', 0) + ex = e.value space = self.space - w_d = space.newdict() - space.exec_(code, w_d, w_d) + assert ex.match(space, space.w_SyntaxError) def test_from_future_import(self): source = """from __future__ import with_statement _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit