From: Stefan Behnel Date: Sat, 23 Apr 2011 14:28:40 +0000 (+0200) Subject: clean up exc_info handling in 'with' statement implementation X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=771071fd49d2b295f8b0c199dbb1c239487ca066;p=cython.git clean up exc_info handling in 'with' statement implementation --- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index ba6a8276..8c201061 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -1944,7 +1944,7 @@ class TempNode(ExprNode): subexprs = [] - def __init__(self, pos, type, env): + def __init__(self, pos, type, env=None): ExprNode.__init__(self, pos) self.type = type if type.is_pyobject: @@ -1954,6 +1954,9 @@ class TempNode(ExprNode): def analyse_types(self, env): return self.type + def analyse_target_declaration(self, env): + pass + def generate_result_code(self, code): pass diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 28ec47ef..5358a3c3 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -5008,7 +5008,7 @@ class ExceptClauseNode(Node): # pattern [ExprNode] # target ExprNode or None # body StatNode - # excinfo_target NameNode or None optional target for exception info + # excinfo_target ResultRefNode or None optional target for exception info # match_flag string result of exception match # exc_value ExcValueNode used internally # function_name string qualified name of enclosing function @@ -5026,8 +5026,6 @@ class ExceptClauseNode(Node): def analyse_declarations(self, env): if self.target: self.target.analyse_target_declaration(env) - if self.excinfo_target is not None: - self.excinfo_target.analyse_target_declaration(env) self.body.analyse_declarations(env) def analyse_expressions(self, env): @@ -5048,7 +5046,6 @@ class ExceptClauseNode(Node): self.excinfo_tuple = ExprNodes.TupleNode(pos=self.pos, args=[ ExprNodes.ExcValueNode(pos=self.pos, env=env) for x in range(3)]) self.excinfo_tuple.analyse_expressions(env) - self.excinfo_target.analyse_target_expression(env, self.excinfo_tuple) self.body.analyse_expressions(env) @@ -5103,7 +5100,7 @@ class ExceptClauseNode(Node): for tempvar, node in zip(exc_vars, self.excinfo_tuple.args): node.set_var(tempvar) self.excinfo_tuple.generate_evaluation_code(code) - self.excinfo_target.generate_assignment_code(self.excinfo_tuple, code) + self.excinfo_target.result_code = self.excinfo_tuple.result() old_break_label, old_continue_label = code.break_label, code.continue_label code.break_label = code.new_label('except_break') @@ -5113,24 +5110,32 @@ class ExceptClauseNode(Node): code.funcstate.exc_vars = exc_vars self.body.generate_execution_code(code) code.funcstate.exc_vars = old_exc_vars + if self.excinfo_target is not None: + self.excinfo_tuple.generate_disposal_code(code) for var in exc_vars: - code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var)) + code.put_decref_clear(var, py_object_type) code.put_goto(end_label) if code.label_used(code.break_label): code.put_label(code.break_label) + if self.excinfo_target is not None: + self.excinfo_tuple.generate_disposal_code(code) for var in exc_vars: - code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var)) + code.put_decref_clear(var, py_object_type) code.put_goto(old_break_label) code.break_label = old_break_label if code.label_used(code.continue_label): code.put_label(code.continue_label) + if self.excinfo_target is not None: + self.excinfo_tuple.generate_disposal_code(code) for var in exc_vars: - code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var)) + code.put_decref_clear(var, py_object_type) code.put_goto(old_continue_label) code.continue_label = old_continue_label + if self.excinfo_target is not None: + self.excinfo_tuple.free_temps(code) for temp in exc_vars: code.funcstate.release_temp(temp) diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 2ba5aadc..f6bf584c 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -11,11 +11,12 @@ import Naming import ExprNodes import Nodes import Options +import Builtin from Cython.Compiler.Visitor import VisitorTransform, TreeVisitor from Cython.Compiler.Visitor import CythonTransform, EnvTransform, ScopeTrackingTransform from Cython.Compiler.ModuleNode import ModuleNode -from Cython.Compiler.UtilNodes import LetNode, LetRefNode +from Cython.Compiler.UtilNodes import LetNode, LetRefNode, ResultRefNode from Cython.Compiler.TreeFragment import TreeFragment, TemplateTransform from Cython.Compiler.StringEncoding import EncodedString from Cython.Compiler.Errors import error, warning, CompileError, InternalError @@ -908,7 +909,6 @@ class WithTransform(CythonTransform, SkipDeclarations): EXC = True try: try: - EXCINFO = None BODY except: EXC = False @@ -927,7 +927,6 @@ class WithTransform(CythonTransform, SkipDeclarations): EXC = True try: try: - EXCINFO = None TARGET = VALUE BODY except: @@ -937,39 +936,30 @@ class WithTransform(CythonTransform, SkipDeclarations): finally: if EXC: EXIT(None, None, None) - MGR = EXIT = VALUE = EXC = None - + MGR = EXIT = VALUE = None """, temps=[u'MGR', u'EXC', u"EXIT", u"VALUE"], pipeline=[NormalizeTree(None)]) def visit_WithStatNode(self, node): - # TODO: Cleanup badly needed - TemplateTransform.temp_name_counter += 1 - handle = "__tmpvar_%d" % TemplateTransform.temp_name_counter - + exc_info = ResultRefNode(pos=node.pos, type=Builtin.tuple_type, may_hold_none=False) self.visitchildren(node, ['body']) - excinfo_temp = ExprNodes.NameNode(node.pos, name=handle)#TempHandle(Builtin.tuple_type) if node.target is not None: result = self.template_with_target.substitute({ u'EXPR' : node.manager, u'BODY' : node.body, u'TARGET' : node.target, - u'EXCINFO' : excinfo_temp + u'EXCINFO' : exc_info, }, pos=node.pos) else: result = self.template_without_target.substitute({ u'EXPR' : node.manager, u'BODY' : node.body, - u'EXCINFO' : excinfo_temp + u'EXCINFO' : exc_info, }, pos=node.pos) # Set except excinfo target to EXCINFO try_except = result.stats[-1].body.stats[-1] - try_except.except_clauses[0].excinfo_target = ExprNodes.NameNode(node.pos, name=handle) -# excinfo_temp.ref(node.pos)) - -# result.stats[-1].body.stats[-1] = TempsBlockNode( -# node.pos, temps=[excinfo_temp], body=try_except) + try_except.except_clauses[0].excinfo_target = exc_info return result diff --git a/Cython/Compiler/UtilNodes.py b/Cython/Compiler/UtilNodes.py index 3aff81f8..42f68e92 100644 --- a/Cython/Compiler/UtilNodes.py +++ b/Cython/Compiler/UtilNodes.py @@ -134,6 +134,10 @@ class ResultRefNode(AtomicExprNode): self.type = type assert self.pos is not None + def clone_node(self): + # nothing to do here + return self + def analyse_types(self, env): if self.expression is not None: self.type = self.expression.type