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