-my @arg_lists = ([ ], [ 'A' ], [ qw<B C> ]);
-
-for my $height (0 .. 1) {
- for my $level (0 .. 1) {
- my $i;
- my $tests = gen $height, $level;
- for (@$tests) {
- my ($code, $exp_spec) = @$_;
- ++$i;
- my $desc = "stress unwind $height $level $i";
- my $cb = do {
- no warnings 'void';
- eval "sub { $code }";
- };
- if ($@) {
- fail "$desc : test did not compile" for 1 .. @arg_lists;
- } else {
- for (@arg_lists) {
- @args = @$_;
- my $res = linearize $cb->();
- my $exp = expect $exp_spec;
- if ($res ne $exp) {
- diag <<DIAG;
+my @targets = (
+ [ sub {
+ my $depth = pop;
+ unshift @stack, HERE;
+ unwind(@_ => $stack[$depth]);
+ }, 'target context from HERE' ],
+ [ sub {
+ my $depth = pop;
+ unwind(@_ => SCOPE($depth == 0 ? 0 : (2 * ($depth - 1) + 1)));
+ }, 'target context from SCOPE' ],
+);
+
+my $seed = 0;
+
+for my $args ([ ], [ 'A' ], [ qw<B C> ]) {
+ my @args = @$args;
+ for my $frame0 (@test_frames) {
+ for my $frame1 (@test_frames) {
+ for my $frame2 (@test_frames) {
+ my $max_depth = 3;
+ $seed += 5; # Coprime with $max_depth
+ my @prepend;
+ for (1 .. $max_depth) {
+ ++$seed;
+ my $i = $seed + $_;
+ my $l = $seed % $max_depth - 1;
+ push @prepend, [ $i .. ($i + $l) ];
+ }
+ my $prepend_str = join ' ', map { '[' . join(' ', @$_) . ']' } @prepend;
+ for my $depth (0 .. $max_depth) {
+ my $exp = do {
+ my @cxts = map $_->[2], $frame0, $frame1, $frame2;
+ my @exp = @args;
+ for (my $i = $depth + 1; $i <= $max_depth; ++$i) {
+ my $c = $cxts[$max_depth - $i];
+ if ($c eq 'v') {
+ @exp = ();
+ } elsif ($c eq 's') {
+ @exp = @exp ? $exp[-1] : undef;
+ } else {
+ unshift @exp, @{$prepend[$max_depth - $i]};
+ }
+ }
+ linearize @exp;
+ };
+ for my $target (@targets) {
+ local @stack;
+ local @pre = @prepend;
+ my @res = $frame0->[0]->($frame1, $frame2, $target, @args, $depth);
+ my $got = linearize @res;
+ if ($got ne $exp) {
+ diag <<DIAG;