summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2021-04-26 11:05:21 +0000
committerRicardo Signes <rjbs@semiotic.systems>2021-10-15 09:28:27 -0400
commitc386ecc10be9e73917fa6b819321f0cc47cacdb6 (patch)
tree54dada91b4c36226358f747c42876727fd2aa6f3
parent83c7d349662bf85048f317a6b23155733307f486 (diff)
downloadperl-c386ecc10be9e73917fa6b819321f0cc47cacdb6.tar.gz
B::Concise now handles n-at-a-time for.
-rw-r--r--ext/B/B/Concise.pm9
-rw-r--r--ext/B/t/optree_for.t128
2 files changed, 134 insertions, 3 deletions
diff --git a/ext/B/B/Concise.pm b/ext/B/B/Concise.pm
index 0bb68a6c4b..a7419d75e0 100644
--- a/ext/B/B/Concise.pm
+++ b/ext/B/B/Concise.pm
@@ -14,7 +14,7 @@ use warnings; # uses #3 and #4, since warnings uses Carp
use Exporter 'import'; # use #5
-our $VERSION = "1.005";
+our $VERSION = "1.006";
our @EXPORT_OK = qw( set_style set_style_standard add_callback
concise_subref concise_cv concise_main
add_style walk_output compile reset_sequence );
@@ -852,9 +852,14 @@ sub concise_op {
# targ holds a reference count
my $refs = "ref" . ($h{targ} != 1 ? "s" : "");
$h{targarglife} = $h{targarg} = "$h{targ} $refs";
- } elsif ($h{targ}) {
+ } elsif ($h{targ} && $h{name} ne 'iter') {
+ # for my ($q, $r, $s) () {} syntax hijacks the targ of the iter op,
+ # (which is the ->next of the enteriter) hence the special cases above
+ # and just below:
my $count = $h{name} eq 'padrange'
? ($op->private & $B::Op_private::defines{'OPpPADRANGE_COUNTMASK'})
+ : $h{name} eq 'enteriter'
+ ? $op->next->targ + 1
: 1;
my (@targarg, @targarglife);
for my $i (0..$count-1) {
diff --git a/ext/B/t/optree_for.t b/ext/B/t/optree_for.t
index 7eea5f801a..a72324cfaf 100644
--- a/ext/B/t/optree_for.t
+++ b/ext/B/t/optree_for.t
@@ -9,7 +9,7 @@ BEGIN {
}
}
use OptreeCheck;
-plan tests => 11;
+plan tests => 19;
pass("FOR LOOPS");
@@ -184,3 +184,129 @@ b <|> and(other->8) K/1
c <2> leaveloop K/2
d <1> leavesub[1 ref] K/REFC,1
EONT_EONT
+
+checkOptree ( name => 'for my ($var) (@a)',
+ code => sub {for my ($var) (@a) {}},
+ bcopts => '-exec',
+ strip_open_hints => 1,
+ expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
+1 <;> nextstate(main 1466 optree_for.t:100) v
+2 <0> pushmark sM
+3 <#> gv[*a] s
+4 <1> rv2av[t3] sKRM/1
+5 <{> enteriter(next->7 last->a redo->6)[$var:1474,1477] KS
+8 <0> iter s
+9 <|> and(other->6) K/1
+6 <0> stub v
+7 <0> unstack s
+ goto 8
+a <2> leaveloop K/2
+b <1> leavesub[1 ref] K/REFC,1
+EOT_EOT
+1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%
+2 <0> pushmark sM
+3 <$> gv(*a) s
+4 <1> rv2av[t2] sKRM/1
+5 <{> enteriter(next->7 last->a redo->6)[$var:1474,1477] KS
+8 <0> iter s
+9 <|> and(other->6) K/1
+6 <0> stub v
+7 <0> unstack s
+ goto 8
+a <2> leaveloop K/2
+b <1> leavesub[1 ref] K/REFC,1
+EONT_EONT
+
+checkOptree ( name => 'for my ($var) (@lexical)',
+ code => sub {for my ($var) (@lexical) {}},
+ bcopts => '-exec',
+ strip_open_hints => 1,
+ expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
+1 <;> nextstate(main 1466 optree_for.t:100) v
+2 <0> pushmark sM
+3 <0> padav[@lexical:FAKE::7] sRM
+4 <{> enteriter(next->6 last->9 redo->5)[$var:1481,1484] KS
+7 <0> iter s
+8 <|> and(other->5) K/1
+5 <0> stub v
+6 <0> unstack s
+ goto 7
+9 <2> leaveloop K/2
+a <1> leavesub[2 refs] K/REFC,1
+EOT_EOT
+1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%
+2 <0> pushmark sM
+3 <0> padav[@lexical:FAKE::2] sRM
+4 <{> enteriter(next->6 last->9 redo->5)[$var:1481,1484] KS
+7 <0> iter s
+8 <|> and(other->5) K/1
+5 <0> stub v
+6 <0> unstack s
+ goto 7
+9 <2> leaveloop K/2
+a <1> leavesub[2 refs] K/REFC,1
+EONT_EONT
+
+checkOptree ( name => 'for my ($key, $value) (%h)',
+ code => sub {for my ($key, $value) (%h) {}},
+ bcopts => '-exec',
+ strip_open_hints => 1,
+ expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
+1 <;> nextstate(main 1466 optree_for.t:100) v
+2 <0> pushmark sM
+3 <#> gv[*h] s
+4 <1> rv2hv[t4] lKM
+5 <{> enteriter(next->7 last->a redo->6)[$key:1488,1491; $value:1488,1491] K/LVINTRO
+8 <0> iter s
+9 <|> and(other->6) K/1
+6 <0> stub v
+7 <0> unstack s
+ goto 8
+a <2> leaveloop K/2
+b <1> leavesub[1 ref] K/REFC,1
+EOT_EOT
+1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%
+2 <0> pushmark sM
+3 <$> gv(*h) s
+4 <1> rv2hv[t3] lKM
+5 <{> enteriter(next->7 last->a redo->6)[$key:1488,1491; $value:1488,1491] K/LVINTRO
+8 <0> iter s
+9 <|> and(other->6) K/1
+6 <0> stub v
+7 <0> unstack s
+ goto 8
+a <2> leaveloop K/2
+b <1> leavesub[1 ref] K/REFC,1
+EONT_EONT
+
+checkOptree ( name => 'for my ($foo, $bar, $baz) (@a)',
+ code => sub {for my ($foo, $bar, $baz) (@a) {}},
+ bcopts => '-exec',
+ strip_open_hints => 1,
+ expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
+1 <;> nextstate(main 1466 optree_for.t:100) v
+2 <0> pushmark sM
+3 <#> gv[*a] s
+4 <1> rv2av[t5] sKRM/1
+5 <{> enteriter(next->7 last->a redo->6)[$foo:1495,1498; $bar:1495,1498; $baz:1495,1498] KS/LVINTRO
+8 <0> iter s
+9 <|> and(other->6) K/1
+6 <0> stub v
+7 <0> unstack s
+ goto 8
+a <2> leaveloop K/2
+b <1> leavesub[1 ref] K/REFC,1
+EOT_EOT
+1 <;> nextstate(main 424 optree_for.t:111) v:>,<,%
+2 <0> pushmark sM
+3 <$> gv(*a) s
+4 <1> rv2av[t4] sKRM/1
+5 <{> enteriter(next->7 last->a redo->6)[$foo:1495,1498; $bar:1495,1498; $baz:1495,1498] KS/LVINTRO
+8 <0> iter s
+9 <|> and(other->6) K/1
+6 <0> stub v
+7 <0> unstack s
+ goto 8
+a <2> leaveloop K/2
+b <1> leavesub[1 ref] K/REFC,1
+EONT_EONT