Commit 8911a122 authored by Stefan Behnel's avatar Stefan Behnel

streamline exit code of with-statement

parent 9112fddd
...@@ -2515,6 +2515,7 @@ class WithExitCallNode(ExprNode): ...@@ -2515,6 +2515,7 @@ class WithExitCallNode(ExprNode):
# args TupleNode or ResultStatNode the exception info tuple # args TupleNode or ResultStatNode the exception info tuple
subexprs = ['args'] subexprs = ['args']
test_if_run = True
def analyse_types(self, env): def analyse_types(self, env):
self.args = self.args.analyse_types(env) self.args = self.args.analyse_types(env)
...@@ -2522,23 +2523,31 @@ class WithExitCallNode(ExprNode): ...@@ -2522,23 +2523,31 @@ class WithExitCallNode(ExprNode):
self.is_temp = True self.is_temp = True
return self return self
def generate_result_code(self, code): def generate_evaluation_code(self, code):
if isinstance(self.args, TupleNode): if self.test_if_run:
# call only if it was not already called (and decref-cleared) # call only if it was not already called (and decref-cleared)
code.putln("if (%s) {" % self.with_stat.exit_var) code.putln("if (%s) {" % self.with_stat.exit_var)
self.args.generate_evaluation_code(code)
result_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False) result_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
code.mark_pos(self.pos)
code.putln("%s = PyObject_Call(%s, %s, NULL);" % ( code.putln("%s = PyObject_Call(%s, %s, NULL);" % (
result_var, result_var,
self.with_stat.exit_var, self.with_stat.exit_var,
self.args.result())) self.args.result()))
code.put_decref_clear(self.with_stat.exit_var, type=py_object_type) code.put_decref_clear(self.with_stat.exit_var, type=py_object_type)
self.args.generate_disposal_code(code)
self.args.free_temps(code)
code.putln(code.error_goto_if_null(result_var, self.pos)) code.putln(code.error_goto_if_null(result_var, self.pos))
code.put_gotref(result_var) code.put_gotref(result_var)
self.allocate_temp_result(code)
code.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self.result(), result_var)) code.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self.result(), result_var))
code.put_decref_clear(result_var, type=py_object_type) code.put_decref_clear(result_var, type=py_object_type)
code.put_error_if_neg(self.pos, self.result()) code.put_error_if_neg(self.pos, self.result())
code.funcstate.release_temp(result_var) code.funcstate.release_temp(result_var)
if isinstance(self.args, TupleNode): if self.test_if_run:
code.putln("}") code.putln("}")
......
...@@ -1230,35 +1230,37 @@ class WithTransform(CythonTransform, SkipDeclarations): ...@@ -1230,35 +1230,37 @@ class WithTransform(CythonTransform, SkipDeclarations):
excinfo_target = ExprNodes.TupleNode(pos, slow=True, args=[ excinfo_target = ExprNodes.TupleNode(pos, slow=True, args=[
ExprNodes.ExcValueNode(pos) for _ in range(3)]) ExprNodes.ExcValueNode(pos) for _ in range(3)])
except_clause = Nodes.ExceptClauseNode( except_clause = Nodes.ExceptClauseNode(
pos, body = Nodes.IfStatNode( pos, body=Nodes.IfStatNode(
pos, if_clauses = [ pos, if_clauses=[
Nodes.IfClauseNode( Nodes.IfClauseNode(
pos, condition = ExprNodes.NotNode( pos, condition=ExprNodes.NotNode(
pos, operand = ExprNodes.WithExitCallNode( pos, operand=ExprNodes.WithExitCallNode(
pos, with_stat = node, pos, with_stat=node,
args = excinfo_target)), test_if_run=False,
body = Nodes.ReraiseStatNode(pos), args=excinfo_target)),
body=Nodes.ReraiseStatNode(pos),
), ),
], ],
else_clause = None), else_clause=None),
pattern = None, pattern=None,
target = None, target=None,
excinfo_target = excinfo_target, excinfo_target=excinfo_target,
) )
node.body = Nodes.TryFinallyStatNode( node.body = Nodes.TryFinallyStatNode(
pos, body = Nodes.TryExceptStatNode( pos, body=Nodes.TryExceptStatNode(
pos, body = body, pos, body=body,
except_clauses = [except_clause], except_clauses=[except_clause],
else_clause = None, else_clause=None,
), ),
finally_clause = Nodes.ExprStatNode( finally_clause=Nodes.ExprStatNode(
pos, expr = ExprNodes.WithExitCallNode( pos, expr=ExprNodes.WithExitCallNode(
pos, with_stat = node, pos, with_stat=node,
args = ExprNodes.TupleNode( test_if_run=True,
pos, args = [ExprNodes.NoneNode(pos) for _ in range(3)] args=ExprNodes.TupleNode(
pos, args=[ExprNodes.NoneNode(pos) for _ in range(3)]
))), ))),
handle_error_case = False, handle_error_case=False,
) )
return node return node
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment