This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #103492] Give lvalue cx to (s)printf args
[perl5.git] / ext / B / t / optree_constants.t
CommitLineData
d51cf0c9
JC
1#!perl
2
3BEGIN {
74517a3a 4 unshift @INC, 't';
d51cf0c9
JC
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 }
27e11f68
NC
10 if (!$Config::Config{useperlio}) {
11 print "1..0 # Skip -- need perlio to walk the optree\n";
12 exit 0;
13 }
d51cf0c9
JC
14}
15
16use OptreeCheck; # ALSO DOES @ARGV HANDLING !!!!!!
17use Config;
18
183eb698 19plan tests => 67;
d51cf0c9
JC
20
21#################################
22
23use constant { # see also t/op/gv.t line 282
f9f861ec
JC
24 myaref => [ 1,2,3 ],
25 myfl => 1.414213,
26 myglob => \*STDIN,
27 myhref => { a => 1 },
28 myint => 42,
29 myrex => qr/foo/,
30 mystr => 'hithere',
31 mysub => \&ok,
32 myundef => undef,
33 myunsub => \&nosuch,
34};
35
36sub myyes() { 1==1 }
37sub myno () { return 1!=1 }
38sub pi () { 3.14159 };
39
4df7f6af
NC
40my $RV_class = $] >= 5.011 ? 'IV' : 'RV';
41
f9f861ec 42my $want = { # expected types, how value renders in-line, todos (maybe)
f9f861ec 43 mystr => [ 'PV', '"'.mystr.'"' ],
4df7f6af 44 myhref => [ $RV_class, '\\\\HASH'],
f9f861ec 45 pi => [ 'NV', pi ],
4df7f6af
NC
46 myglob => [ $RV_class, '\\\\' ],
47 mysub => [ $RV_class, '\\\\' ],
48 myunsub => [ $RV_class, '\\\\' ],
f9f861ec 49 # these are not inlined, at least not per BC::Concise
4df7f6af
NC
50 #myyes => [ $RV_class, ],
51 #myno => [ $RV_class, ],
e412117e 52 $] > 5.009 ? (
4df7f6af 53 myaref => [ $RV_class, '\\\\' ],
e412117e
NC
54 myfl => [ 'NV', myfl ],
55 myint => [ 'IV', myint ],
f7c278bf 56 $] >= 5.011 ? (
4c2c679f 57 myrex => [ $RV_class, '\\\\"\\(?^:Foo\\)"' ],
f7c278bf 58 ) : (
4df7f6af 59 myrex => [ $RV_class, '\\\\' ],
f7c278bf 60 ),
e412117e
NC
61 myundef => [ 'NULL', ],
62 ) : (
63 myaref => [ 'PVIV', '' ],
64 myfl => [ 'PVNV', myfl ],
65 myint => [ 'PVIV', myint ],
66 myrex => [ 'PVNV', '' ],
67 myundef => [ 'PVIV', ],
68 )
d51cf0c9
JC
69};
70
71use constant WEEKDAYS
72 => qw ( Sunday Monday Tuesday Wednesday Thursday Friday Saturday );
73
74
d51cf0c9
JC
75$::{napier} = \2.71828; # counter-example (doesn't get optimized).
76eval "sub napier ();";
77
78
79# should be able to undefine constant::import here ???
80INIT {
81 # eval 'sub constant::import () {}';
82 # undef *constant::import::{CODE};
83};
84
85#################################
f9f861ec 86pass("RENDER CONSTANT SUBS RETURNING SCALARS");
2018a5c3 87
f9f861ec
JC
88for $func (sort keys %$want) {
89 # no strict 'refs'; # why not needed ?
90 checkOptree ( name => "$func() as a coderef",
91 code => \&{$func},
92 noanchors => 1,
93 expect => <<EOT_EOT, expect_nt => <<EONT_EONT);
94 is a constant sub, optimized to a $want->{$func}[0]
2018a5c3 95EOT_EOT
f9f861ec 96 is a constant sub, optimized to a $want->{$func}[0]
d51cf0c9
JC
97EONT_EONT
98
f9f861ec 99}
d51cf0c9 100
f9f861ec 101pass("RENDER CALLS TO THOSE CONSTANT SUBS");
d51cf0c9 102
f9f861ec
JC
103for $func (sort keys %$want) {
104 # print "# doing $func\n";
105 checkOptree ( name => "call $func",
106 code => "$func",
107 ($want->{$func}[2]) ? ( todo => $want->{$func}[2]) : (),
108 bc_opts => '-nobanner',
109 expect => <<EOT_EOT, expect_nt => <<EONT_EONT);
d51cf0c9 1103 <1> leavesub[2 refs] K/REFC,1 ->(end)
f9f861ec 111- <\@> lineseq KP ->3
51530e33 1121 <;> dbstate(main 833 (eval 44):1) v:% ->2
6b7c6d95 1132 <\$> const[$want->{$func}[0] $want->{$func}[1]] s* ->3
d51cf0c9
JC
114EOT_EOT
1153 <1> leavesub[2 refs] K/REFC,1 ->(end)
f9f861ec 116- <\@> lineseq KP ->3
51530e33 1171 <;> dbstate(main 833 (eval 44):1) v:% ->2
6b7c6d95 1182 <\$> const($want->{$func}[0] $want->{$func}[1]) s* ->3
d51cf0c9
JC
119EONT_EONT
120
f9f861ec 121}
d51cf0c9 122
f9f861ec
JC
123##############
124pass("MORE TESTS");
d51cf0c9 125
f9f861ec
JC
126checkOptree ( name => 'myyes() as coderef',
127 code => sub () { 1==1 },
2018a5c3
JC
128 noanchors => 1,
129 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
f9f861ec 130 is a constant sub, optimized to a SPECIAL
2018a5c3 131EOT_EOT
f9f861ec 132 is a constant sub, optimized to a SPECIAL
2018a5c3
JC
133EONT_EONT
134
135
f9f861ec 136checkOptree ( name => 'myyes() as coderef',
36932700 137 prog => 'sub a() { 1==1 }; print a',
2018a5c3 138 noanchors => 1,
e412117e 139 strip_open_hints => 1,
2018a5c3 140 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
36932700
NC
141# 6 <@> leave[1 ref] vKP/REFC ->(end)
142# 1 <0> enter ->2
e412117e 143# 2 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->3
36932700
NC
144# 5 <@> print vK ->6
145# 3 <0> pushmark s ->4
6b7c6d95 146# 4 <$> const[SPECIAL sv_yes] s* ->5
2018a5c3 147EOT_EOT
36932700
NC
148# 6 <@> leave[1 ref] vKP/REFC ->(end)
149# 1 <0> enter ->2
e412117e 150# 2 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->3
36932700
NC
151# 5 <@> print vK ->6
152# 3 <0> pushmark s ->4
6b7c6d95 153# 4 <$> const(SPECIAL sv_yes) s* ->5
2018a5c3
JC
154EONT_EONT
155
d51cf0c9 156
36932700
NC
157# Need to do this as a prog, not code, as only the first constant to use
158# PL_sv_no actually gets to use the real thing - every one following is
159# copied.
f9f861ec 160checkOptree ( name => 'myno() as coderef',
36932700 161 prog => 'sub a() { 1!=1 }; print a',
d51cf0c9 162 noanchors => 1,
e412117e 163 strip_open_hints => 1,
d51cf0c9 164 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
36932700
NC
165# 6 <@> leave[1 ref] vKP/REFC ->(end)
166# 1 <0> enter ->2
e412117e 167# 2 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->3
36932700
NC
168# 5 <@> print vK ->6
169# 3 <0> pushmark s ->4
6b7c6d95 170# 4 <$> const[SPECIAL sv_no] s* ->5
d51cf0c9 171EOT_EOT
36932700
NC
172# 6 <@> leave[1 ref] vKP/REFC ->(end)
173# 1 <0> enter ->2
e412117e 174# 2 <;> nextstate(main 2 -e:1) v:>,<,%,{ ->3
36932700
NC
175# 5 <@> print vK ->6
176# 3 <0> pushmark s ->4
6b7c6d95 177# 4 <$> const(SPECIAL sv_no) s* ->5
d51cf0c9
JC
178EONT_EONT
179
180
e412117e 181my ($expect, $expect_nt) = (<<'EOT_EOT', <<'EONT_EONT');
d51cf0c9
JC
182# 3 <1> leavesub[2 refs] K/REFC,1 ->(end)
183# - <@> lineseq K ->3
51530e33 184# 1 <;> nextstate(constant 61 constant.pm:118) v:%,*,& ->2
dbeafbd1 185# 2 <0> padav[@list:FAKE:m:96] ->3
d51cf0c9
JC
186EOT_EOT
187# 3 <1> leavesub[2 refs] K/REFC,1 ->(end)
188# - <@> lineseq K ->3
51530e33 189# 1 <;> nextstate(constant 61 constant.pm:118) v:%,*,& ->2
dbeafbd1 190# 2 <0> padav[@list:FAKE:m:71] ->3
d51cf0c9
JC
191EONT_EONT
192
e412117e
NC
193if($] < 5.009) {
194 # 5.8.x doesn't add the m flag to padav
195 s/FAKE:m:\d+/FAKE/ foreach ($expect, $expect_nt);
196}
197
198checkOptree ( name => 'constant sub returning list',
199 code => \&WEEKDAYS,
200 noanchors => 1,
201 expect => $expect, expect_nt => $expect_nt);
202
d51cf0c9
JC
203
204sub printem {
205 printf "myint %d mystr %s myfl %f pi %f\n"
206 , myint, mystr, myfl, pi;
207}
208
e412117e 209my ($expect, $expect_nt) = (<<'EOT_EOT', <<'EONT_EONT');
d51cf0c9
JC
210# 9 <1> leavesub[1 ref] K/REFC,1 ->(end)
211# - <@> lineseq KP ->9
be2b1c74 212# 1 <;> nextstate(main 635 optree_constants.t:163) v:>,<,% ->2
d51cf0c9 213# 8 <@> prtf sK ->9
69974ce6
FC
214# 2 <0> pushmark sM ->3
215# 3 <$> const[PV "myint %d mystr %s myfl %f pi %f\n"] sM ->4
216# 4 <$> const[IV 42] sM* ->5
217# 5 <$> const[PV "hithere"] sM* ->6
218# 6 <$> const[NV 1.414213] sM* ->7
219# 7 <$> const[NV 3.14159] sM* ->8
d51cf0c9
JC
220EOT_EOT
221# 9 <1> leavesub[1 ref] K/REFC,1 ->(end)
222# - <@> lineseq KP ->9
be2b1c74 223# 1 <;> nextstate(main 635 optree_constants.t:163) v:>,<,% ->2
d51cf0c9 224# 8 <@> prtf sK ->9
69974ce6
FC
225# 2 <0> pushmark sM ->3
226# 3 <$> const(PV "myint %d mystr %s myfl %f pi %f\n") sM ->4
227# 4 <$> const(IV 42) sM* ->5
228# 5 <$> const(PV "hithere") sM* ->6
229# 6 <$> const(NV 1.414213) sM* ->7
230# 7 <$> const(NV 3.14159) sM* ->8
d51cf0c9
JC
231EONT_EONT
232
69974ce6
FC
233if($] < 5.015) {
234 s/M(?=\*? ->)//g for $expect, $expect_nt;
235}
e412117e
NC
236if($] < 5.009) {
237 # 5.8.x's use constant has larger types
238 foreach ($expect, $expect_nt) {
239 s/IV 42/PV$&/;
240 s/NV 1.41/PV$&/;
241 }
242}
243
244checkOptree ( name => 'call many in a print statement',
245 code => \&printem,
246 strip_open_hints => 1,
247 expect => $expect, expect_nt => $expect_nt);
d51cf0c9 248
183eb698
JC
249# test constant expression folding
250
251checkOptree ( name => 'arithmetic constant folding in print',
252 code => 'print 1+2+3',
253 strip_open_hints => 1,
254 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
255# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
256# - <@> lineseq KP ->5
51530e33 257# 1 <;> nextstate(main 937 (eval 53):1) v:% ->2
183eb698
JC
258# 4 <@> print sK ->5
259# 2 <0> pushmark s ->3
260# 3 <$> const[IV 6] s ->4
261EOT_EOT
262# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
263# - <@> lineseq KP ->5
51530e33 264# 1 <;> nextstate(main 937 (eval 53):1) v:% ->2
183eb698
JC
265# 4 <@> print sK ->5
266# 2 <0> pushmark s ->3
267# 3 <$> const(IV 6) s ->4
268EONT_EONT
269
270checkOptree ( name => 'string constant folding in print',
271 code => 'print "foo"."bar"',
272 strip_open_hints => 1,
273 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
274# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
275# - <@> lineseq KP ->5
51530e33 276# 1 <;> nextstate(main 942 (eval 55):1) v:% ->2
183eb698
JC
277# 4 <@> print sK ->5
278# 2 <0> pushmark s ->3
279# 3 <$> const[PV "foobar"] s ->4
280EOT_EOT
281# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
282# - <@> lineseq KP ->5
51530e33 283# 1 <;> nextstate(main 942 (eval 55):1) v:% ->2
183eb698
JC
284# 4 <@> print sK ->5
285# 2 <0> pushmark s ->3
286# 3 <$> const(PV "foobar") s ->4
287EONT_EONT
288
289checkOptree ( name => 'boolean or folding',
290 code => 'print "foobar" if 1 or 0',
291 strip_open_hints => 1,
292 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
293# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
294# - <@> lineseq KP ->5
51530e33 295# 1 <;> nextstate(main 942 (eval 55):1) v:% ->2
183eb698
JC
296# 4 <@> print sK ->5
297# 2 <0> pushmark s ->3
298# 3 <$> const[PV "foobar"] s ->4
299EOT_EOT
300# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
301# - <@> lineseq KP ->5
51530e33 302# 1 <;> nextstate(main 942 (eval 55):1) v:% ->2
183eb698
JC
303# 4 <@> print sK ->5
304# 2 <0> pushmark s ->3
305# 3 <$> const(PV "foobar") s ->4
306EONT_EONT
307
308checkOptree ( name => 'lc*,uc*,gt,lt,ge,le,cmp',
309 code => sub {
310 $s = uc('foo.').ucfirst('bar.').lc('LOW.').lcfirst('LOW');
311 print "a-lt-b" if "a" lt "b";
312 print "b-gt-a" if "b" gt "a";
313 print "a-le-b" if "a" le "b";
314 print "b-ge-a" if "b" ge "a";
315 print "b-cmp-a" if "b" cmp "a";
316 print "a-gt-b" if "a" gt "b"; # should be suppressed
317 },
318 strip_open_hints => 1,
319 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
320# r <1> leavesub[1 ref] K/REFC,1 ->(end)
321# - <@> lineseq KP ->r
b6093575 322# 1 <;> nextstate(main 916 optree_constants.t:307) v:>,<,%,{ ->2
183eb698
JC
323# 4 <2> sassign vKS/2 ->5
324# 2 <$> const[PV "FOO.Bar.low.lOW"] s ->3
325# - <1> ex-rv2sv sKRM*/1 ->4
326# 3 <#> gvsv[*s] s ->4
b6093575 327# 5 <;> nextstate(main 916 optree_constants.t:308) v:>,<,%,{ ->6
183eb698
JC
328# 8 <@> print vK ->9
329# 6 <0> pushmark s ->7
330# 7 <$> const[PV "a-lt-b"] s ->8
b6093575 331# 9 <;> nextstate(main 916 optree_constants.t:309) v:>,<,%,{ ->a
183eb698
JC
332# c <@> print vK ->d
333# a <0> pushmark s ->b
334# b <$> const[PV "b-gt-a"] s ->c
b6093575 335# d <;> nextstate(main 916 optree_constants.t:310) v:>,<,%,{ ->e
183eb698
JC
336# g <@> print vK ->h
337# e <0> pushmark s ->f
338# f <$> const[PV "a-le-b"] s ->g
b6093575 339# h <;> nextstate(main 916 optree_constants.t:311) v:>,<,%,{ ->i
183eb698
JC
340# k <@> print vK ->l
341# i <0> pushmark s ->j
342# j <$> const[PV "b-ge-a"] s ->k
b6093575 343# l <;> nextstate(main 916 optree_constants.t:312) v:>,<,%,{ ->m
183eb698
JC
344# o <@> print vK ->p
345# m <0> pushmark s ->n
346# n <$> const[PV "b-cmp-a"] s ->o
b6093575 347# p <;> nextstate(main 916 optree_constants.t:313) v:>,<,%,{ ->q
183eb698
JC
348# q <$> const[PVNV 0] s/SHORT ->r
349EOT_EOT
350# r <1> leavesub[1 ref] K/REFC,1 ->(end)
351# - <@> lineseq KP ->r
b6093575 352# 1 <;> nextstate(main 916 optree_constants.t:307) v:>,<,%,{ ->2
183eb698
JC
353# 4 <2> sassign vKS/2 ->5
354# 2 <$> const(PV "FOO.Bar.low.lOW") s ->3
355# - <1> ex-rv2sv sKRM*/1 ->4
356# 3 <$> gvsv(*s) s ->4
b6093575 357# 5 <;> nextstate(main 916 optree_constants.t:308) v:>,<,%,{ ->6
183eb698
JC
358# 8 <@> print vK ->9
359# 6 <0> pushmark s ->7
360# 7 <$> const(PV "a-lt-b") s ->8
b6093575 361# 9 <;> nextstate(main 916 optree_constants.t:309) v:>,<,%,{ ->a
183eb698
JC
362# c <@> print vK ->d
363# a <0> pushmark s ->b
364# b <$> const(PV "b-gt-a") s ->c
b6093575 365# d <;> nextstate(main 916 optree_constants.t:310) v:>,<,%,{ ->e
183eb698
JC
366# g <@> print vK ->h
367# e <0> pushmark s ->f
368# f <$> const(PV "a-le-b") s ->g
b6093575 369# h <;> nextstate(main 916 optree_constants.t:311) v:>,<,%,{ ->i
183eb698
JC
370# k <@> print vK ->l
371# i <0> pushmark s ->j
372# j <$> const(PV "b-ge-a") s ->k
b6093575 373# l <;> nextstate(main 916 optree_constants.t:312) v:>,<,%,{ ->m
183eb698
JC
374# o <@> print vK ->p
375# m <0> pushmark s ->n
376# n <$> const(PV "b-cmp-a") s ->o
b6093575 377# p <;> nextstate(main 916 optree_constants.t:313) v:>,<,%,{ ->q
183eb698
JC
378# q <$> const(SPECIAL sv_no) s/SHORT ->r
379EONT_EONT
380
381checkOptree ( name => 'mixed constant folding, with explicit braces',
382 code => 'print "foo"."bar".(2+3)',
383 strip_open_hints => 1,
384 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
385# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
386# - <@> lineseq KP ->5
51530e33 387# 1 <;> nextstate(main 977 (eval 28):1) v:% ->2
183eb698
JC
388# 4 <@> print sK ->5
389# 2 <0> pushmark s ->3
390# 3 <$> const[PV "foobar5"] s ->4
391EOT_EOT
392# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
393# - <@> lineseq KP ->5
51530e33 394# 1 <;> nextstate(main 977 (eval 28):1) v:% ->2
183eb698
JC
395# 4 <@> print sK ->5
396# 2 <0> pushmark s ->3
397# 3 <$> const(PV "foobar5") s ->4
398EONT_EONT
399
d51cf0c9
JC
400__END__
401
402=head NB
403
404Optimized constant subs are stored as bare scalars in the stash
405(package hash), which formerly held only GVs (typeglobs).
406
407But you cant create them manually - you cant assign a scalar to a
408stash element, and expect it to work like a constant-sub, even if you
409provide a prototype.
410
411This is a feature; alternative is too much action-at-a-distance. The
412following test demonstrates - napier is not seen as a function at all,
413much less an optimized one.
414
415=cut
416
417checkOptree ( name => 'not evertnapier',
418 code => \&napier,
419 noanchors => 1,
420 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
421 has no START
422EOT_EOT
423 has no START
424EONT_EONT
425
426