From 00d29b767d8f938e30a787403cd56e0a2f4dcea6 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Mon, 25 Apr 2011 01:09:26 +0200 Subject: [PATCH] move 'with' statement implementation back into WithTransform to fix 'with' statement usage for compiler directives --- Cython/Compiler/Main.py | 3 +- Cython/Compiler/Nodes.py | 54 ++----------------------- Cython/Compiler/ParseTreeTransforms.py | 55 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 52 deletions(-) diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py index 34d8b22f..fb8d6fcb 100644 --- a/Cython/Compiler/Main.py +++ b/Cython/Compiler/Main.py @@ -102,7 +102,7 @@ class Context(object): def create_pipeline(self, pxd, py=False): from Visitor import PrintTree - from ParseTreeTransforms import NormalizeTree, PostParse, PxdPostParse + from ParseTreeTransforms import WithTransform, NormalizeTree, PostParse, PxdPostParse from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform from ParseTreeTransforms import InterpretCompilerDirectives, TransformBuiltinMethods @@ -139,6 +139,7 @@ class Context(object): _align_function_definitions, ConstantFolding(), FlattenInListTransform(), + WithTransform(self), DecoratorTransform(self), AnalyseDeclarationsTransform(self), AutoTestDictTransform(self), diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 8007d83a..006133c4 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -4835,7 +4835,7 @@ class WithStatNode(StatNode): """ Represents a Python with statement. - Implemented as follows: + Implemented by the WithTransform as follows: MGR = EXPR EXIT = MGR.__exit__ @@ -4855,61 +4855,13 @@ class WithStatNode(StatNode): MGR = EXIT = VALUE = None """ # manager The with statement manager object + # target ExprNode the target lhs of the __enter__() call # body StatNode - child_attrs = ["manager", "body"] + child_attrs = ["manager", "target", "body"] has_target = False - def __init__(self, pos, manager, target, body): - StatNode.__init__(self, pos, manager = manager) - - import ExprNodes - self.target_temp = ExprNodes.TempNode(pos, type=py_object_type) - if target is not None: - self.has_target = True - body = StatListNode( - pos, stats = [ - WithTargetAssignmentStatNode( - pos, lhs = target, rhs = self.target_temp), - body - ]) - - import UtilNodes - excinfo_target = UtilNodes.ResultRefNode( - pos=pos, type=Builtin.tuple_type, may_hold_none=False) - except_clause = ExceptClauseNode( - pos, body = IfStatNode( - pos, if_clauses = [ - IfClauseNode( - pos, condition = ExprNodes.NotNode( - pos, operand = ExprNodes.WithExitCallNode( - pos, with_stat = self, - args = excinfo_target)), - body = ReraiseStatNode(pos), - ), - ], - else_clause = None), - pattern = None, - target = None, - excinfo_target = excinfo_target, - ) - - self.body = TryFinallyStatNode( - pos, body = TryExceptStatNode( - pos, body = body, - except_clauses = [except_clause], - else_clause = None, - ), - finally_clause = ExprStatNode( - pos, expr = ExprNodes.WithExitCallNode( - pos, with_stat = self, - args = ExprNodes.TupleNode( - pos, args = [ExprNodes.NoneNode(pos) for _ in range(3)] - ))), - handle_error_case = False, - ) - def analyse_declarations(self, env): self.manager.analyse_declarations(env) self.body.analyse_declarations(env) diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 8283094a..00de70a3 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -897,6 +897,61 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations): return self.visit_with_directives(node.body, directive_dict) return self.visit_Node(node) +class WithTransform(CythonTransform, SkipDeclarations): + def visit_WithStatNode(self, node): + self.visitchildren(node, 'body') + pos = node.pos + body, target, manager = node.body, node.target, node.manager + node.target_temp = ExprNodes.TempNode(pos, type=PyrexTypes.py_object_type) + if target is not None: + node.has_target = True + body = Nodes.StatListNode( + pos, stats = [ + Nodes.WithTargetAssignmentStatNode( + pos, lhs = target, rhs = node.target_temp), + body + ]) + node.target = None + + excinfo_target = ResultRefNode( + pos=pos, type=Builtin.tuple_type, may_hold_none=False) + except_clause = Nodes.ExceptClauseNode( + pos, body = Nodes.IfStatNode( + pos, if_clauses = [ + Nodes.IfClauseNode( + pos, condition = ExprNodes.NotNode( + pos, operand = ExprNodes.WithExitCallNode( + pos, with_stat = node, + args = excinfo_target)), + body = Nodes.ReraiseStatNode(pos), + ), + ], + else_clause = None), + pattern = None, + target = None, + excinfo_target = excinfo_target, + ) + + node.body = Nodes.TryFinallyStatNode( + pos, body = Nodes.TryExceptStatNode( + pos, body = body, + except_clauses = [except_clause], + else_clause = None, + ), + finally_clause = Nodes.ExprStatNode( + pos, expr = ExprNodes.WithExitCallNode( + pos, with_stat = node, + args = ExprNodes.TupleNode( + pos, args = [ExprNodes.NoneNode(pos) for _ in range(3)] + ))), + handle_error_case = False, + ) + return node + + def visit_ExprNode(self, node): + # With statements are never inside expressions. + return node + class DecoratorTransform(CythonTransform, SkipDeclarations): -- 2.26.2