diff --git a/S04-statements/label.t b/S04-statements/label.t index 0368746b67..d6843bb89c 100644 --- a/S04-statements/label.t +++ b/S04-statements/label.t @@ -89,41 +89,119 @@ throws-like { EVAL q[label1: say "OH HAI"; label1: say "OH NOES"] }, X::Redeclar # NB(bartolin) As of 2020-04-13 Rakudo has different classes for different loop # types. The tests resemble Rakudo's current internal structure, # but the code should work for all implementations. +# Please note that each type of loop comes in two versions: not +# within parens and within parens. Accordings to the old design +# documents the second version should be lazy: +# https://github.com/Raku/old-design-docs/blob/a4c36c683d/S04-control.pod#loops-at-the-statementlist-level-vs-the-statement-level +# The tests explicitly don't test this aspect. They are about the +# crash described in the mentioned bug report. { + my $ignore; my @res; - @ = (L1: while True { while True { @res.push: "WhileLoop"; last L1 } }); - @ = (L2: until False { until False { @res.push: "WhileLoop"; last L2 } }); - @ = (L3: Seq.from-loop( - { loop { @res.push: "WhileLoop"; last L3 } }, - { True }, - :label(L3) - )); - is-deeply @res, ["WhileLoop", "WhileLoop", "WhileLoop"], - 'nested loop with labeled last (1)'; + sub while-loop() { + L: while True { while True { @res.push: 1; last L } } + } + sub while-loop-in-parens() { + (L: while True { while True { @res.push: 3; last L } }) + } + sub until-loop() { + L: until False { until False { @res.push: 5; last L } } + } + sub until-loop-in-parens() { + (L: until False { until False { @res.push: 7; last L } }) + } + # Make sure that loops are run (in case they are lazy). + $ignore = while-loop()[2]; + $ignore = while-loop-in-parens()[2]; + $ignore = until-loop()[2]; + $ignore = until-loop-in-parens()[2]; + is-deeply @res, [1, 3, 5, 7], 'no crash: nested loops and labeled last (1)'; @res = []; - @ = (L4: Seq.from-loop( - { loop { @res.push: "RepeatLoop"; last L4 } }, - { True }, - :label(L4), - :repeat(1) - )); - is-deeply @res, ["RepeatLoop"], 'nested loop with labeled last (2)'; + sub seq-from-loop-while() { + L: Seq.from-loop( + { loop { @res.push: 9; last L } }, + { True }, + :label(L) + ) + } + sub seq-from-loop-while-in-parens() { + (L: Seq.from-loop( + { loop { @res.push: 11; last L } }, + { True }, + :label(L) + )) + } + sub seq-from-loop-repeat() { + L: Seq.from-loop( + { loop { @res.push: 13; last L } }, + { True }, + :label(L), + :repeat(1) + ) + } + sub seq-from-loop-repeat-in-parens() { + (L: Seq.from-loop( + { loop { @res.push: 15; last L } }, + { True }, + :label(L), + :repeat(1) + )) + } + # Make sure that loops are run (in case they are lazy). + $ignore = seq-from-loop-while()[0]; + $ignore = seq-from-loop-while-in-parens()[0]; + $ignore = seq-from-loop-repeat()[0]; + $ignore = seq-from-loop-repeat-in-parens()[0]; + is-deeply @res, [9, 11, 13, 15], 'no crash: nested loops and labeled last (2)'; @res = []; - @ = (L5: loop { loop { @res.push: "CStyleLoop"; last L5 } }); - @ = (L6: Seq.from-loop( - { loop { @res.push: "CStyleLoop"; last L6 } }, - { True }, - { my $foo = 47 }, - :label(L6) - )); - is-deeply @res, ["CStyleLoop", "CStyleLoop"], - 'nested loop with labeled last (3)'; + sub c-style-loop() { + L: loop { loop { @res.push: 0; last L } } + } + sub c-style-loop-in-parens() { + (L: loop { loop { @res.push: 2; last L } }) + } + sub seq-from-loop-c-style() { + L: Seq.from-loop( + { loop { @res.push: 4; last L } }, + { True }, + { my $foo = 47 }, + :label(L) + ) + } + sub seq-from-loop-c-style-in-parens() { + (L: Seq.from-loop( + { loop { @res.push: 6; last L } }, + { True }, + { my $foo = 47 }, + :label(L) + )) + } + # Make sure that loops are run (in case they are lazy). + $ignore = c-style-loop()[0]; + $ignore = c-style-loop-in-parens()[0]; + $ignore = seq-from-loop-c-style()[0]; + $ignore = seq-from-loop-c-style-in-parens()[0]; + is-deeply @res, [0, 2, 4, 6], 'no crash: nested loops and labeled last (3)'; @res = []; - L7: Seq.from-loop( { loop { @res.push: "Loop"; last L7 } }, :label(L7)); - is-deeply @res, ["Loop"], 'nested loop with labeled last (4)'; + sub seq-from-loop-plain() { + L: Seq.from-loop( + { loop { @res.push: 8; last L } }, + :label(L) + ) + } + sub seq-from-loop-plain-in-parens() { + (L: Seq.from-loop( + { loop { @res.push: 10; last L } }, + :label(L) + )) + } + # Make sure that loops are run (in case they are lazy). + $ignore = seq-from-loop-plain()[0]; + $ignore = seq-from-loop-plain-in-parens()[0]; + is-deeply @res, [8, 10], 'no crash: nested loops and labeled last (4)'; } # https://github.com/rakudo/rakudo/issues/4456