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

Allow condition in GILStatNode

parent 605cc214
......@@ -7794,10 +7794,12 @@ class GILStatNode(NogilTryFinallyStatNode):
#
# state string 'gil' or 'nogil'
child_attrs = ["body", "condition", "finally_clause", "finally_except_clause"]
state_temp = None
def __init__(self, pos, state, body):
def __init__(self, pos, state, body, condition=None):
self.state = state
self.condition = condition
self.create_state_temp_if_needed(pos, state, body)
TryFinallyStatNode.__init__(
self, pos,
......
......@@ -4688,6 +4688,30 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
return None
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
# that can replace them with a constant result node
......
......@@ -2915,6 +2915,11 @@ class GilCheck(VisitorTransform):
return 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:
node.nogil_check()
......
......@@ -2055,12 +2055,20 @@ def p_with_items(s, is_async=False):
s.error("with gil/nogil cannot be async")
state = s.systring
s.next()
# support conditional gil/nogil
condition = None
if s.sy == '(':
s.next()
condition = p_test(s)
s.expect(')')
if s.sy == ',':
s.next()
body = p_with_items(s)
else:
body = p_suite(s)
return Nodes.GILStatNode(pos, state=state, body=body)
return Nodes.GILStatNode(pos, state=state, body=body, condition=condition)
else:
manager = p_test(s)
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