5 @INC = qw(../lib ../ext/B/t);
15 #examples poached from perldoc -f sort
17 NOTE: name is no longer a required arg for checkOptree, as label is
18 synthesized out of others. HOWEVER, if the test-code has newlines in
19 it, the label must be overridden by an explicit name.
21 This is because t/TEST is quite particular about the test output it
22 processes, and multi-line labels violate its 1-line-per-test
27 # chunk: # sort lexically
28 @articles = sort @files;
32 checkOptree(note => q{},
34 code => q{@articles = sort @files; },
35 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
36 # 1 <;> nextstate(main 545 (eval 15):1) v
40 # 5 <1> rv2av[t4] lK/1
43 # 8 <#> gv[*articles] s
44 # 9 <1> rv2av[t2] lKRM*/1
45 # a <2> aassign[t5] KS
46 # b <1> leavesub[1 ref] K/REFC,1
48 # 1 <;> nextstate(main 545 (eval 15):1) v
52 # 5 <1> rv2av[t2] lK/1
55 # 8 <$> gv(*articles) s
56 # 9 <1> rv2av[t1] lKRM*/1
57 # a <2> aassign[t3] KS
58 # b <1> leavesub[1 ref] K/REFC,1
64 # chunk: # same thing, but with explicit sort routine
65 @articles = sort {$a cmp $b} @files;
69 checkOptree(note => q{},
71 code => q{@articles = sort {$a cmp $b} @files; },
72 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
73 # 1 <;> nextstate(main 546 (eval 15):1) v
77 # 5 <1> rv2av[t7] lK/1
80 # 8 <#> gv[*articles] s
81 # 9 <1> rv2av[t2] lKRM*/1
82 # a <2> aassign[t5] KS
83 # b <1> leavesub[1 ref] K/REFC,1
85 # 1 <;> nextstate(main 546 (eval 15):1) v
89 # 5 <1> rv2av[t3] lK/1
92 # 8 <$> gv(*articles) s
93 # 9 <1> rv2av[t1] lKRM*/1
94 # a <2> aassign[t2] KS
95 # b <1> leavesub[1 ref] K/REFC,1
101 # chunk: # now case-insensitively
102 @articles = sort {uc($a) cmp uc($b)} @files;
106 checkOptree(note => q{},
108 code => q{@articles = sort {uc($a) cmp uc($b)} @files; },
109 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
110 # 1 <;> nextstate(main 546 (eval 15):1) v
114 # 5 <1> rv2av[t9] lK/1
117 # 8 <#> gv[*articles] s
118 # 9 <1> rv2av[t2] lKRM*/1
119 # a <2> aassign[t10] KS
120 # b <1> leavesub[1 ref] K/REFC,1
122 # 1 <;> nextstate(main 546 (eval 15):1) v
126 # 5 <1> rv2av[t5] lK/1
129 # 8 <$> gv(*articles) s
130 # 9 <1> rv2av[t1] lKRM*/1
131 # a <2> aassign[t6] KS
132 # b <1> leavesub[1 ref] K/REFC,1
138 # chunk: # same thing in reversed order
139 @articles = sort {$b cmp $a} @files;
143 checkOptree(note => q{},
145 code => q{@articles = sort {$b cmp $a} @files; },
146 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
147 # 1 <;> nextstate(main 546 (eval 15):1) v
151 # 5 <1> rv2av[t7] lK/1
154 # 8 <#> gv[*articles] s
155 # 9 <1> rv2av[t2] lKRM*/1
156 # a <2> aassign[t5] KS
157 # b <1> leavesub[1 ref] K/REFC,1
159 # 1 <;> nextstate(main 546 (eval 15):1) v
163 # 5 <1> rv2av[t3] lK/1
166 # 8 <$> gv(*articles) s
167 # 9 <1> rv2av[t1] lKRM*/1
168 # a <2> aassign[t2] KS
169 # b <1> leavesub[1 ref] K/REFC,1
175 # chunk: # sort numerically ascending
176 @articles = sort {$a <=> $b} @files;
180 checkOptree(note => q{},
182 code => q{@articles = sort {$a <=> $b} @files; },
183 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
184 # 1 <;> nextstate(main 546 (eval 15):1) v
188 # 5 <1> rv2av[t7] lK/1
191 # 8 <#> gv[*articles] s
192 # 9 <1> rv2av[t2] lKRM*/1
193 # a <2> aassign[t5] KS
194 # b <1> leavesub[1 ref] K/REFC,1
196 # 1 <;> nextstate(main 546 (eval 15):1) v
200 # 5 <1> rv2av[t3] lK/1
203 # 8 <$> gv(*articles) s
204 # 9 <1> rv2av[t1] lKRM*/1
205 # a <2> aassign[t2] KS
206 # b <1> leavesub[1 ref] K/REFC,1
212 # chunk: # sort numerically descending
213 @articles = sort {$b <=> $a} @files;
217 checkOptree(note => q{},
219 code => q{@articles = sort {$b <=> $a} @files; },
220 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
221 # 1 <;> nextstate(main 587 (eval 26):1) v
225 # 5 <1> rv2av[t7] lK/1
226 # 6 <@> sort lK/REV,NUM
228 # 8 <#> gv[*articles] s
229 # 9 <1> rv2av[t2] lKRM*/1
230 # a <2> aassign[t5] KS
231 # b <1> leavesub[1 ref] K/REFC,1
233 # 1 <;> nextstate(main 546 (eval 15):1) v
237 # 5 <1> rv2av[t3] lK/1
238 # 6 <@> sort lK/REV,NUM
240 # 8 <$> gv(*articles) s
241 # 9 <1> rv2av[t1] lKRM*/1
242 # a <2> aassign[t2] KS
243 # b <1> leavesub[1 ref] K/REFC,1
249 # chunk: # this sorts the %age hash by value instead of key
250 # using an in-line function
251 @eldest = sort { $age{$b} <=> $age{$a} } keys %age;
255 checkOptree(note => q{},
257 code => q{@eldest = sort { $age{$b} <=> $age{$a} } keys %age; },
258 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
259 # 1 <;> nextstate(main 592 (eval 28):1) v
263 # 5 <1> rv2hv[t9] lKRM/1
264 # 6 <1> keys[t10] lK/1
267 # 9 <#> gv[*eldest] s
268 # a <1> rv2av[t2] lKRM*/1
269 # b <2> aassign[t11] KS
270 # c <1> leavesub[1 ref] K/REFC,1
272 # 1 <;> nextstate(main 546 (eval 15):1) v
276 # 5 <1> rv2hv[t3] lKRM/1
277 # 6 <1> keys[t4] lK/1
280 # 9 <$> gv(*eldest) s
281 # a <1> rv2av[t1] lKRM*/1
282 # b <2> aassign[t5] KS
283 # c <1> leavesub[1 ref] K/REFC,1
289 # chunk: # sort using explicit subroutine name
291 $age{$a} <=> $age{$b}; # presuming numeric
293 @sortedclass = sort byage @class;
297 checkOptree(note => q{},
299 code => q{sub byage { $age{$a} <=> $age{$b}; } @sortedclass = sort byage @class; },
300 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
301 # 1 <;> nextstate(main 597 (eval 30):1) v
304 # 4 <$> const[PV "byage"] s/BARE
306 # 6 <1> rv2av[t4] lK/1
309 # 9 <#> gv[*sortedclass] s
310 # a <1> rv2av[t2] lKRM*/1
311 # b <2> aassign[t5] KS
312 # c <1> leavesub[1 ref] K/REFC,1
314 # 1 <;> nextstate(main 546 (eval 15):1) v
317 # 4 <$> const(PV "byage") s/BARE
319 # 6 <1> rv2av[t2] lK/1
322 # 9 <$> gv(*sortedclass) s
323 # a <1> rv2av[t1] lKRM*/1
324 # b <2> aassign[t3] KS
325 # c <1> leavesub[1 ref] K/REFC,1
331 # chunk: sub backwards { $b cmp $a }
332 @harry = qw(dog cat x Cain Abel);
333 @george = qw(gone chased yz Punished Axed);
335 # prints AbelCaincatdogx
336 print sort backwards @harry;
337 # prints xdogcatCainAbel
338 print sort @george, 'to', @harry;
339 # prints AbelAxedCainPunishedcatchaseddoggonetoxyz
343 checkOptree(name => q{sort USERSUB LIST },
345 todo => 'sort why BARE flag happens',
346 code => q{sub backwards { $b cmp $a }
347 @harry = qw(dog cat x Cain Abel);
348 @george = qw(gone chased yz Punished Axed);
349 print sort @harry; print sort backwards @harry;
350 print sort @george, 'to', @harry; },
351 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
352 # 1 <;> nextstate(main 602 (eval 32):2) v
354 # 3 <$> const[PV "dog"] s
355 # 4 <$> const[PV "cat"] s
356 # 5 <$> const[PV "x"] s
357 # 6 <$> const[PV "Cain"] s
358 # 7 <$> const[PV "Abel"] s
361 # a <1> rv2av[t2] lKRM*/1
362 # b <2> aassign[t3] vKS
363 # c <;> nextstate(main 602 (eval 32):3) v
365 # e <$> const[PV "gone"] s
366 # f <$> const[PV "chased"] s
367 # g <$> const[PV "yz"] s
368 # h <$> const[PV "Punished"] s
369 # i <$> const[PV "Axed"] s
371 # k <#> gv[*george] s
372 # l <1> rv2av[t5] lKRM*/1
373 # m <2> aassign[t6] vKS
374 # n <;> nextstate(main 602 (eval 32):4) v
378 # r <1> rv2av[t8] lK/1
381 # u <;> nextstate(main 602 (eval 32):4) v
384 # x <$> const[PV "backwards"] s/BARE
386 # z <1> rv2av[t10] lK/1
389 # 12 <;> nextstate(main 602 (eval 32):5) v
392 # 15 <#> gv[*george] s
393 # 16 <1> rv2av[t12] lK/1
394 # 17 <$> const[PV "to"] s
395 # 18 <#> gv[*harry] s
396 # 19 <1> rv2av[t14] lK/1
399 # 1c <1> leavesub[1 ref] K/REFC,1
401 # 1 <;> nextstate(main 602 (eval 32):2) v
403 # 3 <$> const(PV "dog") s
404 # 4 <$> const(PV "cat") s
405 # 5 <$> const(PV "x") s
406 # 6 <$> const(PV "Cain") s
407 # 7 <$> const(PV "Abel") s
410 # a <1> rv2av[t1] lKRM*/1
411 # b <2> aassign[t2] vKS
412 # c <;> nextstate(main 602 (eval 32):3) v
414 # e <$> const(PV "gone") s
415 # f <$> const(PV "chased") s
416 # g <$> const(PV "yz") s
417 # h <$> const(PV "Punished") s
418 # i <$> const(PV "Axed") s
420 # k <$> gv(*george) s
421 # l <1> rv2av[t3] lKRM*/1
422 # m <2> aassign[t4] vKS
423 # n <;> nextstate(main 602 (eval 32):4) v
427 # r <1> rv2av[t5] lK/1
430 # u <;> nextstate(main 602 (eval 32):4) v
433 # x <$> const(PV "backwards") s/BARE
435 # z <1> rv2av[t6] lK/1
438 # 12 <;> nextstate(main 602 (eval 32):5) v
441 # 15 <$> gv(*george) s
442 # 16 <1> rv2av[t7] lK/1
443 # 17 <$> const(PV "to") s
444 # 18 <$> gv(*harry) s
445 # 19 <1> rv2av[t8] lK/1
448 # 1c <1> leavesub[1 ref] K/REFC,1
454 # chunk: # inefficiently sort by descending numeric compare using
455 # the first integer after the first = sign, or the
456 # whole record case-insensitively otherwise
458 $nums[$b] <=> $nums[$a]
459 || $caps[$a] cmp $caps[$b]
465 # chunk: # same thing, but without any temps
466 @new = map { $_->[0] }
467 sort { $b->[1] <=> $a->[1]
468 || $a->[2] cmp $b->[2]
469 } map { [$_, /=(\d+)/, uc($_)] } @old;
473 checkOptree(name => q{Compound sort/map Expression },
475 code => q{ @new = map { $_->[0] }
476 sort { $b->[1] <=> $a->[1] || $a->[2] cmp $b->[2] }
477 map { [$_, /=(\d+)/, uc($_)] } @old; },
478 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
479 # 1 <;> nextstate(main 609 (eval 34):3) v
485 # 7 <1> rv2av[t19] lKM/1
487 # 9 <|> mapwhile(other->a)[t20] lK
489 # b <;> nextstate(main 608 (eval 34):2) v
492 # e </> match(/"=(\\d+)"/) l/RTIME
495 # h <@> anonlist sKRM/1
501 # m <|> mapwhile(other->n)[t26] lK
503 # o <1> rv2sv sKM/DREFAV,1
504 # p <1> rv2av[t4] sKR/1
505 # q <$> const[IV 0] s
511 # u <1> rv2av[t2] lKRM*/1
512 # v <2> aassign[t27] KS/COMMON
513 # w <1> leavesub[1 ref] K/REFC,1
515 # 1 <;> nextstate(main 609 (eval 34):3) v
521 # 7 <1> rv2av[t10] lKM/1
523 # 9 <|> mapwhile(other->a)[t11] lK
525 # b <;> nextstate(main 608 (eval 34):2) v
528 # e </> match(/"=(\\d+)"/) l/RTIME
531 # h <@> anonlist sKRM/1
537 # m <|> mapwhile(other->n)[t12] lK
539 # o <1> rv2sv sKM/DREFAV,1
540 # p <1> rv2av[t2] sKR/1
541 # q <$> const(IV 0) s
547 # u <1> rv2av[t1] lKRM*/1
548 # v <2> aassign[t13] KS/COMMON
549 # w <1> leavesub[1 ref] K/REFC,1
555 # chunk: # using a prototype allows you to use any comparison subroutine
556 # as a sort subroutine (including other package's subroutines)
558 sub backwards ($$) { $_[1] cmp $_[0]; } # $a and $b are not set here
560 @new = sort other::backwards @old;
564 checkOptree(name => q{sort other::sub LIST },
566 code => q{package other; sub backwards ($$) { $_[1] cmp $_[0]; }
567 package main; @new = sort other::backwards @old; },
568 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
569 # 1 <;> nextstate(main 614 (eval 36):2) v
572 # 4 <$> const[PV "other::backwards"] s/BARE
574 # 6 <1> rv2av[t4] lK/1
578 # a <1> rv2av[t2] lKRM*/1
579 # b <2> aassign[t5] KS
580 # c <1> leavesub[1 ref] K/REFC,1
582 # 1 <;> nextstate(main 614 (eval 36):2) v
585 # 4 <$> const(PV "other::backwards") s/BARE
587 # 6 <1> rv2av[t2] lK/1
591 # a <1> rv2av[t1] lKRM*/1
592 # b <2> aassign[t3] KS
593 # c <1> leavesub[1 ref] K/REFC,1
599 # chunk: # repeat, condensed. $main::a and $b are unaffected
600 sub other::backwards ($$) { $_[1] cmp $_[0]; }
601 @new = sort other::backwards @old;
605 checkOptree(note => q{},
607 code => q{sub other::backwards ($$) { $_[1] cmp $_[0]; } @new = sort other::backwards @old; },
608 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
609 # 1 <;> nextstate(main 619 (eval 38):1) v
612 # 4 <$> const[PV "other::backwards"] s/BARE
614 # 6 <1> rv2av[t4] lK/1
618 # a <1> rv2av[t2] lKRM*/1
619 # b <2> aassign[t5] KS
620 # c <1> leavesub[1 ref] K/REFC,1
622 # 1 <;> nextstate(main 546 (eval 15):1) v
625 # 4 <$> const(PV "other::backwards") s/BARE
627 # 6 <1> rv2av[t2] lK/1
631 # a <1> rv2av[t1] lKRM*/1
632 # b <2> aassign[t3] KS
633 # c <1> leavesub[1 ref] K/REFC,1
639 # chunk: # guarantee stability, regardless of algorithm
641 @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;
645 checkOptree(note => q{},
647 code => q{use sort 'stable'; @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old; },
648 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
649 # 1 <;> nextstate(main 656 (eval 40):1) v
653 # 5 <1> rv2av[t9] lK/1
657 # 9 <1> rv2av[t2] lKRM*/1
658 # a <2> aassign[t14] KS
659 # b <1> leavesub[1 ref] K/REFC,1
661 # 1 <;> nextstate(main 578 (eval 15):1) v
665 # 5 <1> rv2av[t5] lK/1
669 # 9 <1> rv2av[t1] lKRM*/1
670 # a <2> aassign[t6] KS
671 # b <1> leavesub[1 ref] K/REFC,1
677 # chunk: # force use of mergesort (not portable outside Perl 5.8)
678 use sort '_mergesort';
679 @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;
683 checkOptree(note => q{},
685 code => q{use sort '_mergesort'; @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old; },
686 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
687 # 1 <;> nextstate(main 662 (eval 42):1) v
691 # 5 <1> rv2av[t9] lK/1
695 # 9 <1> rv2av[t2] lKRM*/1
696 # a <2> aassign[t14] KS
697 # b <1> leavesub[1 ref] K/REFC,1
699 # 1 <;> nextstate(main 578 (eval 15):1) v
703 # 5 <1> rv2av[t5] lK/1
707 # 9 <1> rv2av[t1] lKRM*/1
708 # a <2> aassign[t6] KS
709 # b <1> leavesub[1 ref] K/REFC,1
715 # chunk: # you should have a good reason to do this!
716 @articles = sort {$FooPack::b <=> $FooPack::a} @files;
720 checkOptree(note => q{},
722 code => q{@articles = sort {$FooPack::b <=> $FooPack::a} @files; },
723 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
724 # 1 <;> nextstate(main 667 (eval 44):1) v
728 # 5 <1> rv2av[t7] lK/1
731 # 8 <#> gv[*articles] s
732 # 9 <1> rv2av[t2] lKRM*/1
733 # a <2> aassign[t8] KS
734 # b <1> leavesub[1 ref] K/REFC,1
736 # 1 <;> nextstate(main 546 (eval 15):1) v
740 # 5 <1> rv2av[t3] lK/1
743 # 8 <$> gv(*articles) s
744 # 9 <1> rv2av[t1] lKRM*/1
745 # a <2> aassign[t4] KS
746 # b <1> leavesub[1 ref] K/REFC,1
753 @result = sort { $a <=> $b } grep { $_ == $_ } @input;
757 checkOptree(note => q{},
759 code => q{@result = sort { $a <=> $b } grep { $_ == $_ } @input; },
760 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
761 # 1 <;> nextstate(main 673 (eval 46):1) v
766 # 6 <1> rv2av[t9] lKM/1
767 # 7 <@> grepstart lK*
768 # 8 <|> grepwhile(other->9)[t10] lK
776 # e <#> gv[*result] s
777 # f <1> rv2av[t2] lKRM*/1
778 # g <2> aassign[t5] KS/COMMON
779 # h <1> leavesub[1 ref] K/REFC,1
781 # 1 <;> nextstate(main 547 (eval 15):1) v
786 # 6 <1> rv2av[t3] lKM/1
787 # 7 <@> grepstart lK*
788 # 8 <|> grepwhile(other->9)[t4] lK
796 # e <$> gv(*result) s
797 # f <1> rv2av[t1] lKRM*/1
798 # g <2> aassign[t2] KS/COMMON
799 # h <1> leavesub[1 ref] K/REFC,1
805 # chunk: # void return context sort
806 sort { $a <=> $b } @input;
810 checkOptree(note => q{},
812 code => q{sort { $a <=> $b } @input; },
813 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
814 # 1 <;> nextstate(main 678 (eval 48):1) v
817 # 4 <1> rv2av[t5] lK/1
819 # 6 <1> leavesub[1 ref] K/REFC,1
821 # 1 <;> nextstate(main 546 (eval 15):1) v
824 # 4 <1> rv2av[t2] lK/1
826 # 6 <1> leavesub[1 ref] K/REFC,1
832 # chunk: # more void context, propagating ?
833 sort { $a <=> $b } grep { $_ == $_ } @input;
837 checkOptree(note => q{},
839 code => q{sort { $a <=> $b } grep { $_ == $_ } @input; },
840 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
841 # 1 <;> nextstate(main 684 (eval 50):1) v
845 # 5 <1> rv2av[t7] lKM/1
846 # 6 <@> grepstart lK*
847 # 7 <|> grepwhile(other->8)[t8] lK
854 # c <1> leavesub[1 ref] K/REFC,1
856 # 1 <;> nextstate(main 547 (eval 15):1) v
860 # 5 <1> rv2av[t2] lKM/1
861 # 6 <@> grepstart lK*
862 # 7 <|> grepwhile(other->8)[t3] lK
869 # c <1> leavesub[1 ref] K/REFC,1
875 # chunk: # scalar return context sort
876 $s = sort { $a <=> $b } @input;
880 checkOptree(note => q{},
882 code => q{$s = sort { $a <=> $b } @input; },
883 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
884 # 1 <;> nextstate(main 689 (eval 52):1) v
887 # 4 <1> rv2av[t6] lK/1
890 # 7 <2> sassign sKS/2
891 # 8 <1> leavesub[1 ref] K/REFC,1
893 # 1 <;> nextstate(main 546 (eval 15):1) v
896 # 4 <1> rv2av[t2] lK/1
899 # 7 <2> sassign sKS/2
900 # 8 <1> leavesub[1 ref] K/REFC,1
906 # chunk: $s = sort { $a <=> $b } grep { $_ == $_ } @input;
910 checkOptree(note => q{},
912 code => q{$s = sort { $a <=> $b } grep { $_ == $_ } @input; },
913 expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
914 # 1 <;> nextstate(main 695 (eval 54):1) v
918 # 5 <1> rv2av[t8] lKM/1
919 # 6 <@> grepstart lK*
920 # 7 <|> grepwhile(other->8)[t9] lK
928 # d <2> sassign sKS/2
929 # e <1> leavesub[1 ref] K/REFC,1
931 # 1 <;> nextstate(main 547 (eval 15):1) v
935 # 5 <1> rv2av[t2] lKM/1
936 # 6 <@> grepstart lK*
937 # 7 <|> grepwhile(other->8)[t3] lK
945 # d <2> sassign sKS/2
946 # e <1> leavesub[1 ref] K/REFC,1