Commit 5ff75cda authored by Noam Hershtig's avatar Noam Hershtig

Allow condition in GILStatNode

parent 605cc214
...@@ -7794,10 +7794,12 @@ class GILStatNode(NogilTryFinallyStatNode): ...@@ -7794,10 +7794,12 @@ class GILStatNode(NogilTryFinallyStatNode):
# #
# state string 'gil' or 'nogil' # state string 'gil' or 'nogil'
child_attrs = ["body", "condition", "finally_clause", "finally_except_clause"]
state_temp = None state_temp = None
def __init__(self, pos, state, body): def __init__(self, pos, state, body, condition=None):
self.state = state self.state = state
self.condition = condition
self.create_state_temp_if_needed(pos, state, body) self.create_state_temp_if_needed(pos, state, body)
TryFinallyStatNode.__init__( TryFinallyStatNode.__init__(
self, pos, self, pos,
......
...@@ -4688,6 +4688,30 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -4688,6 +4688,30 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
return None return None
return node return node
def visit_GILStatNode(self, node):
self.visitchildren(node)
if node.condition is None:
return node
if node.condition.has_constant_result():
# Condition is True - Modify node to be a normal
# GILStatNode with condition=None
if node.condition.constant_result:
node.condition = None
# Condition is False - the body of the GILStatNode
# should run without changing changing the state of the gil
# return the body of the GILStatNode
else:
return node.body
# If condition is not constant we keep the GILStatNode as it is.
# Either it will later become constant (e.g. a `numeric is int`
# expression in a fused typed function) and then when ConstantFolding
# runs again it will be handled or a later transform (i.e. GilCheck)
# will raise an error
return node
# in the future, other nodes can have their own handler method here # in the future, other nodes can have their own handler method here
# that can replace them with a constant result node # that can replace them with a constant result node
......
...@@ -2915,6 +2915,11 @@ class GilCheck(VisitorTransform): ...@@ -2915,6 +2915,11 @@ class GilCheck(VisitorTransform):
return node return node
def visit_GILStatNode(self, node): def visit_GILStatNode(self, node):
if node.condition is not None:
error(node.pos, "Non-constant condition in a "
"`with %s(<condition>)` statement" % node.state)
return node
if self.nogil and node.nogil_check: if self.nogil and node.nogil_check:
node.nogil_check() node.nogil_check()
......
...@@ -2055,12 +2055,20 @@ def p_with_items(s, is_async=False): ...@@ -2055,12 +2055,20 @@ def p_with_items(s, is_async=False):
s.error("with gil/nogil cannot be async") s.error("with gil/nogil cannot be async")
state = s.systring state = s.systring
s.next() s.next()
# support conditional gil/nogil
condition = None
if s.sy == '(':
s.next()
condition = p_test(s)
s.expect(')')
if s.sy == ',': if s.sy == ',':
s.next() s.next()
body = p_with_items(s) body = p_with_items(s)
else: else:
body = p_suite(s) body = p_suite(s)
return Nodes.GILStatNode(pos, state=state, body=body) return Nodes.GILStatNode(pos, state=state, body=body, condition=condition)
else: else:
manager = p_test(s) manager = p_test(s)
target = None target = None
......
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