6 if (($Config::Config{'extensions'} !~ /\bB\b/) ){
7 print "1..0 # Skip -- Perl configured without B module\n";
10 if (!$Config::Config{useperlio}) {
11 print "1..0 # Skip -- need perlio to walk the optree\n";
16 use OptreeCheck; # ALSO DOES @ARGV HANDLING !!!!!!
21 #################################
23 use constant { # see also t/op/gv.t line 358
37 sub myno () { return 1!=1 }
38 sub pi () { 3.14159 };
40 my $RV_class = $] >= 5.011 ? 'IV' : 'RV';
42 my $want = { # expected types, how value renders in-line, todos (maybe)
43 mystr => [ 'PV', '"'.mystr.'"' ],
44 myhref => [ $RV_class, '\\\\HASH'],
46 myglob => [ $RV_class, '\\\\' ],
47 mysub => [ $RV_class, '\\\\' ],
48 myunsub => [ $RV_class, '\\\\' ],
49 # these are not inlined, at least not per BC::Concise
50 #myyes => [ $RV_class, ],
51 #myno => [ $RV_class, ],
52 myaref => [ $RV_class, '\\\\' ],
53 myfl => [ 'NV', myfl ],
54 myint => [ 'IV', myint ],
56 myrex => [ $RV_class, '\\\\"\\(?^:Foo\\)"' ],
58 myrex => [ $RV_class, '\\\\' ],
60 myundef => [ 'NULL', ],
64 => qw ( Sunday Monday Tuesday Wednesday Thursday Friday Saturday );
67 $::{napier} = \2.71828; # counter-example (doesn't get optimized).
68 eval "sub napier ();";
71 # should be able to undefine constant::import here ???
73 # eval 'sub constant::import () {}';
74 # undef *constant::import::{CODE};
77 #################################
78 pass("RENDER CONSTANT SUBS RETURNING SCALARS");
80 for $func (sort keys %$want) {
81 # no strict 'refs'; # why not needed ?
82 checkOptree ( name => "$func() as a coderef",
85 expect => <<EOT_EOT, expect_nt => <<EONT_EONT);
86 is a constant sub, optimized to a $want->{$func}[0]
88 is a constant sub, optimized to a $want->{$func}[0]
93 pass("RENDER CALLS TO THOSE CONSTANT SUBS");
95 for $func (sort keys %$want) {
96 # print "# doing $func\n";
97 checkOptree ( name => "call $func",
99 ($want->{$func}[2]) ? ( todo => $want->{$func}[2]) : (),
100 bc_opts => '-nobanner',
101 expect => <<EOT_EOT, expect_nt => <<EONT_EONT);
102 3 <1> leavesub[2 refs] K/REFC,1 ->(end)
103 - <\@> lineseq KP ->3
104 1 <;> dbstate(main 833 (eval 44):1) v ->2
105 2 <\$> const[$want->{$func}[0] $want->{$func}[1]] s* ->3 < 5.017002
106 2 <\$> const[$want->{$func}[0] $want->{$func}[1]] s*/FOLD ->3 >=5.017002
108 3 <1> leavesub[2 refs] K/REFC,1 ->(end)
109 - <\@> lineseq KP ->3
110 1 <;> dbstate(main 833 (eval 44):1) v ->2
111 2 <\$> const($want->{$func}[0] $want->{$func}[1]) s* ->3 < 5.017002
112 2 <\$> const($want->{$func}[0] $want->{$func}[1]) s*/FOLD ->3 >=5.017002
120 checkOptree ( name => 'myyes() as coderef',
121 code => sub () { 1==1 },
123 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
124 is a constant sub, optimized to a SPECIAL
126 is a constant sub, optimized to a SPECIAL
130 checkOptree ( name => 'myyes() as coderef',
131 prog => 'sub a() { 1==1 }; print a',
133 strip_open_hints => 1,
134 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
135 # 6 <@> leave[1 ref] vKP/REFC ->(end)
137 # 2 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->3
139 # 3 <0> pushmark s ->4
140 # 4 <$> const[SPECIAL sv_yes] s* ->5 < 5.017002
141 # 4 <$> const[SPECIAL sv_yes] s*/FOLD ->5 >=5.017002
143 # 6 <@> leave[1 ref] vKP/REFC ->(end)
145 # 2 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->3
147 # 3 <0> pushmark s ->4
148 # 4 <$> const(SPECIAL sv_yes) s* ->5 < 5.017002
149 # 4 <$> const(SPECIAL sv_yes) s*/FOLD ->5 >=5.017002
153 # Need to do this as a prog, not code, as only the first constant to use
154 # PL_sv_no actually gets to use the real thing - every one following is
156 checkOptree ( name => 'myno() as coderef',
157 prog => 'sub a() { 1!=1 }; print a',
159 strip_open_hints => 1,
160 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
161 # 6 <@> leave[1 ref] vKP/REFC ->(end)
163 # 2 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->3
165 # 3 <0> pushmark s ->4
166 # 4 <$> const[SPECIAL sv_no] s* ->5 < 5.017002
167 # 4 <$> const[SPECIAL sv_no] s*/FOLD ->5 >=5.017002
169 # 6 <@> leave[1 ref] vKP/REFC ->(end)
171 # 2 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->3
173 # 3 <0> pushmark s ->4
174 # 4 <$> const(SPECIAL sv_no) s* ->5 < 5.017002
175 # 4 <$> const(SPECIAL sv_no) s*/FOLD ->5 >=5.017002
179 my ($expect, $expect_nt) =
181 ? (" is a constant sub, optimized to a AV\n") x 2
182 : (<<'EOT_EOT', <<'EONT_EONT');
183 # 3 <1> leavesub[2 refs] K/REFC,1 ->(end)
184 # - <@> lineseq K ->3
185 # 1 <;> nextstate(constant 61 constant.pm:118) v:*,&,x*,x&,x$ ->2
186 # 2 <0> padav[@list:FAKE:m:96] ->3
188 # 3 <1> leavesub[2 refs] K/REFC,1 ->(end)
189 # - <@> lineseq K ->3
190 # 1 <;> nextstate(constant 61 constant.pm:118) v:*,&,x*,x&,x$ ->2
191 # 2 <0> padav[@list:FAKE:m:71] ->3
195 checkOptree ( name => 'constant sub returning list',
198 expect => $expect, expect_nt => $expect_nt);
202 printf "myint %d mystr %s myfl %f pi %f\n"
203 , myint, mystr, myfl, pi;
206 my ($expect, $expect_nt) = (<<'EOT_EOT', <<'EONT_EONT');
207 # 9 <1> leavesub[1 ref] K/REFC,1 ->(end)
208 # - <@> lineseq KP ->9
209 # 1 <;> nextstate(main 635 optree_constants.t:163) v:>,<,% ->2
211 # 2 <0> pushmark sM ->3
212 # 3 <$> const[PV "myint %d mystr %s myfl %f pi %f\n"] sM/FOLD ->4
213 # 4 <$> const[IV 42] sM* ->5 < 5.017002
214 # 5 <$> const[PV "hithere"] sM* ->6 < 5.017002
215 # 6 <$> const[NV 1.414213] sM* ->7 < 5.017002
216 # 7 <$> const[NV 3.14159] sM* ->8 < 5.017002
217 # 4 <$> const[IV 42] sM*/FOLD ->5 >=5.017002
218 # 5 <$> const[PV "hithere"] sM*/FOLD ->6 >=5.017002
219 # 6 <$> const[NV 1.414213] sM*/FOLD ->7 >=5.017002
220 # 7 <$> const[NV 3.14159] sM*/FOLD ->8 >=5.017002
222 # 9 <1> leavesub[1 ref] K/REFC,1 ->(end)
223 # - <@> lineseq KP ->9
224 # 1 <;> nextstate(main 635 optree_constants.t:163) v:>,<,% ->2
226 # 2 <0> pushmark sM ->3
227 # 3 <$> const(PV "myint %d mystr %s myfl %f pi %f\n") sM/FOLD ->4
228 # 4 <$> const(IV 42) sM* ->5 < 5.017002
229 # 5 <$> const(PV "hithere") sM* ->6 < 5.017002
230 # 6 <$> const(NV 1.414213) sM* ->7 < 5.017002
231 # 7 <$> const(NV 3.14159) sM* ->8 < 5.017002
232 # 4 <$> const(IV 42) sM*/FOLD ->5 >=5.017002
233 # 5 <$> const(PV "hithere") sM*/FOLD ->6 >=5.017002
234 # 6 <$> const(NV 1.414213) sM*/FOLD ->7 >=5.017002
235 # 7 <$> const(NV 3.14159) sM*/FOLD ->8 >=5.017002
239 s/M(?=\*? ->)//g for $expect, $expect_nt;
241 if($] < 5.017002 || $] >= 5.019004) {
242 s|\\n"[])] sM\K/FOLD|| for $expect, $expect_nt;
245 checkOptree ( name => 'call many in a print statement',
247 strip_open_hints => 1,
248 expect => $expect, expect_nt => $expect_nt);
250 # test constant expression folding
252 checkOptree ( name => 'arithmetic constant folding in print',
253 code => 'print 1+2+3',
254 strip_open_hints => 1,
255 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
256 # 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
257 # - <@> lineseq KP ->5
258 # 1 <;> nextstate(main 937 (eval 53):1) v ->2
260 # 2 <0> pushmark s ->3
261 # 3 <$> const[IV 6] s ->4 < 5.017002
262 # 3 <$> const[IV 6] s/FOLD ->4 >=5.017002
264 # 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
265 # - <@> lineseq KP ->5
266 # 1 <;> nextstate(main 937 (eval 53):1) v ->2
268 # 2 <0> pushmark s ->3
269 # 3 <$> const(IV 6) s ->4 < 5.017002
270 # 3 <$> const(IV 6) s/FOLD ->4 >=5.017002
273 checkOptree ( name => 'string constant folding in print',
274 code => 'print "foo"."bar"',
275 strip_open_hints => 1,
276 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
277 # 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
278 # - <@> lineseq KP ->5
279 # 1 <;> nextstate(main 942 (eval 55):1) v ->2
281 # 2 <0> pushmark s ->3
282 # 3 <$> const[PV "foobar"] s ->4 < 5.017002
283 # 3 <$> const[PV "foobar"] s/FOLD ->4 >=5.017002
285 # 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
286 # - <@> lineseq KP ->5
287 # 1 <;> nextstate(main 942 (eval 55):1) v ->2
289 # 2 <0> pushmark s ->3
290 # 3 <$> const(PV "foobar") s ->4 < 5.017002
291 # 3 <$> const(PV "foobar") s/FOLD ->4 >=5.017002
294 checkOptree ( name => 'boolean or folding',
295 code => 'print "foobar" if 1 or 0',
296 strip_open_hints => 1,
297 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
298 # 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
299 # - <@> lineseq KP ->5
300 # 1 <;> nextstate(main 942 (eval 55):1) v ->2
301 # 4 <@> print sK ->5 < 5.019004
302 # 4 <@> print sK/FOLD ->5 >=5.019004
303 # 2 <0> pushmark s ->3
304 # 3 <$> const[PV "foobar"] s ->4
306 # 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
307 # - <@> lineseq KP ->5
308 # 1 <;> nextstate(main 942 (eval 55):1) v ->2
309 # 4 <@> print sK ->5 < 5.019004
310 # 4 <@> print sK/FOLD ->5 >=5.019004
311 # 2 <0> pushmark s ->3
312 # 3 <$> const(PV "foobar") s ->4
315 checkOptree ( name => 'lc*,uc*,gt,lt,ge,le,cmp',
317 $s = uc('foo.').ucfirst('bar.').lc('LOW.').lcfirst('LOW');
318 print "a-lt-b" if "a" lt "b";
319 print "b-gt-a" if "b" gt "a";
320 print "a-le-b" if "a" le "b";
321 print "b-ge-a" if "b" ge "a";
322 print "b-cmp-a" if "b" cmp "a";
323 print "a-gt-b" if "a" gt "b"; # should be suppressed
325 strip_open_hints => 1,
326 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
327 # r <1> leavesub[1 ref] K/REFC,1 ->(end)
328 # - <@> lineseq KP ->r
329 # 1 <;> nextstate(main 916 optree_constants.t:307) v:>,<,%,{ ->2
330 # 4 <2> sassign vKS/2 ->5
331 # 2 <$> const[PV "FOO.Bar.low.lOW"] s ->3 < 5.017002
332 # 2 <$> const[PV "FOO.Bar.low.lOW"] s/FOLD ->3 >=5.017002
333 # - <1> ex-rv2sv sKRM*/1 ->4
334 # 3 <#> gvsv[*s] s ->4
335 # 5 <;> nextstate(main 916 optree_constants.t:308) v:>,<,%,{ ->6
336 # 8 <@> print vK ->9 < 5.019004
337 # 8 <@> print vK/FOLD ->9 >=5.019004
338 # 6 <0> pushmark s ->7
339 # 7 <$> const[PV "a-lt-b"] s ->8
340 # 9 <;> nextstate(main 916 optree_constants.t:309) v:>,<,%,{ ->a
341 # c <@> print vK ->d < 5.019004
342 # c <@> print vK/FOLD ->d >=5.019004
343 # a <0> pushmark s ->b
344 # b <$> const[PV "b-gt-a"] s ->c
345 # d <;> nextstate(main 916 optree_constants.t:310) v:>,<,%,{ ->e
346 # g <@> print vK ->h < 5.019004
347 # g <@> print vK/FOLD ->h >=5.019004
348 # e <0> pushmark s ->f
349 # f <$> const[PV "a-le-b"] s ->g
350 # h <;> nextstate(main 916 optree_constants.t:311) v:>,<,%,{ ->i
351 # k <@> print vK ->l < 5.019004
352 # k <@> print vK/FOLD ->l >=5.019004
353 # i <0> pushmark s ->j
354 # j <$> const[PV "b-ge-a"] s ->k
355 # l <;> nextstate(main 916 optree_constants.t:312) v:>,<,%,{ ->m
356 # o <@> print vK ->p < 5.019004
357 # o <@> print vK/FOLD ->p >=5.019004
358 # m <0> pushmark s ->n
359 # n <$> const[PV "b-cmp-a"] s ->o
360 # p <;> nextstate(main 916 optree_constants.t:313) v:>,<,%,{ ->q
361 # q <$> const[PVNV 0] s/SHORT ->r < 5.017002
362 # q <$> const[PVNV 0] s/FOLD,SHORT ->r >=5.017002 < 5.019003
363 # q <$> const[SPECIAL sv_no] s/SHORT,FOLD ->r >=5.019003
365 # r <1> leavesub[1 ref] K/REFC,1 ->(end)
366 # - <@> lineseq KP ->r
367 # 1 <;> nextstate(main 916 optree_constants.t:307) v:>,<,%,{ ->2
368 # 4 <2> sassign vKS/2 ->5
369 # 2 <$> const(PV "FOO.Bar.low.lOW") s ->3 < 5.017002
370 # 2 <$> const(PV "FOO.Bar.low.lOW") s/FOLD ->3 >=5.017002
371 # - <1> ex-rv2sv sKRM*/1 ->4
372 # 3 <$> gvsv(*s) s ->4
373 # 5 <;> nextstate(main 916 optree_constants.t:308) v:>,<,%,{ ->6
374 # 8 <@> print vK ->9 < 5.019004
375 # 8 <@> print vK/FOLD ->9 >=5.019004
376 # 6 <0> pushmark s ->7
377 # 7 <$> const(PV "a-lt-b") s ->8
378 # 9 <;> nextstate(main 916 optree_constants.t:309) v:>,<,%,{ ->a
379 # c <@> print vK ->d < 5.019004
380 # c <@> print vK/FOLD ->d >=5.019004
381 # a <0> pushmark s ->b
382 # b <$> const(PV "b-gt-a") s ->c
383 # d <;> nextstate(main 916 optree_constants.t:310) v:>,<,%,{ ->e
384 # g <@> print vK ->h < 5.019004
385 # g <@> print vK/FOLD ->h >=5.019004
386 # e <0> pushmark s ->f
387 # f <$> const(PV "a-le-b") s ->g
388 # h <;> nextstate(main 916 optree_constants.t:311) v:>,<,%,{ ->i
389 # k <@> print vK ->l < 5.019004
390 # k <@> print vK/FOLD ->l >=5.019004
391 # i <0> pushmark s ->j
392 # j <$> const(PV "b-ge-a") s ->k
393 # l <;> nextstate(main 916 optree_constants.t:312) v:>,<,%,{ ->m
394 # o <@> print vK ->p < 5.019004
395 # o <@> print vK/FOLD ->p >=5.019004
396 # m <0> pushmark s ->n
397 # n <$> const(PV "b-cmp-a") s ->o
398 # p <;> nextstate(main 916 optree_constants.t:313) v:>,<,%,{ ->q
399 # q <$> const(SPECIAL sv_no) s/SHORT ->r < 5.017002
400 # q <$> const(SPECIAL sv_no) s/SHORT,FOLD ->r >=5.017002
403 checkOptree ( name => 'mixed constant folding, with explicit braces',
404 code => 'print "foo"."bar".(2+3)',
405 strip_open_hints => 1,
406 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
407 # 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
408 # - <@> lineseq KP ->5
409 # 1 <;> nextstate(main 977 (eval 28):1) v ->2
411 # 2 <0> pushmark s ->3
412 # 3 <$> const[PV "foobar5"] s ->4 < 5.017002
413 # 3 <$> const[PV "foobar5"] s/FOLD ->4 >=5.017002
415 # 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
416 # - <@> lineseq KP ->5
417 # 1 <;> nextstate(main 977 (eval 28):1) v ->2
419 # 2 <0> pushmark s ->3
420 # 3 <$> const(PV "foobar5") s ->4 < 5.017002
421 # 3 <$> const(PV "foobar5") s/FOLD ->4 >=5.017002
428 Optimized constant subs are stored as bare scalars in the stash
429 (package hash), which formerly held only GVs (typeglobs).
431 But you cant create them manually - you cant assign a scalar to a
432 stash element, and expect it to work like a constant-sub, even if you
435 This is a feature; alternative is too much action-at-a-distance. The
436 following test demonstrates - napier is not seen as a function at all,
437 much less an optimized one.
441 checkOptree ( name => 'not evertnapier',
444 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');