Author: Vasily Kuznetsov <kvas...@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. _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit