This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Brendan Byrd is now a perl AUTHOR
[perl5.git] / ext / B / t / f_map.t
1 #!perl
2
3 BEGIN {
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     if (!$Config::Config{useperlio}) {
11         print "1..0 # Skip -- need perlio to walk the optree\n";
12         exit 0;
13     }
14 }
15 use OptreeCheck;
16 plan tests => 18;
17
18
19 =head1 f_map.t
20
21 Code test snippets here are adapted from `perldoc -f map`
22
23 Due to a bleadperl optimization (Dave Mitchell, circa may 04), the
24 (map|grep)(start|while) opcodes have different flags in 5.9, their
25 private flags /1, /2 are gone in blead (for the cases covered)
26
27 When the optree stuff was integrated into 5.8.6, these tests failed,
28 and were todo'd.  They're now done, by version-specific tweaking in
29 mkCheckRex(), therefore the skip is removed too.
30
31 =for gentest
32
33 # chunk: #!perl
34 # examples shamelessly snatched from perldoc -f map
35
36 =cut
37
38 =for gentest
39
40 # chunk: # translates a list of numbers to the corresponding characters.
41 @chars = map(chr, @nums);
42
43 =cut
44
45 checkOptree(note   => q{},
46             bcopts => q{-exec},
47             code   => q{@chars = map(chr, @nums); },
48             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
49 # 1  <;> nextstate(main 475 (eval 10):1) v
50 # 2  <0> pushmark s
51 # 3  <0> pushmark s
52 # 4  <#> gv[*nums] s
53 # 5  <1> rv2av[t7] lKM/1
54 # 6  <@> mapstart lK
55 # 7  <|> mapwhile(other->8)[t8] lK
56 # 8      <#> gvsv[*_] s
57 # 9      <1> chr[t5] sK/1
58 #            goto 7
59 # a  <0> pushmark s
60 # b  <#> gv[*chars] s
61 # c  <1> rv2av[t2] lKRM*/1
62 # d  <2> aassign[t9] KS/COMMON
63 # e  <1> leavesub[1 ref] K/REFC,1
64 EOT_EOT
65 # 1  <;> nextstate(main 559 (eval 15):1) v
66 # 2  <0> pushmark s
67 # 3  <0> pushmark s
68 # 4  <$> gv(*nums) s
69 # 5  <1> rv2av[t4] lKM/1
70 # 6  <@> mapstart lK
71 # 7  <|> mapwhile(other->8)[t5] lK
72 # 8      <$> gvsv(*_) s
73 # 9      <1> chr[t3] sK/1
74 #            goto 7
75 # a  <0> pushmark s
76 # b  <$> gv(*chars) s
77 # c  <1> rv2av[t1] lKRM*/1
78 # d  <2> aassign[t6] KS/COMMON
79 # e  <1> leavesub[1 ref] K/REFC,1
80 EONT_EONT
81
82
83 =for gentest
84
85 # chunk: %hash = map { getkey($_) => $_ } @array;
86
87 =cut
88
89 checkOptree(note   => q{},
90             bcopts => q{-exec},
91             code   => q{%hash = map { getkey($_) => $_ } @array; },
92             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
93 # 1  <;> nextstate(main 476 (eval 10):1) v:{
94 # 2  <0> pushmark s
95 # 3  <0> pushmark s
96 # 4  <#> gv[*array] s
97 # 5  <1> rv2av[t8] lKM/1
98 # 6  <@> mapstart lK*              < 5.017002
99 # 6  <@> mapstart lK               >=5.017002
100 # 7  <|> mapwhile(other->8)[t9] lK
101 # 8      <0> enter l
102 # 9      <;> nextstate(main 475 (eval 10):1) v:{
103 # a      <0> pushmark s
104 # b      <0> pushmark s
105 # c      <#> gvsv[*_] s
106 # d      <#> gv[*getkey] s/EARLYCV
107 # e      <1> entersub[t5] lKS/TARG
108 # f      <#> gvsv[*_] s
109 # g      <@> list lK
110 # h      <@> leave lKP
111 #            goto 7
112 # i  <0> pushmark s
113 # j  <#> gv[*hash] s
114 # k  <1> rv2hv[t2] lKRM*/1
115 # l  <2> aassign[t10] KS/COMMON
116 # m  <1> leavesub[1 ref] K/REFC,1
117 EOT_EOT
118 # 1  <;> nextstate(main 560 (eval 15):1) v:{
119 # 2  <0> pushmark s
120 # 3  <0> pushmark s
121 # 4  <$> gv(*array) s
122 # 5  <1> rv2av[t3] lKM/1
123 # 6  <@> mapstart lK*              < 5.017002
124 # 6  <@> mapstart lK               >=5.017002
125 # 7  <|> mapwhile(other->8)[t4] lK
126 # 8      <0> enter l
127 # 9      <;> nextstate(main 559 (eval 15):1) v:{
128 # a      <0> pushmark s
129 # b      <0> pushmark s
130 # c      <$> gvsv(*_) s
131 # d      <$> gv(*getkey) s/EARLYCV
132 # e      <1> entersub[t2] lKS/TARG
133 # f      <$> gvsv(*_) s
134 # g      <@> list lK
135 # h      <@> leave lKP
136 #            goto 7
137 # i  <0> pushmark s
138 # j  <$> gv(*hash) s
139 # k  <1> rv2hv[t1] lKRM*/1
140 # l  <2> aassign[t5] KS/COMMON
141 # m  <1> leavesub[1 ref] K/REFC,1
142 EONT_EONT
143
144
145 =for gentest
146
147 # chunk: {
148     %hash = ();
149     foreach $_ (@array) {
150         $hash{getkey($_)} = $_;
151     }
152 }
153
154 =cut
155
156 checkOptree(note   => q{},
157             bcopts => q{-exec},
158             code   => q{{ %hash = (); foreach $_ (@array) { $hash{getkey($_)} = $_; } } },
159             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
160 # 1  <;> nextstate(main 478 (eval 10):1) v:{
161 # 2  <{> enterloop(next->u last->u redo->3) 
162 # 3  <;> nextstate(main 475 (eval 10):1) v
163 # 4  <0> pushmark s
164 # 5  <0> pushmark s
165 # 6  <#> gv[*hash] s
166 # 7  <1> rv2hv[t2] lKRM*/1
167 # 8  <2> aassign[t3] vKS
168 # 9  <;> nextstate(main 476 (eval 10):1) v:{
169 # a  <0> pushmark sM
170 # b  <#> gv[*array] s
171 # c  <1> rv2av[t6] sKRM/1
172 # d  <#> gv[*_] s
173 # e  <1> rv2gv sKRM/1
174 # f  <{> enteriter(next->q last->t redo->g) lKS/8
175 # r  <0> iter s
176 # s  <|> and(other->g) K/1
177 # g      <;> nextstate(main 475 (eval 10):1) v:{
178 # h      <#> gvsv[*_] s
179 # i      <#> gv[*hash] s
180 # j      <1> rv2hv sKR/1
181 # k      <0> pushmark s
182 # l      <#> gvsv[*_] s
183 # m      <#> gv[*getkey] s/EARLYCV
184 # n      <1> entersub[t10] sKS/TARG
185 # o      <2> helem sKRM*/2
186 # p      <2> sassign vKS/2
187 # q      <0> unstack s
188 #            goto r
189 # t  <2> leaveloop KP/2
190 # u  <2> leaveloop K/2
191 # v  <1> leavesub[1 ref] K/REFC,1
192 EOT_EOT
193 # 1  <;> nextstate(main 562 (eval 15):1) v:{
194 # 2  <{> enterloop(next->u last->u redo->3) 
195 # 3  <;> nextstate(main 559 (eval 15):1) v
196 # 4  <0> pushmark s
197 # 5  <0> pushmark s
198 # 6  <$> gv(*hash) s
199 # 7  <1> rv2hv[t1] lKRM*/1
200 # 8  <2> aassign[t2] vKS
201 # 9  <;> nextstate(main 560 (eval 15):1) v:{
202 # a  <0> pushmark sM
203 # b  <$> gv(*array) s
204 # c  <1> rv2av[t3] sKRM/1
205 # d  <$> gv(*_) s
206 # e  <1> rv2gv sKRM/1
207 # f  <{> enteriter(next->q last->t redo->g) lKS/8
208 # r  <0> iter s
209 # s  <|> and(other->g) K/1
210 # g      <;> nextstate(main 559 (eval 15):1) v:{
211 # h      <$> gvsv(*_) s
212 # i      <$> gv(*hash) s
213 # j      <1> rv2hv sKR/1
214 # k      <0> pushmark s
215 # l      <$> gvsv(*_) s
216 # m      <$> gv(*getkey) s/EARLYCV
217 # n      <1> entersub[t4] sKS/TARG
218 # o      <2> helem sKRM*/2
219 # p      <2> sassign vKS/2
220 # q      <0> unstack s
221 #            goto r
222 # t  <2> leaveloop KP/2
223 # u  <2> leaveloop K/2
224 # v  <1> leavesub[1 ref] K/REFC,1
225 EONT_EONT
226
227
228 =for gentest
229
230 # chunk: #%hash = map {  "\L$_", 1  } @array;  # perl guesses EXPR.  wrong
231 %hash = map { +"\L$_", 1  } @array;  # perl guesses BLOCK. right
232
233 =cut
234
235 checkOptree(note   => q{},
236             bcopts => q{-exec},
237             code   => q{%hash = map { +"\L$_", 1 } @array; },
238             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
239 # 1  <;> nextstate(main 476 (eval 10):1) v
240 # 2  <0> pushmark s
241 # 3  <0> pushmark s
242 # 4  <#> gv[*array] s
243 # 5  <1> rv2av[t7] lKM/1
244 # 6  <@> mapstart lK*              < 5.017002
245 # 6  <@> mapstart lK               >=5.017002
246 # 7  <|> mapwhile(other->8)[t9] lK
247 # 8      <0> pushmark s
248 # 9      <#> gvsv[*_] s
249 # a      <1> lc[t4] sK/1
250 # b      <@> stringify[t5] sK/1
251 # c      <$> const[IV 1] s
252 # d      <@> list lK
253 # -      <@> scope lK              < 5.017002
254 #            goto 7
255 # e  <0> pushmark s
256 # f  <#> gv[*hash] s
257 # g  <1> rv2hv[t2] lKRM*/1
258 # h  <2> aassign[t10] KS/COMMON
259 # i  <1> leavesub[1 ref] K/REFC,1
260 EOT_EOT
261 # 1  <;> nextstate(main 560 (eval 15):1) v
262 # 2  <0> pushmark s
263 # 3  <0> pushmark s
264 # 4  <$> gv(*array) s
265 # 5  <1> rv2av[t4] lKM/1
266 # 6  <@> mapstart lK*              < 5.017002
267 # 6  <@> mapstart lK               >=5.017002
268 # 7  <|> mapwhile(other->8)[t5] lK
269 # 8      <0> pushmark s
270 # 9      <$> gvsv(*_) s
271 # a      <1> lc[t2] sK/1
272 # b      <@> stringify[t3] sK/1
273 # c      <$> const(IV 1) s
274 # d      <@> list lK
275 # -      <@> scope lK              < 5.017002
276 #            goto 7
277 # e  <0> pushmark s
278 # f  <$> gv(*hash) s
279 # g  <1> rv2hv[t1] lKRM*/1
280 # h  <2> aassign[t6] KS/COMMON
281 # i  <1> leavesub[1 ref] K/REFC,1
282 EONT_EONT
283
284
285 =for gentest
286
287 # chunk: %hash = map { ("\L$_", 1) } @array;  # this also works
288
289 =cut
290
291 checkOptree(note   => q{},
292             bcopts => q{-exec},
293             code   => q{%hash = map { ("\L$_", 1) } @array; },
294             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
295 # 1  <;> nextstate(main 476 (eval 10):1) v
296 # 2  <0> pushmark s
297 # 3  <0> pushmark s
298 # 4  <#> gv[*array] s
299 # 5  <1> rv2av[t7] lKM/1
300 # 6  <@> mapstart lK*              < 5.017002
301 # 6  <@> mapstart lK               >=5.017002
302 # 7  <|> mapwhile(other->8)[t9] lK
303 # 8      <0> pushmark s
304 # 9      <#> gvsv[*_] s
305 # a      <1> lc[t4] sK/1
306 # b      <@> stringify[t5] sK/1
307 # c      <$> const[IV 1] s
308 # d      <@> list lKP
309 # -      <@> scope lK              < 5.017002
310 #            goto 7
311 # e  <0> pushmark s
312 # f  <#> gv[*hash] s
313 # g  <1> rv2hv[t2] lKRM*/1
314 # h  <2> aassign[t10] KS/COMMON
315 # i  <1> leavesub[1 ref] K/REFC,1
316 EOT_EOT
317 # 1  <;> nextstate(main 560 (eval 15):1) v
318 # 2  <0> pushmark s
319 # 3  <0> pushmark s
320 # 4  <$> gv(*array) s
321 # 5  <1> rv2av[t4] lKM/1
322 # 6  <@> mapstart lK*              < 5.017002
323 # 6  <@> mapstart lK               >=5.017002
324 # 7  <|> mapwhile(other->8)[t5] lK
325 # 8      <0> pushmark s
326 # 9      <$> gvsv(*_) s
327 # a      <1> lc[t2] sK/1
328 # b      <@> stringify[t3] sK/1
329 # c      <$> const(IV 1) s
330 # d      <@> list lKP
331 # -      <@> scope lK              < 5.017002
332 #            goto 7
333 # e  <0> pushmark s
334 # f  <$> gv(*hash) s
335 # g  <1> rv2hv[t1] lKRM*/1
336 # h  <2> aassign[t6] KS/COMMON
337 # i  <1> leavesub[1 ref] K/REFC,1
338 EONT_EONT
339
340
341 =for gentest
342
343 # chunk: %hash = map {  lc($_), 1  } @array;  # as does this.
344
345 =cut
346
347 checkOptree(note   => q{},
348             bcopts => q{-exec},
349             code   => q{%hash = map { lc($_), 1 } @array; },
350             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
351 # 1  <;> nextstate(main 476 (eval 10):1) v
352 # 2  <0> pushmark s
353 # 3  <0> pushmark s
354 # 4  <#> gv[*array] s
355 # 5  <1> rv2av[t6] lKM/1
356 # 6  <@> mapstart lK*              < 5.017002
357 # 6  <@> mapstart lK               >=5.017002
358 # 7  <|> mapwhile(other->8)[t8] lK
359 # 8      <0> pushmark s
360 # 9      <#> gvsv[*_] s
361 # a      <1> lc[t4] sK/1
362 # b      <$> const[IV 1] s
363 # c      <@> list lK
364 # -      <@> scope lK              < 5.017002
365 #            goto 7
366 # d  <0> pushmark s
367 # e  <#> gv[*hash] s
368 # f  <1> rv2hv[t2] lKRM*/1
369 # g  <2> aassign[t9] KS/COMMON
370 # h  <1> leavesub[1 ref] K/REFC,1
371 EOT_EOT
372 # 1  <;> nextstate(main 589 (eval 26):1) v
373 # 2  <0> pushmark s
374 # 3  <0> pushmark s
375 # 4  <$> gv(*array) s
376 # 5  <1> rv2av[t3] lKM/1
377 # 6  <@> mapstart lK*              < 5.017002
378 # 6  <@> mapstart lK               >=5.017002
379 # 7  <|> mapwhile(other->8)[t4] lK
380 # 8      <0> pushmark s
381 # 9      <$> gvsv(*_) s
382 # a      <1> lc[t2] sK/1
383 # b      <$> const(IV 1) s
384 # c      <@> list lK
385 # -      <@> scope lK              < 5.017002
386 #            goto 7
387 # d  <0> pushmark s
388 # e  <$> gv(*hash) s
389 # f  <1> rv2hv[t1] lKRM*/1
390 # g  <2> aassign[t5] KS/COMMON
391 # h  <1> leavesub[1 ref] K/REFC,1
392 EONT_EONT
393
394
395 =for gentest
396
397 # chunk: %hash = map +( lc($_), 1 ), @array;  # this is EXPR and works!
398
399 =cut
400
401 checkOptree(note   => q{},
402             bcopts => q{-exec},
403             code   => q{%hash = map +( lc($_), 1 ), @array; },
404             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
405 # 1  <;> nextstate(main 475 (eval 10):1) v
406 # 2  <0> pushmark s
407 # 3  <0> pushmark s
408 # 4  <#> gv[*array] s
409 # 5  <1> rv2av[t6] lKM/1
410 # 6  <@> mapstart lK
411 # 7  <|> mapwhile(other->8)[t7] lK
412 # 8      <0> pushmark s
413 # 9      <#> gvsv[*_] s
414 # a      <1> lc[t4] sK/1
415 # b      <$> const[IV 1] s
416 # c      <@> list lKP
417 #            goto 7
418 # d  <0> pushmark s
419 # e  <#> gv[*hash] s
420 # f  <1> rv2hv[t2] lKRM*/1
421 # g  <2> aassign[t8] KS/COMMON
422 # h  <1> leavesub[1 ref] K/REFC,1
423 EOT_EOT
424 # 1  <;> nextstate(main 593 (eval 28):1) v
425 # 2  <0> pushmark s
426 # 3  <0> pushmark s
427 # 4  <$> gv(*array) s
428 # 5  <1> rv2av[t3] lKM/1
429 # 6  <@> mapstart lK
430 # 7  <|> mapwhile(other->8)[t4] lK
431 # 8      <0> pushmark s
432 # 9      <$> gvsv(*_) s
433 # a      <1> lc[t2] sK/1
434 # b      <$> const(IV 1) s
435 # c      <@> list lKP
436 #            goto 7
437 # d  <0> pushmark s
438 # e  <$> gv(*hash) s
439 # f  <1> rv2hv[t1] lKRM*/1
440 # g  <2> aassign[t5] KS/COMMON
441 # h  <1> leavesub[1 ref] K/REFC,1
442 EONT_EONT
443
444
445 =for gentest
446
447 # chunk: %hash = map  ( lc($_), 1 ), @array;  # evaluates to (1, @array)
448
449 =cut
450
451 checkOptree(note   => q{},
452             bcopts => q{-exec},
453             code   => q{%hash = map ( lc($_), 1 ), @array; },
454             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
455 # 1  <;> nextstate(main 475 (eval 10):1) v
456 # 2  <0> pushmark s
457 # 3  <0> pushmark s
458 # 4  <0> pushmark s
459 # 5  <$> const[IV 1] sM
460 # 6  <@> mapstart lK
461 # 7  <|> mapwhile(other->8)[t5] lK
462 # 8      <#> gvsv[*_] s
463 # 9      <1> lc[t4] sK/1
464 #            goto 7
465 # a  <0> pushmark s
466 # b  <#> gv[*hash] s
467 # c  <1> rv2hv[t2] lKRM*/1
468 # d  <2> aassign[t6] KS/COMMON
469 # e  <#> gv[*array] s
470 # f  <1> rv2av[t8] K/1
471 # g  <@> list K
472 # h  <1> leavesub[1 ref] K/REFC,1
473 EOT_EOT
474 # 1  <;> nextstate(main 597 (eval 30):1) v
475 # 2  <0> pushmark s
476 # 3  <0> pushmark s
477 # 4  <0> pushmark s
478 # 5  <$> const(IV 1) sM
479 # 6  <@> mapstart lK
480 # 7  <|> mapwhile(other->8)[t3] lK
481 # 8      <$> gvsv(*_) s
482 # 9      <1> lc[t2] sK/1
483 #            goto 7
484 # a  <0> pushmark s
485 # b  <$> gv(*hash) s
486 # c  <1> rv2hv[t1] lKRM*/1
487 # d  <2> aassign[t4] KS/COMMON
488 # e  <$> gv(*array) s
489 # f  <1> rv2av[t5] K/1
490 # g  <@> list K
491 # h  <1> leavesub[1 ref] K/REFC,1
492 EONT_EONT
493
494
495 =for gentest
496
497 # chunk: @hashes = map +{ lc($_), 1 }, @array # EXPR, so needs , at end
498
499 =cut
500
501 checkOptree(note   => q{},
502             bcopts => q{-exec},
503             code   => q{@hashes = map +{ lc($_), 1 }, @array },
504             expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
505 # 1  <;> nextstate(main 475 (eval 10):1) v
506 # 2  <0> pushmark s
507 # 3  <0> pushmark s
508 # 4  <#> gv[*array] s
509 # 5  <1> rv2av[t6] lKM/1
510 # 6  <@> mapstart lK
511 # 7  <|> mapwhile(other->8)[t7] lK
512 # 8      <0> pushmark s
513 # 9      <#> gvsv[*_] s
514 # a      <1> lc[t4] sK/1
515 # b      <$> const[IV 1] s
516 # c      <@> anonhash sK*/1
517 #            goto 7
518 # d  <0> pushmark s
519 # e  <#> gv[*hashes] s
520 # f  <1> rv2av[t2] lKRM*/1
521 # g  <2> aassign[t8] KS/COMMON
522 # h  <1> leavesub[1 ref] K/REFC,1
523 EOT_EOT
524 # 1  <;> nextstate(main 601 (eval 32):1) v
525 # 2  <0> pushmark s
526 # 3  <0> pushmark s
527 # 4  <$> gv(*array) s
528 # 5  <1> rv2av[t3] lKM/1
529 # 6  <@> mapstart lK
530 # 7  <|> mapwhile(other->8)[t4] lK
531 # 8      <0> pushmark s
532 # 9      <$> gvsv(*_) s
533 # a      <1> lc[t2] sK/1
534 # b      <$> const(IV 1) s
535 # c      <@> anonhash sK*/1
536 #            goto 7
537 # d  <0> pushmark s
538 # e  <$> gv(*hashes) s
539 # f  <1> rv2av[t1] lKRM*/1
540 # g  <2> aassign[t5] KS/COMMON
541 # h  <1> leavesub[1 ref] K/REFC,1
542 EONT_EONT