Commit 00d29b76 authored by Stefan Behnel's avatar Stefan Behnel

move 'with' statement implementation back into WithTransform to fix 'with'...

move 'with' statement implementation back into WithTransform to fix 'with' statement usage for compiler directives
parent 402cc4b9
...@@ -102,7 +102,7 @@ class Context(object): ...@@ -102,7 +102,7 @@ class Context(object):
def create_pipeline(self, pxd, py=False): def create_pipeline(self, pxd, py=False):
from Visitor import PrintTree 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 AnalyseDeclarationsTransform, AnalyseExpressionsTransform
from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
from ParseTreeTransforms import InterpretCompilerDirectives, TransformBuiltinMethods from ParseTreeTransforms import InterpretCompilerDirectives, TransformBuiltinMethods
...@@ -139,6 +139,7 @@ class Context(object): ...@@ -139,6 +139,7 @@ class Context(object):
_align_function_definitions, _align_function_definitions,
ConstantFolding(), ConstantFolding(),
FlattenInListTransform(), FlattenInListTransform(),
WithTransform(self),
DecoratorTransform(self), DecoratorTransform(self),
AnalyseDeclarationsTransform(self), AnalyseDeclarationsTransform(self),
AutoTestDictTransform(self), AutoTestDictTransform(self),
......
...@@ -4835,7 +4835,7 @@ class WithStatNode(StatNode): ...@@ -4835,7 +4835,7 @@ class WithStatNode(StatNode):
""" """
Represents a Python with statement. Represents a Python with statement.
Implemented as follows: Implemented by the WithTransform as follows:
MGR = EXPR MGR = EXPR
EXIT = MGR.__exit__ EXIT = MGR.__exit__
...@@ -4855,61 +4855,13 @@ class WithStatNode(StatNode): ...@@ -4855,61 +4855,13 @@ class WithStatNode(StatNode):
MGR = EXIT = VALUE = None MGR = EXIT = VALUE = None
""" """
# manager The with statement manager object # manager The with statement manager object
# target ExprNode the target lhs of the __enter__() call
# body StatNode # body StatNode
child_attrs = ["manager", "body"] child_attrs = ["manager", "target", "body"]
has_target = False 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): def analyse_declarations(self, env):
self.manager.analyse_declarations(env) self.manager.analyse_declarations(env)
self.body.analyse_declarations(env) self.body.analyse_declarations(env)
......
...@@ -897,6 +897,61 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations): ...@@ -897,6 +897,61 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
return self.visit_with_directives(node.body, directive_dict) return self.visit_with_directives(node.body, directive_dict)
return self.visit_Node(node) 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): class DecoratorTransform(CythonTransform, SkipDeclarations):
......
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