1.1 --- a/common.py Mon May 27 11:58:58 2019 +0200
1.2 +++ b/common.py Sun Jun 02 23:13:27 2019 +0200
1.3 @@ -563,6 +563,8 @@
1.4 self.next_temporary()
1.5 t2 = self.get_temporary_name()
1.6 self.next_temporary()
1.7 + t3 = self.get_temporary_name()
1.8 + self.next_temporary()
1.9
1.10 node = compiler.ast.Stmt([
1.11
1.12 @@ -583,9 +585,10 @@
1.13 # try:
1.14 # while True:
1.15 # try:
1.16 - # <var>... = <t2>()
1.17 + # <t3> = <t2>()
1.18 # except StopIteration:
1.19 # raise LoopExit
1.20 + # <var>... = <t3>
1.21 # {n.body}
1.22 # except LoopExit:
1.23 # {n.else_}
1.24 @@ -601,13 +604,16 @@
1.25 compiler.ast.Stmt([
1.26 compiler.ast.TryExcept(
1.27 compiler.ast.Assign(
1.28 - [n.assign],
1.29 + [compiler.ast.AssName(t3, "OP_ASSIGN")],
1.30 compiler.ast.CallFunc(
1.31 compiler.ast.Name(t2),
1.32 [])),
1.33 [(compiler.ast.Name("StopIteration"), None,
1.34 compiler.ast.Raise(compiler.ast.Name("LoopExit")))],
1.35 None),
1.36 + compiler.ast.Assign(
1.37 + [n.assign],
1.38 + compiler.ast.Name(t3)),
1.39 n.body]),
1.40 None),
1.41 [(compiler.ast.Name("LoopExit"), None, n.else_ or compiler.ast.Pass())],
2.1 --- a/internal_tests/branches.py Mon May 27 11:58:58 2019 +0200
2.2 +++ b/internal_tests/branches.py Sun Jun 02 23:13:27 2019 +0200
2.3 @@ -687,4 +687,77 @@
2.4 bt.get_assignment_positions_for_branches("a", ar)
2.5 names.append(bt.assignments["a"])
2.6
2.7 +# This demonstrates why the assignment in a "for" loop construct must appear
2.8 +# outside the inner "try" body: null usage escapes the loop via the exception
2.9 +# handler and the raise statement, even though the assignment would only be
2.10 +# valid otherwise.
2.11 +
2.12 +# Equivalent to...
2.13 +#
2.14 +# try:
2.15 +# while ...:
2.16 +# try:
2.17 +# a = ...
2.18 +# except:
2.19 +# raise ...
2.20 +# a.p
2.21 +# except:
2.22 +# pass
2.23 +
2.24 +bt = branching.BranchTracker()
2.25 +bt.new_branchpoint() # begin (try)
2.26 +bt.new_branchpoint(True) # begin (while)
2.27 +bt.new_branch(True) # while ...
2.28 +bt.new_branchpoint() # begin (try)
2.29 +a = bt.assign_names(["a"])
2.30 +bt.resume_abandoned_branches() # except
2.31 +bt.abandon_branch() # raise
2.32 +bt.shelve_branch()
2.33 +bt.new_branch() # (null)
2.34 +bt.shelve_branch()
2.35 +bt.merge_branches() # end (try)
2.36 +ap = bt.use_attribute("a", "p")
2.37 +bt.resume_continuing_branches()
2.38 +bt.shelve_branch(True)
2.39 +bt.new_branch() # (null)
2.40 +bt.shelve_branch()
2.41 +bt.merge_branches() # end (while)
2.42 +bt.resume_broken_branches()
2.43 +bt.resume_abandoned_branches() # except
2.44 +bt.shelve_branch()
2.45 +bt.new_branch() # (null)
2.46 +bt.shelve_branch()
2.47 +bt.merge_branches() # end (try)
2.48 +
2.49 +print simple_usage(a) == \
2.50 + {'a' : set([('p',), ()])}, simple_usage(a)
2.51 +print bt.get_assignment_positions_for_branches("a", ap) == [0], \
2.52 + bt.get_assignment_positions_for_branches("a", ap)
2.53 +names.append(bt.assignments["a"])
2.54 +
2.55 +# Equivalent to...
2.56 +#
2.57 +# b = ...
2.58 +# while ...:
2.59 +# a = ...
2.60 +# a.p
2.61 +
2.62 +bt = branching.BranchTracker()
2.63 +bt.new_branchpoint(True) # begin
2.64 +b = bt.assign_names(["b"])
2.65 +bt.new_branch(True) # while ...
2.66 +a = bt.assign_names(["a"])
2.67 +ap = bt.use_attribute("a", "p")
2.68 +bt.resume_continuing_branches()
2.69 +bt.shelve_branch(True)
2.70 +bt.new_branch() # (null)
2.71 +bt.shelve_branch()
2.72 +bt.merge_branches() # end
2.73 +
2.74 +print simple_usage(a) == \
2.75 + {'a' : set([('p',)])}, simple_usage(a)
2.76 +print bt.get_assignment_positions_for_branches("a", ap) == [0], \
2.77 + bt.get_assignment_positions_for_branches("a", ap)
2.78 +names.append(bt.assignments["a"])
2.79 +
2.80 # vim: tabstop=4 expandtab shiftwidth=4