1#!perl 2 3BEGIN { 4 unshift @INC, 't'; 5 require Config; 6 if (($Config::Config{'extensions'} !~ /\bB\b/) ){ 7 print "1..0 # Skip -- Perl configured without B module\n"; 8 exit 0; 9 } 10} 11use OptreeCheck; 12use Config; 13plan tests => 18; 14 15SKIP: { 16skip "no perlio in this build", 4 unless $Config::Config{useperlio}; 17 18# The regression this was testing is that the first aelemfast, derived 19# from a lexical array, is supposed to be a BASEOP "<0>", while the 20# second, from a global, is an SVOP "<$>" or a PADOP "<#>" depending 21# on threading. In buggy versions, both showed up as SVOPs/PADOPs. See 22# B.xs:cc_opclass() for the relevant code. 23 24# All this is much simpler, now that aelemfast_lex has been broken out from 25# aelemfast 26checkOptree ( name => 'OP_AELEMFAST opclass', 27 code => sub { my @x; our @y; $x[127] + $y[-128]}, 28 strip_open_hints => 1, 29 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 30# 7 <1> leavesub[1 ref] K/REFC,1 ->(end) 31# - <@> lineseq KP ->7 32# 1 <;> nextstate(main 634 optree_misc.t:25) v:>,<,% ->2 33# 2 <0> padav[@x:634,636] vM/LVINTRO ->3 34# - <;> ex-nextstate(main 1594 optree_misc.t:27) v:>,<,% ->3 35# - <1> rv2av[t4] vK/OURINTR,1 ->3 36# - <#> gv[*y] s ->- 37# 3 <;> nextstate(main 636 optree_misc.t:25) v:>,<,%,{ ->4 38# 6 <2> add[t6] sK/2 ->7 39# - <1> ex-aelem sK/2 ->5 40# 4 <0> aelemfast_lex[@x:634,636] sR/key=127 ->5 41# - <0> ex-const s ->- 42# - <1> ex-aelem sK/2 ->6 43# - <1> ex-rv2av sKR/1 ->- 44# 5 <#> aelemfast[*y] s/key=128 ->6 45# - <0> ex-const s/FOLD ->- 46EOT_EOT 47# 7 <1> leavesub[1 ref] K/REFC,1 ->(end) 48# - <@> lineseq KP ->7 49# 1 <;> nextstate(main 634 optree_misc.t:27) v:>,<,% ->2 50# 2 <0> padav[@x:634,636] vM/LVINTRO ->3 51# - <;> ex-nextstate(main 1594 optree_misc.t:27) v:>,<,% ->3 52# - <1> rv2av[t3] vK/OURINTR,1 ->3 53# - <$> gv(*y) s ->- 54# 3 <;> nextstate(main 636 optree_misc.t:27) v:>,<,%,{ ->4 55# 6 <2> add[t4] sK/2 ->7 56# - <1> ex-aelem sK/2 ->5 57# 4 <0> aelemfast_lex[@x:634,636] sR/key=127 ->5 58# - <0> ex-const s ->- 59# - <1> ex-aelem sK/2 ->6 60# - <1> ex-rv2av sKR/1 ->- 61# 5 <$> aelemfast(*y) s/key=128 ->6 62# - <0> ex-const s/FOLD ->- 63EONT_EONT 64 65checkOptree ( name => 'PMOP children', 66 code => sub { $foo =~ s/(a)/$1/ }, 67 strip_open_hints => 1, 68 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 69# 5 <1> leavesub[1 ref] K/REFC,1 ->(end) 70# - <@> lineseq KP ->5 71# 1 <;> nextstate(main 1 -e:1) v:>,<,%,{ ->2 72# 4 </> subst(/"(a)"/) sKS ->5 73# - <1> ex-rv2sv sKRM/1 ->3 74# 2 <#> gvsv[*foo] s ->3 75# - <1> ex-rv2sv sK/1 ->4 76# 3 <#> gvsv[*1] s ->4 77EOT_EOT 78# 5 <1> leavesub[1 ref] K/REFC,1 ->(end) 79# - <@> lineseq KP ->5 80# 1 <;> nextstate(main 1 -e:1) v:>,<,%,{ ->2 81# 4 </> subst(/"(a)"/) sKS ->5 82# - <1> ex-rv2sv sKRM/1 ->3 83# 2 <$> gvsv(*foo) s ->3 84# - <1> ex-rv2sv sK/1 ->4 85# 3 <$> gvsv(*1) s ->4 86EONT_EONT 87 88} #skip 89 90my $t = <<'EOT_EOT'; 91# 8 <@> leave[1 ref] vKP/REFC ->(end) 92# 1 <0> enter ->2 93# 2 <;> nextstate(main 1 -e:1) v:>,<,%,{ ->3 94# 7 <2> sassign vKS/2 ->8 95# 5 <@> index[t2] sK/2 ->6 96# - <0> ex-pushmark s ->3 97# 3 <$> const[PV "foo"] s ->4 98# 4 <$> const[PVMG "foo"] s ->5 99# - <1> ex-rv2sv sKRM*/1 ->7 100# 6 <#> gvsv[*_] s ->7 101EOT_EOT 102my $nt = <<'EONT_EONT'; 103# 8 <@> leave[1 ref] vKP/REFC ->(end) 104# 1 <0> enter ->2 105# 2 <;> nextstate(main 1 -e:1) v:>,<,%,{ ->3 106# 7 <2> sassign vKS/2 ->8 107# 5 <@> index[t1] sK/2 ->6 108# - <0> ex-pushmark s ->3 109# 3 <$> const(PV "foo") s ->4 110# 4 <$> const(PVMG "foo") s ->5 111# - <1> ex-rv2sv sKRM*/1 ->7 112# 6 <$> gvsv(*_) s ->7 113EONT_EONT 114 115checkOptree ( name => 'index and PVBM', 116 prog => '$_ = index q(foo), q(foo)', 117 strip_open_hints => 1, 118 expect => $t, expect_nt => $nt); 119 120my $tmpfile = tempfile(); 121open my $fh, '>', $tmpfile or die "Cannot open $tmpfile: $!"; 122print $fh "no warnings;format =\n@<<<\n\$a\n@>>>\n\@b\n."; 123close $fh; 124 125checkOptree ( name => 'formats', 126 bcopts => 'STDOUT', 127 progfile => $tmpfile, 128 strip_open_hints => 1, 129 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 130# main::STDOUT (FORMAT): 131# c <1> leavewrite[1 ref] K/REFC,1 ->(end) 132# - <@> lineseq KP ->c 133# 1 <;> nextstate(main 1 -:4) v:>,<,% ->2 134# 5 <@> formline vK/2 ->6 135# 2 <0> pushmark s ->3 136# 3 <$> const[PV "@<<<\n"] s ->4 137# - <@> lineseq lK ->5 138# - <;> ex-nextstate(main 3 tmp35894B:3) v:>,<,% ->4 139# - <1> ex-rv2sv sK/1 ->- 140# 4 <#> gvsv[*a] s ->5 141# 6 <;> nextstate(main 1 -:6) v:>,<,% ->7 142# b <@> formline sK/2 ->c 143# 7 <0> pushmark s ->8 144# 8 <$> const[PV "@>>>\n"] s ->9 145# - <@> lineseq lK ->b 146# - <;> ex-nextstate(main 3 tmp35894B:5) v:>,<,% ->9 147# a <1> rv2av[t3] lK/1 ->b 148# 9 <#> gv[*b] s ->a 149EOT_EOT 150# main::STDOUT (FORMAT): 151# c <1> leavewrite[1 ref] K/REFC,1 ->(end) 152# - <@> lineseq KP ->c 153# 1 <;> nextstate(main 1 -:4) v:>,<,% ->2 154# 5 <@> formline vK/2 ->6 155# 2 <0> pushmark s ->3 156# 3 <$> const(PV "@<<<\n") s ->4 157# - <@> lineseq lK ->5 158# - <;> ex-nextstate(main 3 tmp35894B:3) v:>,<,% ->4 159# - <1> ex-rv2sv sK/1 ->- 160# 4 <$> gvsv(*a) s ->5 161# 6 <;> nextstate(main 1 -:6) v:>,<,% ->7 162# b <@> formline sK/2 ->c 163# 7 <0> pushmark s ->8 164# 8 <$> const(PV "@>>>\n") s ->9 165# - <@> lineseq lK ->b 166# - <;> ex-nextstate(main 3 tmp35894B:5) v:>,<,% ->9 167# a <1> rv2av[t3] lK/1 ->b 168# 9 <$> gv(*b) s ->a 169EONT_EONT 170 171checkOptree ( name => 'padrange', 172 code => sub { my ($x,$y); @a = ($x,$y); ($x,$y) = @a }, 173 strip_open_hints => 1, 174 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 175# f <1> leavesub[1 ref] K/REFC,1 ->(end) 176# - <@> lineseq KP ->f 177# 1 <;> nextstate(main 1 -e:1) v:>,<,% ->2 178# - <@> list vKP ->3 179# 2 <0> padrange[$x:1,2; $y:1,2] vM/LVINTRO,range=2 ->3 180# - <0> padsv[$x:1,2] vM/LVINTRO ->- 181# - <0> padsv[$y:1,2] vM/LVINTRO ->- 182# 3 <;> nextstate(main 2 -e:1) v:>,<,% ->4 183# 8 <2> aassign[t4] vKS/COM_AGG ->9 184# - <1> ex-list lKP ->5 185# 4 <0> padrange[$x:1,2; $y:1,2] /range=2 ->5 186# - <0> padsv[$x:1,2] s ->- 187# - <0> padsv[$y:1,2] s ->- 188# - <1> ex-list lK ->8 189# 5 <0> pushmark s ->6 190# 7 <1> rv2av[t3] lKRM*/1 ->8 191# 6 <#> gv[*a] s ->7 192# 9 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->a 193# e <2> aassign[t6] KS/COM_RC1 ->f 194# - <1> ex-list lK ->d 195# a <0> pushmark s ->b 196# c <1> rv2av[t5] lK/1 ->d 197# b <#> gv[*a] s ->c 198# - <1> ex-list lKPRM* ->e 199# d <0> padrange[$x:1,2; $y:1,2] RM/range=2 ->e 200# - <0> padsv[$x:1,2] sRM* ->- 201# - <0> padsv[$y:1,2] sRM* ->- 202EOT_EOT 203# f <1> leavesub[1 ref] K/REFC,1 ->(end) 204# - <@> lineseq KP ->f 205# 1 <;> nextstate(main 1 -e:1) v:>,<,% ->2 206# - <@> list vKP ->3 207# 2 <0> padrange[$x:1,2; $y:1,2] vM/LVINTRO,range=2 ->3 208# - <0> padsv[$x:1,2] vM/LVINTRO ->- 209# - <0> padsv[$y:1,2] vM/LVINTRO ->- 210# 3 <;> nextstate(main 2 -e:1) v:>,<,% ->4 211# 8 <2> aassign[t4] vKS/COM_AGG ->9 212# - <1> ex-list lKP ->5 213# 4 <0> padrange[$x:1,2; $y:1,2] /range=2 ->5 214# - <0> padsv[$x:1,2] s ->- 215# - <0> padsv[$y:1,2] s ->- 216# - <1> ex-list lK ->8 217# 5 <0> pushmark s ->6 218# 7 <1> rv2av[t3] lKRM*/1 ->8 219# 6 <$> gv(*a) s ->7 220# 9 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->a 221# e <2> aassign[t6] KS/COM_RC1 ->f 222# - <1> ex-list lK ->d 223# a <0> pushmark s ->b 224# c <1> rv2av[t5] lK/1 ->d 225# b <$> gv(*a) s ->c 226# - <1> ex-list lKPRM* ->e 227# d <0> padrange[$x:1,2; $y:1,2] RM/range=2 ->e 228# - <0> padsv[$x:1,2] sRM* ->- 229# - <0> padsv[$y:1,2] sRM* ->- 230EONT_EONT 231 232checkOptree ( name => 'padrange and @_', 233 code => sub { my ($a,$b) = @_; 234 my ($c,$d) = @X::_; 235 package Y; 236 my ($e,$f) = @_; 237 }, 238 strip_open_hints => 1, 239 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 240# d <1> leavesub[1 ref] K/REFC,1 ->(end) 241# - <@> lineseq KP ->d 242# 1 <;> nextstate(main 1 p3:1) v:>,<,% ->2 243# 3 <2> aassign[t5] vKS ->4 244# - <1> ex-list lK ->- 245# 2 <0> padrange[$a:1,4; $b:1,4] */LVINTRO,range=2 ->3 246# - <1> rv2av[t4] lK/1 ->- 247# - <#> gv[*_] s ->- 248# - <1> ex-list lKPRM* ->3 249# - <0> pushmark sRM*/LVINTRO ->- 250# - <0> padsv[$a:1,4] sRM*/LVINTRO ->- 251# - <0> padsv[$b:1,4] sRM*/LVINTRO ->- 252# 4 <;> nextstate(main 2 p3:2) v:>,<,% ->5 253# 9 <2> aassign[t10] vKS/COM_RC1 ->a 254# - <1> ex-list lK ->8 255# 5 <0> pushmark s ->6 256# 7 <1> rv2av[t9] lK/1 ->8 257# 6 <#> gv[*X::_] s ->7 258# - <1> ex-list lKPRM* ->9 259# 8 <0> padrange[$c:2,4; $d:2,4] RM/LVINTRO,range=2 ->9 260# - <0> padsv[$c:2,4] sRM*/LVINTRO ->- 261# - <0> padsv[$d:2,4] sRM*/LVINTRO ->- 262# a <;> nextstate(Y 3 p3:4) v:>,<,%,{ ->b 263# c <2> aassign[t15] KS ->d 264# - <1> ex-list lK ->- 265# b <0> padrange[$e:3,4; $f:3,4] */LVINTRO,range=2 ->c 266# - <1> rv2av[t14] lK/1 ->- 267# - <#> gv[*_] s ->- 268# - <1> ex-list lKPRM* ->c 269# - <0> pushmark sRM*/LVINTRO ->- 270# - <0> padsv[$e:3,4] sRM*/LVINTRO ->- 271# - <0> padsv[$f:3,4] sRM*/LVINTRO ->- 272EOT_EOT 273# d <1> leavesub[1 ref] K/REFC,1 ->(end) 274# - <@> lineseq KP ->d 275# 1 <;> nextstate(main 1 p3:1) v:>,<,% ->2 276# 3 <2> aassign[t5] vKS ->4 277# - <1> ex-list lK ->- 278# 2 <0> padrange[$a:1,4; $b:1,4] */LVINTRO,range=2 ->3 279# - <1> rv2av[t4] lK/1 ->- 280# - <$> gv(*_) s ->- 281# - <1> ex-list lKPRM* ->3 282# - <0> pushmark sRM*/LVINTRO ->- 283# - <0> padsv[$a:1,4] sRM*/LVINTRO ->- 284# - <0> padsv[$b:1,4] sRM*/LVINTRO ->- 285# 4 <;> nextstate(main 2 p3:2) v:>,<,% ->5 286# 9 <2> aassign[t10] vKS/COM_RC1 ->a 287# - <1> ex-list lK ->8 288# 5 <0> pushmark s ->6 289# 7 <1> rv2av[t9] lK/1 ->8 290# 6 <$> gv(*X::_) s ->7 291# - <1> ex-list lKPRM* ->9 292# 8 <0> padrange[$c:2,4; $d:2,4] RM/LVINTRO,range=2 ->9 293# - <0> padsv[$c:2,4] sRM*/LVINTRO ->- 294# - <0> padsv[$d:2,4] sRM*/LVINTRO ->- 295# a <;> nextstate(Y 3 p3:4) v:>,<,%,{ ->b 296# c <2> aassign[t15] KS ->d 297# - <1> ex-list lK ->- 298# b <0> padrange[$e:3,4; $f:3,4] */LVINTRO,range=2 ->c 299# - <1> rv2av[t14] lK/1 ->- 300# - <$> gv(*_) s ->- 301# - <1> ex-list lKPRM* ->c 302# - <0> pushmark sRM*/LVINTRO ->- 303# - <0> padsv[$e:3,4] sRM*/LVINTRO ->- 304# - <0> padsv[$f:3,4] sRM*/LVINTRO ->- 305EONT_EONT 306 307checkOptree ( name => 'consolidate padranges', 308 code => sub { my ($a,$b); my ($c,$d); 1 }, 309 strip_open_hints => 1, 310 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 311# 5 <1> leavesub[1 ref] K/REFC,1 ->(end) 312# - <@> lineseq KP ->5 313# 1 <;> nextstate(main 900 optree_misc.t:334) v:>,<,% ->2 314# - <@> list vKP ->- 315# 2 <0> padrange[$a:900,902; $b:900,902; $c:901,902; $d:901,902] vM/LVINTRO,range=4 ->3 316# - <0> padsv[$a:900,902] vM/LVINTRO ->- 317# - <0> padsv[$b:900,902] vM/LVINTRO ->- 318# - <;> nextstate(main 901 optree_misc.t:334) v:>,<,% ->- 319# - <@> list vKP ->3 320# - <0> pushmark vM/LVINTRO ->- 321# - <0> padsv[$c:901,902] vM/LVINTRO ->- 322# - <0> padsv[$d:901,902] vM/LVINTRO ->- 323# 3 <;> nextstate(main 902 optree_misc.t:334) v:>,<,%,{ ->4 324# 4 <$> const[IV 1] s ->5 325EOT_EOT 326# 5 <1> leavesub[1 ref] K/REFC,1 ->(end) 327# - <@> lineseq KP ->5 328# 1 <;> nextstate(main 900 optree_misc.t:334) v:>,<,% ->2 329# - <@> list vKP ->- 330# 2 <0> padrange[$a:900,902; $b:900,902; $c:901,902; $d:901,902] vM/LVINTRO,range=4 ->3 331# - <0> padsv[$a:900,902] vM/LVINTRO ->- 332# - <0> padsv[$b:900,902] vM/LVINTRO ->- 333# - <;> nextstate(main 901 optree_misc.t:334) v:>,<,% ->- 334# - <@> list vKP ->3 335# - <0> pushmark vM/LVINTRO ->- 336# - <0> padsv[$c:901,902] vM/LVINTRO ->- 337# - <0> padsv[$d:901,902] vM/LVINTRO ->- 338# 3 <;> nextstate(main 902 optree_misc.t:334) v:>,<,%,{ ->4 339# 4 <$> const(IV 1) s ->5 340EONT_EONT 341 342 343checkOptree ( name => 'consolidate padranges and singletons', 344 code => sub { my ($a,$b); my $c; my ($d,$e); 345 my @f; my $g; my ($h,$i); my %j; 1 }, 346 strip_open_hints => 1, 347 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 348# 5 <1> leavesub[1 ref] K/REFC,1 ->(end) 349# - <@> lineseq KP ->5 350# 1 <;> nextstate(main 903 optree_misc.t:371) v:>,<,% ->2 351# - <@> list vKP ->- 352# 2 <0> padrange[$a:903,910; $b:903,910; $c:904,910; $d:905,910; $e:905,910; @f:906,910; $g:907,910; $h:908,910; $i:908,910; %j:909,910] vM/LVINTRO,range=10 ->3 353# - <0> padsv[$a:903,910] vM/LVINTRO ->- 354# - <0> padsv[$b:903,910] vM/LVINTRO ->- 355# - <;> nextstate(main 904 optree_misc.t:371) v:>,<,% ->- 356# - <0> padsv[$c:904,910] vM/LVINTRO ->- 357# - <;> nextstate(main 905 optree_misc.t:371) v:>,<,%,{ ->- 358# - <@> list vKP ->- 359# - <0> pushmark vM/LVINTRO ->- 360# - <0> padsv[$d:905,910] vM/LVINTRO ->- 361# - <0> padsv[$e:905,910] vM/LVINTRO ->- 362# - <;> nextstate(main 906 optree_misc.t:372) v:>,<,%,{ ->- 363# - <0> padav[@f:906,910] vM/LVINTRO ->- 364# - <;> nextstate(main 907 optree_misc.t:372) v:>,<,%,{ ->- 365# - <0> padsv[$g:907,910] vM/LVINTRO ->- 366# - <;> nextstate(main 908 optree_misc.t:372) v:>,<,%,{ ->- 367# - <@> list vKP ->- 368# - <0> pushmark vM/LVINTRO ->- 369# - <0> padsv[$h:908,910] vM/LVINTRO ->- 370# - <0> padsv[$i:908,910] vM/LVINTRO ->- 371# - <;> nextstate(main 909 optree_misc.t:372) v:>,<,%,{ ->- 372# - <0> padhv[%j:909,910] vM/LVINTRO ->3 373# 3 <;> nextstate(main 910 optree_misc.t:372) v:>,<,%,{ ->4 374# 4 <$> const[IV 1] s ->5 375EOT_EOT 376# 5 <1> leavesub[1 ref] K/REFC,1 ->(end) 377# - <@> lineseq KP ->5 378# 1 <;> nextstate(main 903 optree_misc.t:371) v:>,<,% ->2 379# - <@> list vKP ->- 380# 2 <0> padrange[$a:903,910; $b:903,910; $c:904,910; $d:905,910; $e:905,910; @f:906,910; $g:907,910; $h:908,910; $i:908,910; %j:909,910] vM/LVINTRO,range=10 ->3 381# - <0> padsv[$a:903,910] vM/LVINTRO ->- 382# - <0> padsv[$b:903,910] vM/LVINTRO ->- 383# - <;> nextstate(main 904 optree_misc.t:371) v:>,<,% ->- 384# - <0> padsv[$c:904,910] vM/LVINTRO ->- 385# - <;> nextstate(main 905 optree_misc.t:371) v:>,<,%,{ ->- 386# - <@> list vKP ->- 387# - <0> pushmark vM/LVINTRO ->- 388# - <0> padsv[$d:905,910] vM/LVINTRO ->- 389# - <0> padsv[$e:905,910] vM/LVINTRO ->- 390# - <;> nextstate(main 906 optree_misc.t:372) v:>,<,%,{ ->- 391# - <0> padav[@f:906,910] vM/LVINTRO ->- 392# - <;> nextstate(main 907 optree_misc.t:372) v:>,<,%,{ ->- 393# - <0> padsv[$g:907,910] vM/LVINTRO ->- 394# - <;> nextstate(main 908 optree_misc.t:372) v:>,<,%,{ ->- 395# - <@> list vKP ->- 396# - <0> pushmark vM/LVINTRO ->- 397# - <0> padsv[$h:908,910] vM/LVINTRO ->- 398# - <0> padsv[$i:908,910] vM/LVINTRO ->- 399# - <;> nextstate(main 909 optree_misc.t:372) v:>,<,%,{ ->- 400# - <0> padhv[%j:909,910] vM/LVINTRO ->3 401# 3 <;> nextstate(main 910 optree_misc.t:372) v:>,<,%,{ ->4 402# 4 <$> const(IV 1) s ->5 403EONT_EONT 404 405 406checkOptree ( name => 'm?x?', 407 code => sub { m?x?; }, 408 strip_open_hints => 1, 409 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); 410# 3 <1> leavesub[1 ref] K/REFC,1 ->(end) 411# - <@> lineseq KP ->3 412# 1 <;> nextstate(main 914 optree_misc.t:434) v:>,<,%,{ ->2 413# 2 </> match(/"x"/) ->3 414EOT_EOT 415# 3 <1> leavesub[1 ref] K/REFC,1 ->(end) 416# - <@> lineseq KP ->3 417# 1 <;> nextstate(main 914 optree_misc.t:434) v:>,<,%,{ ->2 418# 2 </> match(/"x"/) ->3 419EONT_EONT 420 421 422unlink $tmpfile; 423