diff --git a/ext/B/t/optree_for.t b/ext/B/t/optree_for.t index 415a1492c862..bddb43752902 100644 --- a/ext/B/t/optree_for.t +++ b/ext/B/t/optree_for.t @@ -23,28 +23,26 @@ checkOptree ( name => 'for (@a)', 3 <#> gv[*a] s 4 <1> rv2av[t2] sKRM/1 5 <#> gv[*_] s -6 <{> enteriter(next->8 last->b redo->7) KS/DEF -9 <0> iter s -a <|> and(other->7) K/1 -7 <0> stub v -8 <0> unstack s - goto 9 -b <2> leaveloop K/2 -c <1> leavesub[1 ref] K/REFC,1 +6 <{> enteriter(next->7 last->a redo->7) KS/DEF +8 <0> iter s +9 <|> and(other->7) K/1 +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:14) v:>,<,% 2 <0> pushmark sM 3 <$> gv(*a) s 4 <1> rv2av[t1] sKRM/1 5 <$> gv(*_) s -6 <{> enteriter(next->8 last->b redo->7) KS/DEF -9 <0> iter s -a <|> and(other->7) K/1 -7 <0> stub v -8 <0> unstack s - goto 9 -b <2> leaveloop K/2 -c <1> leavesub[1 ref] K/REFC,1 +6 <{> enteriter(next->7 last->a redo->7) KS/DEF +8 <0> iter s +9 <|> and(other->7) K/1 +7 <0> unstack s + goto 8 +a <2> leaveloop K/2 +b <1> leavesub[1 ref] K/REFC,1 EONT_EONT my @lexical; @@ -58,27 +56,25 @@ checkOptree ( name => 'for (@lexical)', 2 <0> pushmark sM 3 <0> padav[@lexical:FAKE::7] sRM 4 <#> gv[*_] s -5 <{> enteriter(next->7 last->a redo->6) KS/DEF -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[2 refs] K/REFC,1 +5 <{> enteriter(next->6 last->9 redo->6) KS/DEF +7 <0> iter s +8 <|> and(other->6) K/1 +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:14) v:>,<,% 2 <0> pushmark sM 3 <0> padav[@lexical:FAKE::2] sRM 4 <$> gv(*_) s -5 <{> enteriter(next->7 last->a redo->6) KS/DEF -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[2 refs] K/REFC,1 +5 <{> enteriter(next->6 last->9 redo->6) KS/DEF +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <1> leavesub[2 refs] K/REFC,1 EONT_EONT checkOptree ( name => 'for $var (@a)', @@ -92,14 +88,13 @@ checkOptree ( name => 'for $var (@a)', 4 <1> rv2av[t3] sKRM/1 5 <#> gv[*var] s 6 <1> rv2gv sKRM/1 -7 <{> enteriter(next->9 last->c redo->8) KS -a <0> iter s -b <|> and(other->8) K/1 -8 <0> stub v -9 <0> unstack s - goto a -c <2> leaveloop KP/2 -d <1> leavesub[1 ref] K/REFC,1 +7 <{> enteriter(next->8 last->b redo->8) KS +9 <0> iter s +a <|> and(other->8) K/1 +8 <0> unstack s + goto 9 +b <2> leaveloop KP/2 +c <1> leavesub[1 ref] K/REFC,1 EOT_EOT 1 <;> nextstate(main 1453 optree_for.t:67) v:{ 2 <0> pushmark sM @@ -107,14 +102,13 @@ EOT_EOT 4 <1> rv2av[t1] sKRM/1 5 <$> gv(*var) s 6 <1> rv2gv sKRM/1 -7 <{> enteriter(next->9 last->c redo->8) KS -a <0> iter s -b <|> and(other->8) K/1 -8 <0> stub v -9 <0> unstack s - goto a -c <2> leaveloop KP/2 -d <1> leavesub[1 ref] K/REFC,1 +7 <{> enteriter(next->8 last->b redo->8) KS +9 <0> iter s +a <|> and(other->8) K/1 +8 <0> unstack s + goto 9 +b <2> leaveloop KP/2 +c <1> leavesub[1 ref] K/REFC,1 EONT_EONT checkOptree ( name => 'for my $var (@a)', @@ -126,27 +120,25 @@ checkOptree ( name => 'for my $var (@a)', 2 <0> pushmark sM 3 <#> gv[*a] s 4 <1> rv2av[t3] sKRM/1 -5 <{> enteriter(next->7 last->a redo->6)[$var:1460,1463] 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 +5 <{> enteriter(next->6 last->9 redo->6)[$var:1460,1463] KS/LVINTRO +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <1> leavesub[1 ref] K/REFC,1 EOT_EOT 1 <;> nextstate(main 424 optree_for.t:14) v:>,<,% 2 <0> pushmark sM 3 <$> gv(*a) s 4 <1> rv2av[t2] sKRM/1 -5 <{> enteriter(next->7 last->a redo->6)[$var:1460,1463] 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 +5 <{> enteriter(next->6 last->9 redo->6)[$var:1460,1463] KS/LVINTRO +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <1> leavesub[1 ref] K/REFC,1 EONT_EONT checkOptree ( name => 'for our $var (@a)', @@ -160,14 +152,13 @@ checkOptree ( name => 'for our $var (@a)', 4 <1> rv2av[t4] sKRM/1 5 <#> gv[*var] s 6 <1> rv2gv sK/FAKE,1 -7 <{> enteriter(next->9 last->c redo->8) KS/OURINTR -a <0> iter s -b <|> and(other->8) K/1 -8 <0> stub v -9 <0> unstack s - goto a -c <2> leaveloop K/2 -d <1> leavesub[1 ref] K/REFC,1 +7 <{> enteriter(next->8 last->b redo->8) KS/OURINTR +9 <0> iter s +a <|> and(other->8) K/1 +8 <0> unstack s + goto 9 +b <2> leaveloop K/2 +c <1> leavesub[1 ref] K/REFC,1 EOT_EOT 1 <;> nextstate(main 424 optree_for.t:111) v:>,<,% 2 <0> pushmark sM @@ -175,14 +166,13 @@ EOT_EOT 4 <1> rv2av[t2] sKRM/1 5 <$> gv(*var) s 6 <1> rv2gv sK/FAKE,1 -7 <{> enteriter(next->9 last->c redo->8) KS/OURINTR -a <0> iter s -b <|> and(other->8) K/1 -8 <0> stub v -9 <0> unstack s - goto a -c <2> leaveloop K/2 -d <1> leavesub[1 ref] K/REFC,1 +7 <{> enteriter(next->8 last->b redo->8) KS/OURINTR +9 <0> iter s +a <|> and(other->8) K/1 +8 <0> unstack s + goto 9 +b <2> leaveloop K/2 +c <1> leavesub[1 ref] K/REFC,1 EONT_EONT checkOptree ( name => 'for my ($var) (@a)', @@ -194,27 +184,25 @@ checkOptree ( name => 'for my ($var) (@a)', 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] KPS/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 +5 <{> enteriter(next->6 last->9 redo->6)[$var:1474,1477] KPS/LVINTRO +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <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] KPS/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 +5 <{> enteriter(next->6 last->9 redo->6)[$var:1474,1477] KPS/LVINTRO +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <1> leavesub[1 ref] K/REFC,1 EONT_EONT checkOptree ( name => 'for my ($var) (@lexical)', @@ -225,26 +213,24 @@ checkOptree ( name => 'for my ($var) (@lexical)', 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] KPS/LVINTRO -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 +4 <{> enteriter(next->5 last->8 redo->5)[$var:1481,1484] KPS/LVINTRO +6 <0> iter s +7 <|> and(other->5) K/1 +5 <0> unstack s + goto 6 +8 <2> leaveloop K/2 +9 <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] KPS/LVINTRO -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 +4 <{> enteriter(next->5 last->8 redo->5)[$var:1481,1484] KPS/LVINTRO +6 <0> iter s +7 <|> and(other->5) K/1 +5 <0> unstack s + goto 6 +8 <2> leaveloop K/2 +9 <1> leavesub[2 refs] K/REFC,1 EONT_EONT checkOptree ( name => 'for my ($key, $value) (%h)', @@ -256,27 +242,25 @@ checkOptree ( name => 'for my ($key, $value) (%h)', 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] KP/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 +5 <{> enteriter(next->6 last->9 redo->6)[$key:1488,1491; $value:1488,1491] KP/LVINTRO +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <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] KP/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 +5 <{> enteriter(next->6 last->9 redo->6)[$key:1488,1491; $value:1488,1491] KP/LVINTRO +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <1> leavesub[1 ref] K/REFC,1 EONT_EONT checkOptree ( name => 'for my ($foo, $bar, $baz) (@a)', @@ -288,25 +272,23 @@ checkOptree ( name => 'for my ($foo, $bar, $baz) (@a)', 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] KPS/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 +5 <{> enteriter(next->6 last->9 redo->6)[$foo:1495,1498; $bar:1495,1498; $baz:1495,1498] KPS/LVINTRO +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <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] KPS/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 +5 <{> enteriter(next->6 last->9 redo->6)[$foo:1495,1498; $bar:1495,1498; $baz:1495,1498] KPS/LVINTRO +7 <0> iter s +8 <|> and(other->6) K/1 +6 <0> unstack s + goto 7 +9 <2> leaveloop K/2 +a <1> leavesub[1 ref] K/REFC,1 EONT_EONT diff --git a/ext/B/t/optree_samples.t b/ext/B/t/optree_samples.t index 329a85b34d81..88e1ddf80cdd 100644 --- a/ext/B/t/optree_samples.t +++ b/ext/B/t/optree_samples.t @@ -637,20 +637,18 @@ checkOptree ( name => 'if ($a || $b) { } return 1', # 3 <|> or(other->4) sK/1 # 4 <#> gvsv[*b] s # 5 <|> and(other->6) vK/1 -# 6 <0> stub v -# 7 <;> nextstate(main 997 (eval 15):1) v -# 8 <$> const[IV 1] s -# 9 <1> leavesub[1 ref] K/REFC,1 +# 6 <;> nextstate(main 997 (eval 15):1) v +# 7 <$> const[IV 1] s +# 8 <1> leavesub[1 ref] K/REFC,1 EOT_EOT # 1 <;> nextstate(main 997 (eval 15):1) v # 2 <$> gvsv(*a) s # 3 <|> or(other->4) sK/1 # 4 <$> gvsv(*b) s # 5 <|> and(other->6) vK/1 -# 6 <0> stub v -# 7 <;> nextstate(main 3 (eval 3):1) v -# 8 <$> const(IV 1) s -# 9 <1> leavesub[1 ref] K/REFC,1 +# 6 <;> nextstate(main 3 (eval 3):1) v +# 7 <$> const(IV 1) s +# 8 <1> leavesub[1 ref] K/REFC,1 EONT_EONT pass("rpeep - unless ($a && $b)"); @@ -664,20 +662,18 @@ checkOptree ( name => 'unless ($a && $b) { } return 1', # 3 <|> and(other->4) sK/1 # 4 <#> gvsv[*b] s # 5 <|> or(other->6) vK/1 -# 6 <0> stub v -# 7 <;> nextstate(main 997 (eval 15):1) v -# 8 <$> const[IV 1] s -# 9 <1> leavesub[1 ref] K/REFC,1 +# 6 <;> nextstate(main 997 (eval 15):1) v +# 7 <$> const[IV 1] s +# 8 <1> leavesub[1 ref] K/REFC,1 EOT_EOT # 1 <;> nextstate(main 997 (eval 15):1) v # 2 <$> gvsv(*a) s # 3 <|> and(other->4) sK/1 # 4 <$> gvsv(*b) s # 5 <|> or(other->6) vK/1 -# 6 <0> stub v -# 7 <;> nextstate(main 3 (eval 3):1) v -# 8 <$> const(IV 1) s -# 9 <1> leavesub[1 ref] K/REFC,1 +# 6 <;> nextstate(main 3 (eval 3):1) v +# 7 <$> const(IV 1) s +# 8 <1> leavesub[1 ref] K/REFC,1 EONT_EONT pass("rpeep - my $a; my @b; my %c; print 'f'"); diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 6b52d6757be3..4b3b04a4edcf 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -7,7 +7,7 @@ # This is based on the module of the same name by Malcolm Beattie, # but essentially none of his code remains. -package B::Deparse 1.87; +package B::Deparse 1.88; use strict; use Carp; use B qw(class main_root main_start main_cv svref_2object opnumber perlstring @@ -274,7 +274,7 @@ BEGIN { # - indent() removes semicolons wherever it sees \cK. -BEGIN { for (qw[ const stringify rv2sv list glob pushmark null aelem +BEGIN { for (qw[ const stringify rv2sv list glob pushmark null stub aelem kvaslice kvhslice padsv argcheck nextstate dbstate rv2av rv2hv helem pushdefer leavetrycatch custom ]) { @@ -920,7 +920,8 @@ sub compile { my $kid; if ( $root->name eq 'leave' and ($kid = $root->first)->name eq 'enter' - and !null($kid = $kid->sibling) and $kid->name eq 'stub' + and !null($kid = $kid->sibling) and ($kid->name eq 'stub' + or $kid->name eq 'null' and $kid->targ == OP_STUB) and !null($kid = $kid->sibling) and $kid->name eq 'null' and class($kid) eq 'COP' and null $kid->sibling ) { @@ -1815,7 +1816,6 @@ sub lineseq { if defined($self->{'limit_seq'}) && (!defined($limit_seq) || $self->{'limit_seq'} < $limit_seq); local $self->{'limit_seq'} = $limit_seq; - $self->walk_lineseq($root, \@ops, sub { push @exprs, $_[0]} ); @@ -1832,6 +1832,7 @@ sub scopeop { my($real_block, $self, $op, $cx) = @_; my $kid; my @kids; + my $leadingstub = ''; local(@$self{qw'curstash warnings hints hinthash'}) = @$self{qw'curstash warnings hints hinthash'} if $real_block; @@ -1862,6 +1863,10 @@ sub scopeop { } } else { $kid = $op->first; + if ($kid->name eq "null" && $kid->targ == OP_STUB) { + $leadingstub = "();"; + $kid = $kid->sibling; + } } for (; !null($kid); $kid = $kid->sibling) { push @kids, $kid; @@ -1874,7 +1879,10 @@ sub scopeop { . " {\n\t$body\n\b}"; } else { my $lineseq = $self->lineseq($op, $cx, @kids); - return (length ($lineseq) ? "$lineseq;" : ""); + return (length ($lineseq) ? "$lineseq;" + : $leadingstub + ? $leadingstub + : ""); } } @@ -4423,6 +4431,8 @@ sub pp_null { if ($op->targ == OP_LIST) { my $my_attr = maybe_var_attr($self, $op, $cx); return $my_attr if defined $my_attr; + } elsif ($op->targ == OP_STUB) { + return "()"; } if (class($op) eq "OP") { diff --git a/op.c b/op.c index 8a85229e5116..6967b5b2e33b 100644 --- a/op.c +++ b/op.c @@ -2490,6 +2490,9 @@ Perl_scalarvoid(pTHX_ OP *arg) "anonymous hash ({})" : "anonymous array ([])"; break; + case OP_STUB: + op_null(o); + break; } if (useless_sv) {