[pypy-commit] pypy py3.3: Handle optimize=1 in calls to compile builtin function (remove asserts).

kvas noreply at buildbot.pypy.org
Sun Jul 27 11:54:53 CEST 2014


Author: Vasily Kuznetsov <kvas.it at gmail.com>
Branch: py3.3
Changeset: r72553:52aa5e85cfdf
Date: 2014-07-27 11:53 +0200
http://bitbucket.org/pypy/pypy/changeset/52aa5e85cfdf/

Log:	Handle optimize=1 in calls to compile builtin function (remove
	asserts).

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
@@ -435,9 +435,12 @@
             self.error("illegal expression for augmented assignment", assign)
 
     def visit_Assert(self, asrt):
+        if self.compile_info.optimize >= 1:
+            return
         self.update_position(asrt.lineno)
         end = self.new_block()
-        self.emit_jump(ops.JUMP_IF_NOT_DEBUG, end)
+        if self.compile_info.optimize != 0:
+            self.emit_jump(ops.JUMP_IF_NOT_DEBUG, end)
         asrt.test.accept_jump_if(self, True, end)
         self.emit_op_name(ops.LOAD_GLOBAL, self.names, "AssertionError")
         if asrt.msg:
diff --git a/pypy/interpreter/pycompiler.py b/pypy/interpreter/pycompiler.py
--- a/pypy/interpreter/pycompiler.py
+++ b/pypy/interpreter/pycompiler.py
@@ -106,7 +106,7 @@
         self.additional_rules = {}
         self.compiler_flags = self.future_flags.allowed_flags
 
-    def compile_ast(self, node, filename, mode, flags):
+    def compile_ast(self, node, filename, mode, flags, optimize=-1):
         if mode == 'eval':
             check = isinstance(node, ast.Expression)
         elif mode == 'exec':
@@ -123,7 +123,8 @@
         f_flags, f_lineno, f_col = fut
         future_pos = f_lineno, f_col
         flags |= f_flags
-        info = pyparse.CompileInfo(filename, mode, flags, future_pos)
+        info = pyparse.CompileInfo(filename, mode, flags, future_pos,
+                optimize=optimize)
         return self._compile_ast(node, info)
 
     def _compile_ast(self, node, info):
@@ -163,8 +164,9 @@
                                  e.wrap_info(space))
         return mod
 
-    def compile(self, source, filename, mode, flags, hidden_applevel=False):
+    def compile(self, source, filename, mode, flags, hidden_applevel=False,
+            optimize=-1):
         info = pyparse.CompileInfo(filename, mode, flags,
-                                   hidden_applevel=hidden_applevel)
+                hidden_applevel=hidden_applevel, optimize=optimize)
         mod = self._compile_to_ast(source, info)
         return self._compile_ast(mod, info)
diff --git a/pypy/interpreter/pyparser/pyparse.py b/pypy/interpreter/pyparser/pyparse.py
--- a/pypy/interpreter/pyparser/pyparse.py
+++ b/pypy/interpreter/pyparser/pyparse.py
@@ -69,15 +69,21 @@
       import.
     * hidden_applevel: Will this code unit and sub units be hidden at the
       applevel?
+    * optimize: optimization level:
+        -1 = same as interpreter,
+         0 = no optmiziation,
+         1 = remove asserts,
+         2 = remove docstrings.
     """
 
     def __init__(self, filename, mode="exec", flags=0, future_pos=(0, 0),
-                 hidden_applevel=False):
+                 hidden_applevel=False, optimize=-1):
         rstring.check_str0(filename)
         self.filename = filename
         self.mode = mode
         self.encoding = None
         self.flags = flags
+        self.optimize = optimize
         self.last_future_import = future_pos
         self.hidden_applevel = hidden_applevel
 
diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -43,13 +43,12 @@
             space.w_ValueError,
             space.wrap("compile() arg 3 must be 'exec', 'eval' or 'single'"))
 
-    # XXX: optimize flag is not used
-
     if space.isinstance_w(w_source, space.gettypeobject(ast.AST.typedef)):
         ast_node = space.interp_w(ast.mod, w_source)
         ast_node.sync_app_attrs(space)
         ec.compiler.validate_ast(ast_node)
-        code = ec.compiler.compile_ast(ast_node, filename, mode, flags)
+        code = ec.compiler.compile_ast(ast_node, filename, mode, flags,
+                optimize=optimize)
         return space.wrap(code)
 
     flags |= consts.PyCF_SOURCE_IS_UTF8
@@ -59,7 +58,8 @@
     if flags & consts.PyCF_ONLY_AST:
         code = ec.compiler.compile_to_ast(source, filename, mode, flags)
     else:
-        code = ec.compiler.compile(source, filename, mode, flags)
+        code = ec.compiler.compile(source, filename, mode, flags,
+                optimize=optimize)
     return space.wrap(code)
 
 
diff --git a/pypy/module/__builtin__/test/test_compile.py b/pypy/module/__builtin__/test/test_compile.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__builtin__/test/test_compile.py
@@ -0,0 +1,58 @@
+class AppTestCompile:
+
+    # TODO: This test still fails for now because the docstrings are not
+    #       removed with optimize=2.
+    def untest_compile(self):
+        import ast
+
+        codestr = '''def f():
+        """doc"""
+        try:
+            assert False
+        except AssertionError:
+            return (True, f.__doc__)
+        else:
+            return (False, f.__doc__)
+        '''
+
+        def f(): """doc"""
+        values = [(-1, __debug__, f.__doc__),
+                  (0, True, 'doc'),
+                  (1, False, 'doc'),
+                  (2, False, None)]
+
+        for optval, debugval, docstring in values:
+            # test both direct compilation and compilation via AST
+            codeobjs = []
+            codeobjs.append(
+                    compile(codestr, "<test>", "exec", optimize=optval))
+            tree = ast.parse(codestr)
+            codeobjs.append(compile(tree, "<test>", "exec", optimize=optval))
+
+            for i, code in enumerate(codeobjs):
+                print(optval, debugval, docstring, i)
+                ns = {}
+                exec(code, ns)
+                rv = ns['f']()
+                assert rv == (debugval, docstring)
+
+    def test_assert_remove(self):
+        """Test just removal of the asserts with optimize=1."""
+        import ast
+
+        code = """def f():
+        assert False
+        """
+        tree = ast.parse(code)
+        for to_compile in [code, tree]:
+            compiled = compile(to_compile, "<test>", "exec", optimize=1)
+            ns = {}
+            exec(compiled, ns)
+            ns['f']()
+
+
+# TODO: Remove docstrings with optimize=2.
+# TODO: Check the value of __debug__ inside of the compiled block!
+#       According to the documentation, it should follow the optimize flag.
+# TODO: It would also be good to test that with the assert is not removed and
+#       is executed when -O flag is set but optimize=0.


More information about the pypy-commit mailing list