def _handle_loop(node, state, ctx, visit_after, visiting_after, walk_field, **_):
if not visiting_after:
# Need to traverse fields explicitly since for the purposes of _replace_returns(),
# the body of `orelse` field is not inside a loop.
state = state.update(loop_nesting_ctr=state.loop_nesting_ctr + 1)
state, new_body = walk_field(state, node.body, block_context=True)
state = state.update(loop_nesting_ctr=state.loop_nesting_ctr - 1)
state, new_orelse = walk_field(state, node.orelse, block_context=True)
visit_after()
return state, replace_fields(node, body=new_body, orelse=new_orelse)
else:
# If there was a return inside a loop, append a conditional break
# to propagate the return otside all nested loops
if state.return_inside_a_loop:
new_nodes = [
node,
ast.If(
test=ast.Name(id=ctx.return_flag_var),
body=[ast.Break()],
orelse=[])]
else:
new_nodes = node
# if we are at root level, reset the return-inside-a-loop flag
if state.loop_nesting_ctr == 0:
state = state.update(return_inside_a_loop=False)
return state, new_nodes
评论列表
文章目录