This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
ca58619bf221474d1e21fc68e7104032ba5c1ed4
[perl5.git] / lib / overload.t
1 #!./perl
2
3 BEGIN {
4     chdir 't' if -d 't';
5     @INC = '../lib';
6     require Config;
7     if (($Config::Config{'extensions'} !~ m!\bList/Util\b!) ){
8         print "1..0 # Skip -- Perl configured without List::Util module\n";
9         exit 0;
10     }
11 }
12
13 package Oscalar;
14 use overload ( 
15                                 # Anonymous subroutines:
16 '+'     =>      sub {new Oscalar $ {$_[0]}+$_[1]},
17 '-'     =>      sub {new Oscalar
18                        $_[2]? $_[1]-${$_[0]} : ${$_[0]}-$_[1]},
19 '<=>'   =>      sub {new Oscalar
20                        $_[2]? $_[1]-${$_[0]} : ${$_[0]}-$_[1]},
21 'cmp'   =>      sub {new Oscalar
22                        $_[2]? ($_[1] cmp ${$_[0]}) : (${$_[0]} cmp $_[1])},
23 '*'     =>      sub {new Oscalar ${$_[0]}*$_[1]},
24 '/'     =>      sub {new Oscalar 
25                        $_[2]? $_[1]/${$_[0]} :
26                          ${$_[0]}/$_[1]},
27 '%'     =>      sub {new Oscalar
28                        $_[2]? $_[1]%${$_[0]} : ${$_[0]}%$_[1]},
29 '**'    =>      sub {new Oscalar
30                        $_[2]? $_[1]**${$_[0]} : ${$_[0]}-$_[1]},
31
32 qw(
33 ""      stringify
34 0+      numify)                 # Order of arguments insignificant
35 );
36
37 sub new {
38   my $foo = $_[1];
39   bless \$foo, $_[0];
40 }
41
42 sub stringify { "${$_[0]}" }
43 sub numify { 0 + "${$_[0]}" }   # Not needed, additional overhead
44                                 # comparing to direct compilation based on
45                                 # stringify
46
47 package main;
48
49 $| = 1;
50 use Test::More tests => 1970;
51
52
53 $a = new Oscalar "087";
54 $b= "$a";
55
56 is($b, $a);
57 is($b, "087");
58 is(ref $a, "Oscalar");
59 is($a, $a);
60 is($a, "087");
61
62 $c = $a + 7;
63
64 is(ref $c, "Oscalar");
65 isnt($c, $a);
66 is($c, "94");
67
68 $b=$a;
69
70 is(ref $a, "Oscalar");
71
72 $b++;
73
74 is(ref $b, "Oscalar");
75 is($a, "087");
76 is($b, "88");
77 is(ref $a, "Oscalar");
78
79 $c=$b;
80 $c-=$a;
81
82 is(ref $c, "Oscalar");
83 is($a, "087");
84 is($c, "1");
85 is(ref $a, "Oscalar");
86
87 $b=1;
88 $b+=$a;
89
90 is(ref $b, "Oscalar");
91 is($a, "087");
92 is($b, "88");
93 is(ref $a, "Oscalar");
94
95 eval q[ package Oscalar; use overload ('++' => sub { $ {$_[0]}++;$_[0] } ) ];
96
97 $b=$a;
98
99 is(ref $a, "Oscalar");
100
101 $b++;
102
103 is(ref $b, "Oscalar");
104 is($a, "087");
105 is($b, "88");
106 is(ref $a, "Oscalar");
107
108 package Oscalar;
109 $dummy=bless \$dummy;           # Now cache of method should be reloaded
110 package main;
111
112 $b=$a;
113 $b++;                           
114
115 is(ref $b, "Oscalar");
116 is($a, "087");
117 is($b, "88");
118 is(ref $a, "Oscalar");
119
120 undef $b;                       # Destroying updates tables too...
121
122 eval q[package Oscalar; use overload ('++' => sub { $ {$_[0]} += 2; $_[0] } ) ];
123
124 $b=$a;
125
126 is(ref $a, "Oscalar");
127
128 $b++;
129
130 is(ref $b, "Oscalar");
131 is($a, "087");
132 is($b, "88");
133 is(ref $a, "Oscalar");
134
135 package Oscalar;
136 $dummy=bless \$dummy;           # Now cache of method should be reloaded
137 package main;
138
139 $b++;                           
140
141 is(ref $b, "Oscalar");
142 is($a, "087");
143 is($b, "90");
144 is(ref $a, "Oscalar");
145
146 $b=$a;
147 $b++;
148
149 is(ref $b, "Oscalar");
150 is($a, "087");
151 is($b, "89");
152 is(ref $a, "Oscalar");
153
154
155 ok($b? 1:0);
156
157 eval q[ package Oscalar; use overload ('=' => sub {$main::copies++; 
158                                                    package Oscalar;
159                                                    local $new=$ {$_[0]};
160                                                    bless \$new } ) ];
161
162 $b=new Oscalar "$a";
163
164 is(ref $b, "Oscalar");
165 is($a, "087");
166 is($b, "087");
167 is(ref $a, "Oscalar");
168
169 $b++;
170
171 is(ref $b, "Oscalar");
172 is($a, "087");
173 is($b, "89");
174 is(ref $a, "Oscalar");
175 is($copies, undef);
176
177 $b+=1;
178
179 is(ref $b, "Oscalar");
180 is($a, "087");
181 is($b, "90");
182 is(ref $a, "Oscalar");
183 is($copies, undef);
184
185 $b=$a;
186 $b+=1;
187
188 is(ref $b, "Oscalar");
189 is($a, "087");
190 is($b, "88");
191 is(ref $a, "Oscalar");
192 is($copies, undef);
193
194 $b=$a;
195 $b++;
196
197 is(ref $b, "Oscalar");
198 is($a, "087");
199 is($b, "89");
200 is(ref $a, "Oscalar");
201 is($copies, 1);
202
203 eval q[package Oscalar; use overload ('+=' => sub {$ {$_[0]} += 3*$_[1];
204                                                    $_[0] } ) ];
205 $c=new Oscalar;                 # Cause rehash
206
207 $b=$a;
208 $b+=1;
209
210 is(ref $b, "Oscalar");
211 is($a, "087");
212 is($b, "90");
213 is(ref $a, "Oscalar");
214 is($copies, 2);
215
216 $b+=$b;
217
218 is(ref $b, "Oscalar");
219 is($b, "360");
220 is($copies, 2);
221 $b=-$b;
222
223 is(ref $b, "Oscalar");
224 is($b, "-360");
225 is($copies, 2);
226
227 $b=abs($b);
228
229 is(ref $b, "Oscalar");
230 is($b, "360");
231 is($copies, 2);
232
233 $b=abs($b);
234
235 is(ref $b, "Oscalar");
236 is($b, "360");
237 is($copies, 2);
238
239 eval q[package Oscalar; 
240        use overload ('x' => sub {new Oscalar ( $_[2] ? "_.$_[1]._" x $ {$_[0]}
241                                               : "_.${$_[0]}._" x $_[1])}) ];
242
243 $a=new Oscalar "yy";
244 $a x= 3;
245 is($a, "_.yy.__.yy.__.yy._");
246
247 eval q[package Oscalar; 
248        use overload ('.' => sub {new Oscalar ( $_[2] ? 
249                                               "_.$_[1].__.$ {$_[0]}._"
250                                               : "_.$ {$_[0]}.__.$_[1]._")}) ];
251
252 $a=new Oscalar "xx";
253
254 is("b${a}c", "_._.b.__.xx._.__.c._");
255
256 # Check inheritance of overloading;
257 {
258   package OscalarI;
259   @ISA = 'Oscalar';
260 }
261
262 $aI = new OscalarI "$a";
263 is(ref $aI, "OscalarI");
264 is("$aI", "xx");
265 is($aI, "xx");
266 is("b${aI}c", "_._.b.__.xx._.__.c._");
267
268 # Here we test blessing to a package updates hash
269
270 eval "package Oscalar; no overload '.'";
271
272 is("b${a}", "_.b.__.xx._");
273 $x="1";
274 bless \$x, Oscalar;
275 is("b${a}c", "bxxc");
276 new Oscalar 1;
277 is("b${a}c", "bxxc");
278
279 # Negative overloading:
280
281 $na = eval { ~$a };
282 like($@, qr/no method found/);
283
284 # Check AUTOLOADING:
285
286 *Oscalar::AUTOLOAD = 
287   sub { *{"Oscalar::$AUTOLOAD"} = sub {"_!_" . shift() . "_!_"} ;
288         goto &{"Oscalar::$AUTOLOAD"}};
289
290 eval "package Oscalar; sub comple; use overload '~' => 'comple'";
291
292 $na = eval { ~$a };             # Hash was not updated
293 like($@, qr/no method found/);
294
295 bless \$x, Oscalar;
296
297 $na = eval { ~$a };             # Hash updated
298 warn "`$na', $@" if $@;
299 ok !$@;
300 is($na, '_!_xx_!_');
301
302 $na = 0;
303
304 $na = eval { ~$aI };            # Hash was not updated
305 like($@, qr/no method found/);
306
307 bless \$x, OscalarI;
308
309 $na = eval { ~$aI };
310 print $@;
311
312 ok(!$@);
313 is($na, '_!_xx_!_');
314
315 eval "package Oscalar; sub rshft; use overload '>>' => 'rshft'";
316
317 $na = eval { $aI >> 1 };        # Hash was not updated
318 like($@, qr/no method found/);
319
320 bless \$x, OscalarI;
321
322 $na = 0;
323
324 $na = eval { $aI >> 1 };
325 print $@;
326
327 ok(!$@);
328 is($na, '_!_xx_!_');
329
330 # warn overload::Method($a, '0+'), "\n";
331 is(overload::Method($a, '0+'), \&Oscalar::numify);
332 is(overload::Method($aI,'0+'), \&Oscalar::numify);
333 ok(overload::Overloaded($aI));
334 ok(!overload::Overloaded('overload'));
335
336 ok(! defined overload::Method($aI, '<<'));
337 ok(! defined overload::Method($a, '<'));
338
339 like (overload::StrVal($aI), qr/^OscalarI=SCALAR\(0x[\da-fA-F]+\)$/);
340 is(overload::StrVal(\$aI), "@{[\$aI]}");
341
342 # Check overloading by methods (specified deep in the ISA tree).
343 {
344   package OscalarII;
345   @ISA = 'OscalarI';
346   sub Oscalar::lshft {"_<<_" . shift() . "_<<_"}
347   eval "package OscalarI; use overload '<<' => 'lshft', '|' => 'lshft'";
348 }
349
350 $aaII = "087";
351 $aII = \$aaII;
352 bless $aII, 'OscalarII';
353 bless \$fake, 'OscalarI';               # update the hash
354 is(($aI | 3), '_<<_xx_<<_');
355 # warn $aII << 3;
356 is(($aII << 3), '_<<_087_<<_');
357
358 {
359   BEGIN { $int = 7; overload::constant 'integer' => sub {$int++; shift}; }
360   $out = 2**10;
361 }
362 is($int, 9);
363 is($out, 1024);
364 is($int, 9);
365 {
366   BEGIN { overload::constant 'integer' => sub {$int++; shift()+1}; }
367   eval q{$out = 42};
368 }
369 is($int, 10);
370 is($out, 43);
371
372 $foo = 'foo';
373 $foo1 = 'f\'o\\o';
374 {
375   BEGIN { $q = $qr = 7; 
376           overload::constant 'q' => sub {$q++; push @q, shift, ($_[1] || 'none'); shift},
377                              'qr' => sub {$qr++; push @qr, shift, ($_[1] || 'none'); shift}; }
378   $out = 'foo';
379   $out1 = 'f\'o\\o';
380   $out2 = "a\a$foo,\,";
381   /b\b$foo.\./;
382 }
383
384 is($out, 'foo');
385 is($out, $foo);
386 is($out1, 'f\'o\\o');
387 is($out1, $foo1);
388 is($out2, "a\afoo,\,");
389 is("@q", "foo q f'o\\\\o q a\\a qq ,\\, qq");
390 is($q, 11);
391 is("@qr", "b\\b qq .\\. qq");
392 is($qr, 9);
393
394 {
395   $_ = '!<b>!foo!<-.>!';
396   BEGIN { overload::constant 'q' => sub {push @q1, shift, ($_[1] || 'none'); "_<" . (shift) . ">_"},
397                              'qr' => sub {push @qr1, shift, ($_[1] || 'none'); "!<" . (shift) . ">!"}; }
398   $out = 'foo';
399   $out1 = 'f\'o\\o';
400   $out2 = "a\a$foo,\,";
401   $res = /b\b$foo.\./;
402   $a = <<EOF;
403 oups
404 EOF
405   $b = <<'EOF';
406 oups1
407 EOF
408   $c = bareword;
409   m'try it';
410   s'first part'second part';
411   s/yet another/tail here/;
412   tr/A-Z/a-z/;
413 }
414
415 is($out, '_<foo>_');
416 is($out1, '_<f\'o\\o>_');
417 is($out2, "_<a\a>_foo_<,\,>_");
418 is("@q1", "foo q f'o\\\\o q a\\a qq ,\\, qq oups
419  qq oups1
420  q second part q tail here s A-Z tr a-z tr");
421 is("@qr1", "b\\b qq .\\. qq try it q first part q yet another qq");
422 is($res, 1);
423 is($a, "_<oups
424 >_");
425 is($b, "_<oups1
426 >_");
427 is($c, "bareword");
428
429 {
430   package symbolic;             # Primitive symbolic calculator
431   use overload nomethod => \&wrap, '""' => \&str, '0+' => \&num,
432       '=' => \&cpy, '++' => \&inc, '--' => \&dec;
433
434   sub new { shift; bless ['n', @_] }
435   sub cpy {
436     my $self = shift;
437     bless [@$self], ref $self;
438   }
439   sub inc { $_[0] = bless ['++', $_[0], 1]; }
440   sub dec { $_[0] = bless ['--', $_[0], 1]; }
441   sub wrap {
442     my ($obj, $other, $inv, $meth) = @_;
443     if ($meth eq '++' or $meth eq '--') {
444       @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference
445       return $obj;
446     }
447     ($obj, $other) = ($other, $obj) if $inv;
448     bless [$meth, $obj, $other];
449   }
450   sub str {
451     my ($meth, $a, $b) = @{+shift};
452     $a = 'u' unless defined $a;
453     if (defined $b) {
454       "[$meth $a $b]";
455     } else {
456       "[$meth $a]";
457     }
458   } 
459   my %subr = ( 'n' => sub {$_[0]} );
460   foreach my $op (split " ", $overload::ops{with_assign}) {
461     $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
462   }
463   my @bins = qw(binary 3way_comparison num_comparison str_comparison);
464   foreach my $op (split " ", "@overload::ops{ @bins }") {
465     $subr{$op} = eval "sub {shift() $op shift()}";
466   }
467   foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
468     $subr{$op} = eval "sub {$op shift()}";
469   }
470   $subr{'++'} = $subr{'+'};
471   $subr{'--'} = $subr{'-'};
472   
473   sub num {
474     my ($meth, $a, $b) = @{+shift};
475     my $subr = $subr{$meth} 
476       or die "Do not know how to ($meth) in symbolic";
477     $a = $a->num if ref $a eq __PACKAGE__;
478     $b = $b->num if ref $b eq __PACKAGE__;
479     $subr->($a,$b);
480   }
481   sub TIESCALAR { my $pack = shift; $pack->new(@_) }
482   sub FETCH { shift }
483   sub nop {  }          # Around a bug
484   sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; }
485   sub STORE { 
486     my $obj = shift; 
487     $#$obj = 1; 
488     $obj->[1] = shift;
489   }
490 }
491
492 {
493   my $foo = new symbolic 11;
494   my $baz = $foo++;
495   is((sprintf "%d", $foo), '12');
496   is((sprintf "%d", $baz), '11');
497   my $bar = $foo;
498   $baz = ++$foo;
499   is((sprintf "%d", $foo), '13');
500   is((sprintf "%d", $bar), '12');
501   is((sprintf "%d", $baz), '13');
502   my $ban = $foo;
503   $baz = ($foo += 1);
504   is((sprintf "%d", $foo), '14');
505   is((sprintf "%d", $bar), '12');
506   is((sprintf "%d", $baz), '14');
507   is((sprintf "%d", $ban), '13');
508   $baz = 0;
509   $baz = $foo++;
510   is((sprintf "%d", $foo), '15');
511   is((sprintf "%d", $baz), '14');
512   is("$foo", '[++ [+= [++ [++ [n 11] 1] 1] 1] 1]');
513 }
514
515 {
516   my $iter = new symbolic 2;
517   my $side = new symbolic 1;
518   my $cnt = $iter;
519   
520   while ($cnt) {
521     $cnt = $cnt - 1;            # The "simple" way
522     $side = (sqrt(1 + $side**2) - 1)/$side;
523   }
524   my $pi = $side*(2**($iter+2));
525   is("$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]');
526   is((sprintf "%f", $pi), '3.182598');
527 }
528
529 {
530   my $iter = new symbolic 2;
531   my $side = new symbolic 1;
532   my $cnt = $iter;
533   
534   while ($cnt--) {
535     $side = (sqrt(1 + $side**2) - 1)/$side;
536   }
537   my $pi = $side*(2**($iter+2));
538   is("$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]');
539   is((sprintf "%f", $pi), '3.182598');
540 }
541
542 {
543   my ($a, $b);
544   symbolic->vars($a, $b);
545   my $c = sqrt($a**2 + $b**2);
546   $a = 3; $b = 4;
547   is((sprintf "%d", $c), '5');
548   $a = 12; $b = 5;
549   is((sprintf "%d", $c), '13');
550 }
551
552 {
553   package symbolic1;            # Primitive symbolic calculator
554   # Mutator inc/dec
555   use overload nomethod => \&wrap, '""' => \&str, '0+' => \&num, '=' => \&cpy;
556
557   sub new { shift; bless ['n', @_] }
558   sub cpy {
559     my $self = shift;
560     bless [@$self], ref $self;
561   }
562   sub wrap {
563     my ($obj, $other, $inv, $meth) = @_;
564     if ($meth eq '++' or $meth eq '--') {
565       @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference
566       return $obj;
567     }
568     ($obj, $other) = ($other, $obj) if $inv;
569     bless [$meth, $obj, $other];
570   }
571   sub str {
572     my ($meth, $a, $b) = @{+shift};
573     $a = 'u' unless defined $a;
574     if (defined $b) {
575       "[$meth $a $b]";
576     } else {
577       "[$meth $a]";
578     }
579   } 
580   my %subr = ( 'n' => sub {$_[0]} );
581   foreach my $op (split " ", $overload::ops{with_assign}) {
582     $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
583   }
584   my @bins = qw(binary 3way_comparison num_comparison str_comparison);
585   foreach my $op (split " ", "@overload::ops{ @bins }") {
586     $subr{$op} = eval "sub {shift() $op shift()}";
587   }
588   foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
589     $subr{$op} = eval "sub {$op shift()}";
590   }
591   $subr{'++'} = $subr{'+'};
592   $subr{'--'} = $subr{'-'};
593   
594   sub num {
595     my ($meth, $a, $b) = @{+shift};
596     my $subr = $subr{$meth} 
597       or die "Do not know how to ($meth) in symbolic";
598     $a = $a->num if ref $a eq __PACKAGE__;
599     $b = $b->num if ref $b eq __PACKAGE__;
600     $subr->($a,$b);
601   }
602   sub TIESCALAR { my $pack = shift; $pack->new(@_) }
603   sub FETCH { shift }
604   sub nop {  }          # Around a bug
605   sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; }
606   sub STORE { 
607     my $obj = shift; 
608     $#$obj = 1; 
609     $obj->[1] = shift;
610   }
611 }
612
613 {
614   my $foo = new symbolic1 11;
615   my $baz = $foo++;
616   is((sprintf "%d", $foo), '12');
617   is((sprintf "%d", $baz), '11');
618   my $bar = $foo;
619   $baz = ++$foo;
620   is((sprintf "%d", $foo), '13');
621   is((sprintf "%d", $bar), '12');
622   is((sprintf "%d", $baz), '13');
623   my $ban = $foo;
624   $baz = ($foo += 1);
625   is((sprintf "%d", $foo), '14');
626   is((sprintf "%d", $bar), '12');
627   is((sprintf "%d", $baz), '14');
628   is((sprintf "%d", $ban), '13');
629   $baz = 0;
630   $baz = $foo++;
631   is((sprintf "%d", $foo), '15');
632   is((sprintf "%d", $baz), '14');
633   is("$foo", '[++ [+= [++ [++ [n 11] 1] 1] 1] 1]');
634 }
635
636 {
637   my $iter = new symbolic1 2;
638   my $side = new symbolic1 1;
639   my $cnt = $iter;
640   
641   while ($cnt) {
642     $cnt = $cnt - 1;            # The "simple" way
643     $side = (sqrt(1 + $side**2) - 1)/$side;
644   }
645   my $pi = $side*(2**($iter+2));
646   is("$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]');
647   is((sprintf "%f", $pi), '3.182598');
648 }
649
650 {
651   my $iter = new symbolic1 2;
652   my $side = new symbolic1 1;
653   my $cnt = $iter;
654   
655   while ($cnt--) {
656     $side = (sqrt(1 + $side**2) - 1)/$side;
657   }
658   my $pi = $side*(2**($iter+2));
659   is("$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]');
660   is((sprintf "%f", $pi), '3.182598');
661 }
662
663 {
664   my ($a, $b);
665   symbolic1->vars($a, $b);
666   my $c = sqrt($a**2 + $b**2);
667   $a = 3; $b = 4;
668   is((sprintf "%d", $c), '5');
669   $a = 12; $b = 5;
670   is((sprintf "%d", $c), '13');
671 }
672
673 {
674   package two_face;             # Scalars with separate string and
675                                 # numeric values.
676   sub new { my $p = shift; bless [@_], $p }
677   use overload '""' => \&str, '0+' => \&num, fallback => 1;
678   sub num {shift->[1]}
679   sub str {shift->[0]}
680 }
681
682 {
683   my $seven = new two_face ("vii", 7);
684   is((sprintf "seven=$seven, seven=%d, eight=%d", $seven, $seven+1),
685         'seven=vii, seven=7, eight=8');
686   is(scalar ($seven =~ /i/), '1');
687 }
688
689 {
690   package sorting;
691   use overload 'cmp' => \&comp;
692   sub new { my ($p, $v) = @_; bless \$v, $p }
693   sub comp { my ($x,$y) = @_; ($$x * 3 % 10) <=> ($$y * 3 % 10) or $$x cmp $$y }
694 }
695 {
696   my @arr = map sorting->new($_), 0..12;
697   my @sorted1 = sort @arr;
698   my @sorted2 = map $$_, @sorted1;
699   is("@sorted2", '0 10 7 4 1 11 8 5 12 2 9 6 3');
700 }
701 {
702   package iterator;
703   use overload '<>' => \&iter;
704   sub new { my ($p, $v) = @_; bless \$v, $p }
705   sub iter { my ($x) = @_; return undef if $$x < 0; return $$x--; }
706 }
707
708 # XXX iterator overload not intended to work with CORE::GLOBAL?
709 if (defined &CORE::GLOBAL::glob) {
710   is('1', '1');
711   is('1', '1');
712   is('1', '1');
713 }
714 else {
715   my $iter = iterator->new(5);
716   my $acc = '';
717   my $out;
718   $acc .= " $out" while $out = <${iter}>;
719   is($acc, ' 5 4 3 2 1 0');
720   $iter = iterator->new(5);
721   is(scalar <${iter}>, '5');
722   $acc = '';
723   $acc .= " $out" while $out = <$iter>;
724   is($acc, ' 4 3 2 1 0');
725 }
726 {
727   package deref;
728   use overload '%{}' => \&hderef, '&{}' => \&cderef, 
729     '*{}' => \&gderef, '${}' => \&sderef, '@{}' => \&aderef;
730   sub new { my ($p, $v) = @_; bless \$v, $p }
731   sub deref {
732     my ($self, $key) = (shift, shift);
733     my $class = ref $self;
734     bless $self, 'deref::dummy'; # Disable overloading of %{} 
735     my $out = $self->{$key};
736     bless $self, $class;        # Restore overloading
737     $out;
738   }
739   sub hderef {shift->deref('h')}
740   sub aderef {shift->deref('a')}
741   sub cderef {shift->deref('c')}
742   sub gderef {shift->deref('g')}
743   sub sderef {shift->deref('s')}
744 }
745 {
746   my $deref = bless { h => { foo => 5 , fake => 23 },
747                       c => sub {return shift() + 34},
748                       's' => \123,
749                       a => [11..13],
750                       g => \*srt,
751                     }, 'deref';
752   # Hash:
753   my @cont = sort %$deref;
754   if ("\t" eq "\011") { # ASCII
755       is("@cont", '23 5 fake foo');
756   } 
757   else {                # EBCDIC alpha-numeric sort order
758       is("@cont", 'fake foo 23 5');
759   }
760   my @keys = sort keys %$deref;
761   is("@keys", 'fake foo');
762   my @val = sort values %$deref;
763   is("@val", '23 5');
764   is($deref->{foo}, 5);
765   is(defined $deref->{bar}, '');
766   my $key;
767   @keys = ();
768   push @keys, $key while $key = each %$deref;
769   @keys = sort @keys;
770   is("@keys", 'fake foo');
771   is(exists $deref->{bar}, '');
772   is(exists $deref->{foo}, 1);
773   # Code:
774   is($deref->(5), 39);
775   is(&$deref(6), 40);
776   sub xxx_goto { goto &$deref }
777   is(xxx_goto(7), 41);
778   my $srt = bless { c => sub {$b <=> $a}
779                   }, 'deref';
780   *srt = \&$srt;
781   my @sorted = sort srt 11, 2, 5, 1, 22;
782   is("@sorted", '22 11 5 2 1');
783   # Scalar
784   is($$deref, 123);
785   # Code
786   @sorted = sort $srt 11, 2, 5, 1, 22;
787   is("@sorted", '22 11 5 2 1');
788   # Array
789   is("@$deref", '11 12 13');
790   is($#$deref, '2');
791   my $l = @$deref;
792   is($l, 3);
793   is($deref->[2], '13');
794   $l = pop @$deref;
795   is($l, 13);
796   $l = 1;
797   is($deref->[$l], '12');
798   # Repeated dereference
799   my $double = bless { h => $deref,
800                      }, 'deref';
801   is($double->{foo}, 5);
802 }
803
804 {
805   package two_refs;
806   use overload '%{}' => \&gethash, '@{}' => sub { ${shift()} };
807   sub new { 
808     my $p = shift; 
809     bless \ [@_], $p;
810   }
811   sub gethash {
812     my %h;
813     my $self = shift;
814     tie %h, ref $self, $self;
815     \%h;
816   }
817
818   sub TIEHASH { my $p = shift; bless \ shift, $p }
819   my %fields;
820   my $i = 0;
821   $fields{$_} = $i++ foreach qw{zero one two three};
822   sub STORE { 
823     my $self = ${shift()};
824     my $key = $fields{shift()};
825     defined $key or die "Out of band access";
826     $$self->[$key] = shift;
827   }
828   sub FETCH { 
829     my $self = ${shift()};
830     my $key = $fields{shift()};
831     defined $key or die "Out of band access";
832     $$self->[$key];
833   }
834 }
835
836 my $bar = new two_refs 3,4,5,6;
837 $bar->[2] = 11;
838 is($bar->{two}, 11);
839 $bar->{three} = 13;
840 is($bar->[3], 13);
841
842 {
843   package two_refs_o;
844   @ISA = ('two_refs');
845 }
846
847 $bar = new two_refs_o 3,4,5,6;
848 $bar->[2] = 11;
849 is($bar->{two}, 11);
850 $bar->{three} = 13;
851 is($bar->[3], 13);
852
853 {
854   package two_refs1;
855   use overload '%{}' => sub { ${shift()}->[1] },
856                '@{}' => sub { ${shift()}->[0] };
857   sub new { 
858     my $p = shift; 
859     my $a = [@_];
860     my %h;
861     tie %h, $p, $a;
862     bless \ [$a, \%h], $p;
863   }
864   sub gethash {
865     my %h;
866     my $self = shift;
867     tie %h, ref $self, $self;
868     \%h;
869   }
870
871   sub TIEHASH { my $p = shift; bless \ shift, $p }
872   my %fields;
873   my $i = 0;
874   $fields{$_} = $i++ foreach qw{zero one two three};
875   sub STORE { 
876     my $a = ${shift()};
877     my $key = $fields{shift()};
878     defined $key or die "Out of band access";
879     $a->[$key] = shift;
880   }
881   sub FETCH { 
882     my $a = ${shift()};
883     my $key = $fields{shift()};
884     defined $key or die "Out of band access";
885     $a->[$key];
886   }
887 }
888
889 $bar = new two_refs_o 3,4,5,6;
890 $bar->[2] = 11;
891 is($bar->{two}, 11);
892 $bar->{three} = 13;
893 is($bar->[3], 13);
894
895 {
896   package two_refs1_o;
897   @ISA = ('two_refs1');
898 }
899
900 $bar = new two_refs1_o 3,4,5,6;
901 $bar->[2] = 11;
902 is($bar->{two}, 11);
903 $bar->{three} = 13;
904 is($bar->[3], 13);
905
906 {
907   package B;
908   use overload bool => sub { ${+shift} };
909 }
910
911 my $aaa;
912 { my $bbbb = 0; $aaa = bless \$bbbb, B }
913
914 is !$aaa, 1;
915
916 unless ($aaa) {
917   pass();
918 } else {
919   fail();
920 }
921
922 # check that overload isn't done twice by join
923 { my $c = 0;
924   package Join;
925   use overload '""' => sub { $c++ };
926   my $x = join '', bless([]), 'pq', bless([]);
927   main::is $x, '0pq1';
928 };
929
930 # Test module-specific warning
931 {
932     # check the Odd number of arguments for overload::constant warning
933     my $a = "" ;
934     local $SIG{__WARN__} = sub {$a = $_[0]} ;
935     $x = eval ' overload::constant "integer" ; ' ;
936     is($a, "");
937     use warnings 'overload' ;
938     $x = eval ' overload::constant "integer" ; ' ;
939     like($a, qr/^Odd number of arguments for overload::constant at/);
940 }
941
942 {
943     # check the `$_[0]' is not an overloadable type warning
944     my $a = "" ;
945     local $SIG{__WARN__} = sub {$a = $_[0]} ;
946     $x = eval ' overload::constant "fred" => sub {} ; ' ;
947     is($a, "");
948     use warnings 'overload' ;
949     $x = eval ' overload::constant "fred" => sub {} ; ' ;
950     like($a, qr/^`fred' is not an overloadable type at/);
951 }
952
953 {
954     # check the `$_[1]' is not a code reference warning
955     my $a = "" ;
956     local $SIG{__WARN__} = sub {$a = $_[0]} ;
957     $x = eval ' overload::constant "integer" => 1; ' ;
958     is($a, "");
959     use warnings 'overload' ;
960     $x = eval ' overload::constant "integer" => 1; ' ;
961     like($a, qr/^`1' is not a code reference at/);
962 }
963
964 {
965   my $c = 0;
966   package ov_int1;
967   use overload '""'    => sub { 3+shift->[0] },
968                '0+'    => sub { 10+shift->[0] },
969                'int'   => sub { 100+shift->[0] };
970   sub new {my $p = shift; bless [shift], $p}
971
972   package ov_int2;
973   use overload '""'    => sub { 5+shift->[0] },
974                '0+'    => sub { 30+shift->[0] },
975                'int'   => sub { 'ov_int1'->new(1000+shift->[0]) };
976   sub new {my $p = shift; bless [shift], $p}
977
978   package noov_int;
979   use overload '""'    => sub { 2+shift->[0] },
980                '0+'    => sub { 9+shift->[0] };
981   sub new {my $p = shift; bless [shift], $p}
982
983   package main;
984
985   my $x = new noov_int 11;
986   my $int_x = int $x;
987   main::is("$int_x", 20);
988   $x = new ov_int1 31;
989   $int_x = int $x;
990   main::is("$int_x", 131);
991   $x = new ov_int2 51;
992   $int_x = int $x;
993   main::is("$int_x", 1054);
994 }
995
996 # make sure that we don't infinitely recurse
997 {
998   my $c = 0;
999   package Recurse;
1000   use overload '""'    => sub { shift },
1001                '0+'    => sub { shift },
1002                'bool'  => sub { shift },
1003                fallback => 1;
1004   my $x = bless([]);
1005   # For some reason beyond me these have to be oks rather than likes.
1006   main::ok("$x" =~ /Recurse=ARRAY/);
1007   main::ok($x);
1008   main::ok($x+0 =~ qr/Recurse=ARRAY/);
1009 }
1010
1011 # BugID 20010422.003
1012 package Foo;
1013
1014 use overload
1015   'bool' => sub { return !$_[0]->is_zero() || undef; }
1016 ;
1017  
1018 sub is_zero
1019   {
1020   my $self = shift;
1021   return $self->{var} == 0;
1022   }
1023
1024 sub new
1025   {
1026   my $class = shift;
1027   my $self =  {};
1028   $self->{var} = shift;
1029   bless $self,$class;
1030   }
1031
1032 package main;
1033
1034 use strict;
1035
1036 my $r = Foo->new(8);
1037 $r = Foo->new(0);
1038
1039 is(($r || 0), 0);
1040
1041 package utf8_o;
1042
1043 use overload 
1044   '""'  =>  sub { return $_[0]->{var}; }
1045   ;
1046   
1047 sub new
1048   {
1049     my $class = shift;
1050     my $self =  {};
1051     $self->{var} = shift;
1052     bless $self,$class;
1053   }
1054
1055 package main;
1056
1057
1058 my $utfvar = new utf8_o 200.2.1;
1059 is("$utfvar", 200.2.1); # 223 - stringify
1060 is("a$utfvar", "a".200.2.1); # 224 - overload via sv_2pv_flags
1061
1062 # 225..227 -- more %{} tests.  Hangs in 5.6.0, okay in later releases.
1063 # Basically this example implements strong encapsulation: if Hderef::import()
1064 # were to eval the overload code in the caller's namespace, the privatisation
1065 # would be quite transparent.
1066 package Hderef;
1067 use overload '%{}' => sub { (caller(0))[0] eq 'Foo' ? $_[0] : die "zap" };
1068 package Foo;
1069 @Foo::ISA = 'Hderef';
1070 sub new { bless {}, shift }
1071 sub xet { @_ == 2 ? $_[0]->{$_[1]} :
1072           @_ == 3 ? ($_[0]->{$_[1]} = $_[2]) : undef }
1073 package main;
1074 my $a = Foo->new;
1075 $a->xet('b', 42);
1076 is ($a->xet('b'), 42);
1077 ok (!defined eval { $a->{b} });
1078 like ($@, qr/zap/);
1079
1080 {
1081    package t229;
1082    use overload '='  => sub { 42 },
1083                 '++' => sub { my $x = ${$_[0]}; $_[0] };
1084    sub new { my $x = 42; bless \$x }
1085
1086    my $warn;
1087    {  
1088      local $SIG{__WARN__} = sub { $warn++ };
1089       my $x = t229->new;
1090       my $y = $x;
1091       eval { $y++ };
1092    }
1093    main::ok (!$warn);
1094 }
1095
1096 {
1097     my ($int, $out1, $out2);
1098     {
1099         BEGIN { $int = 0; overload::constant 'integer' => sub {$int++; 17}; }
1100         $out1 = 0;
1101         $out2 = 1;
1102     }
1103     is($int,  2,  "#24313");    # 230
1104     is($out1, 17, "#24313");    # 231
1105     is($out2, 17, "#24313");    # 232
1106 }
1107
1108 {
1109     package Numify;
1110     use overload (qw(0+ numify fallback 1));
1111
1112     sub new {
1113         my $val = $_[1];
1114         bless \$val, $_[0];
1115     }
1116
1117     sub numify { ${$_[0]} }
1118 }
1119
1120 {
1121     package perl31793;
1122     use overload cmp => sub { 0 };
1123     package perl31793_fb;
1124     use overload cmp => sub { 0 }, fallback => 1;
1125     package main;
1126     my $o  = bless [], 'perl31793';
1127     my $of = bless [], 'perl31793_fb';
1128     my $no = bless [], 'no_overload';
1129     like(overload::StrVal(\"scalar"), qr/^SCALAR\(0x[0-9a-f]+\)$/);
1130     like(overload::StrVal([]),        qr/^ARRAY\(0x[0-9a-f]+\)$/);
1131     like(overload::StrVal({}),        qr/^HASH\(0x[0-9a-f]+\)$/);
1132     like(overload::StrVal(sub{1}),    qr/^CODE\(0x[0-9a-f]+\)$/);
1133     like(overload::StrVal(\*GLOB),    qr/^GLOB\(0x[0-9a-f]+\)$/);
1134     like(overload::StrVal(\$o),       qr/^REF\(0x[0-9a-f]+\)$/);
1135     like(overload::StrVal(qr/a/),     qr/^Regexp=REGEXP\(0x[0-9a-f]+\)$/);
1136     like(overload::StrVal($o),        qr/^perl31793=ARRAY\(0x[0-9a-f]+\)$/);
1137     like(overload::StrVal($of),       qr/^perl31793_fb=ARRAY\(0x[0-9a-f]+\)$/);
1138     like(overload::StrVal($no),       qr/^no_overload=ARRAY\(0x[0-9a-f]+\)$/);
1139 }
1140
1141 # These are all check that overloaded values rather than reference addresses
1142 # are what is getting tested.
1143 my ($two, $one, $un, $deux) = map {new Numify $_} 2, 1, 1, 2;
1144 my ($ein, $zwei) = (1, 2);
1145
1146 my %map = (one => 1, un => 1, ein => 1, deux => 2, two => 2, zwei => 2);
1147 foreach my $op (qw(<=> == != < <= > >=)) {
1148     foreach my $l (keys %map) {
1149         foreach my $r (keys %map) {
1150             my $ocode = "\$$l $op \$$r";
1151             my $rcode = "$map{$l} $op $map{$r}";
1152
1153             my $got = eval $ocode;
1154             die if $@;
1155             my $expect = eval $rcode;
1156             die if $@;
1157             is ($got, $expect, $ocode) or print "# $rcode\n";
1158         }
1159     }
1160 }
1161 {
1162     # check that overloading works in regexes
1163     {
1164         package Foo493;
1165         use overload
1166             '""' => sub { "^$_[0][0]\$" },
1167             '.'  => sub { 
1168                     bless [
1169                              $_[2]
1170                             ? (ref $_[1] ? $_[1][0] : $_[1]) . ':' .$_[0][0] 
1171                             : $_[0][0] . ':' . (ref $_[1] ? $_[1][0] : $_[1])
1172                     ], 'Foo493'
1173                         };
1174     }
1175
1176     my $a = bless [ "a" ], 'Foo493';
1177     like('a', qr/$a/);
1178     like('x:a', qr/x$a/);
1179     like('x:a:=', qr/x$a=$/);
1180     like('x:a:a:=', qr/x$a$a=$/);
1181
1182 }
1183
1184 {
1185     {
1186         package QRonly;
1187         use overload qr => sub { qr/x/ }, fallback => 1;
1188     }
1189     {
1190         my $x = bless [], "QRonly";
1191
1192         # like tries to be too clever, and decides that $x-stringified
1193         # doesn't look like a regex
1194         ok("x" =~ $x, "qr-only matches");
1195         ok("y" !~ $x, "qr-only doesn't match what it shouldn't");
1196         ok("xx" =~ /x$x/, "qr-only matches with concat");
1197         like("$x", qr/^QRonly=ARRAY/, "qr-only doesn't have string overload");
1198
1199         my $qr = bless qr/y/, "QRonly";
1200         ok("x" =~ $qr, "qr with qr-overload uses overload");
1201         ok("y" !~ $qr, "qr with qr-overload uses overload");
1202         is("$qr", "".qr/y/, "qr with qr-overload stringify");
1203
1204         my $rx = $$qr;
1205         ok("y" =~ $rx, "bare rx with qr-overload doesn't overload match");
1206         ok("x" !~ $rx, "bare rx with qr-overload doesn't overload match");
1207         is("$rx", "".qr/y/, "bare rx with qr-overload stringify");
1208     }
1209     {
1210         package QRandSTR;
1211         use overload qr => sub { qr/x/ }, q/""/ => sub { "y" };
1212     }
1213     {
1214         my $x = bless [], "QRandSTR";
1215         ok("x" =~ $x, "qr+str uses qr for match");
1216         ok("y" !~ $x, "qr+str uses qr for match");
1217         ok("xx" =~ /x$x/, "qr+str uses qr for match with concat");
1218         is("$x", "y", "qr+str uses str for stringify");
1219
1220         my $qr = bless qr/z/, "QRandSTR";
1221         is("$qr", "y", "qr with qr+str uses str for stringify");
1222         ok("xx" =~ /x$x/, "qr with qr+str uses qr for match");
1223
1224         my $rx = $$qr;
1225         ok("z" =~ $rx, "bare rx with qr+str doesn't overload match");
1226         is("$rx", "".qr/z/, "bare rx with qr+str doesn't overload stringify");
1227     }
1228     {
1229         package QRany;
1230         use overload qr => sub { $_[0]->(@_) };
1231
1232         package QRself;
1233         use overload qr => sub { $_[0] };
1234     }
1235     {
1236         my $rx = bless sub { ${ qr/x/ } }, "QRany";
1237         ok("x" =~ $rx, "qr overload accepts a bare rx");
1238         ok("y" !~ $rx, "qr overload accepts a bare rx");
1239
1240         my $str = bless sub { "x" }, "QRany";
1241         ok(!eval { "x" =~ $str }, "qr overload doesn't accept a string");
1242         like($@, qr/^Overloaded qr did not return a REGEXP/, "correct error");
1243
1244         my $oqr = bless qr/z/, "QRandSTR";
1245         my $oqro = bless sub { $oqr }, "QRany";
1246         ok("z" =~ $oqro, "qr overload doesn't recurse");
1247
1248         my $qrs = bless qr/z/, "QRself";
1249         ok("z" =~ $qrs, "qr overload can return self");
1250     }
1251     {
1252         package STRonly;
1253         use overload q/""/ => sub { "x" };
1254
1255         package STRonlyFB;
1256         use overload q/""/ => sub { "x" }, fallback => 1;
1257     }
1258     {
1259         my $fb = bless [], "STRonlyFB";
1260         ok("x" =~ $fb, "qr falls back to \"\"");
1261         ok("y" !~ $fb, "qr falls back to \"\"");
1262
1263         my $nofb = bless [], "STRonly";
1264         ok("x" =~ $nofb, "qr falls back even without fallback");
1265         ok("y" !~ $nofb, "qr falls back even without fallback");
1266     }
1267 }
1268
1269 {
1270     my $twenty_three = 23;
1271     # Check that constant overloading propagates into evals
1272     BEGIN { overload::constant integer => sub { 23 } }
1273     is(eval "17", $twenty_three);
1274 }
1275
1276 {
1277     package Sklorsh;
1278     use overload
1279         bool     => sub { shift->is_cool };
1280
1281     sub is_cool {
1282         $_[0]->{name} eq 'cool';
1283     }
1284
1285     sub delete {
1286         undef %{$_[0]};
1287         bless $_[0], 'Brap';
1288         return 1;
1289     }
1290
1291     sub delete_with_self {
1292         my $self = shift;
1293         undef %$self;
1294         bless $self, 'Brap';
1295         return 1;
1296     }
1297
1298     package Brap;
1299
1300     1;
1301
1302     package main;
1303
1304     my $obj;
1305     $obj = bless {name => 'cool'}, 'Sklorsh';
1306     $obj->delete;
1307     ok(eval {if ($obj) {1}; 1}, $@ || 'reblessed into nonexistent namespace');
1308
1309     $obj = bless {name => 'cool'}, 'Sklorsh';
1310     $obj->delete_with_self;
1311     ok (eval {if ($obj) {1}; 1}, $@);
1312     
1313     my $a = $b = {name => 'hot'};
1314     bless $b, 'Sklorsh';
1315     is(ref $a, 'Sklorsh');
1316     is(ref $b, 'Sklorsh');
1317     ok(!$b, "Expect overloaded boolean");
1318     ok(!$a, "Expect overloaded boolean");
1319 }
1320
1321 {
1322     package Flrbbbbb;
1323     use overload
1324         bool     => sub { shift->{truth} eq 'yes' },
1325         '0+'     => sub { shift->{truth} eq 'yes' ? '1' : '0' },
1326         '!'      => sub { shift->{truth} eq 'no' },
1327         fallback => 1;
1328
1329     sub new { my $class = shift; bless { truth => shift }, $class }
1330
1331     package main;
1332
1333     my $yes = Flrbbbbb->new('yes');
1334     my $x;
1335     $x = 1 if $yes;                     is($x, 1);
1336     $x = 2 unless $yes;                 is($x, 1);
1337     $x = 3 if !$yes;                    is($x, 1);
1338     $x = 4 unless !$yes;                is($x, 4);
1339
1340     my $no = Flrbbbbb->new('no');
1341     $x = 0;
1342     $x = 1 if $no;                      is($x, 0);
1343     $x = 2 unless $no;                  is($x, 2);
1344     $x = 3 if !$no;                     is($x, 3);
1345     $x = 4 unless !$no;                 is($x, 3);
1346
1347     $x = 0;
1348     $x = 1 if !$no && $yes;             is($x, 1);
1349     $x = 2 unless !$no && $yes;         is($x, 1);
1350     $x = 3 if $no || !$yes;             is($x, 1);
1351     $x = 4 unless $no || !$yes;         is($x, 4);
1352
1353     $x = 0;
1354     $x = 1 if !$no || !$yes;            is($x, 1);
1355     $x = 2 unless !$no || !$yes;        is($x, 1);
1356     $x = 3 if !$no && !$yes;            is($x, 1);
1357     $x = 4 unless !$no && !$yes;        is($x, 4);
1358 }
1359
1360 {
1361     use Scalar::Util 'weaken';
1362
1363     package Shklitza;
1364     use overload '""' => sub {"CLiK KLAK"};
1365
1366     package Ksshfwoom;
1367
1368     package main;
1369
1370     my ($obj, $ref);
1371     $obj = bless do {my $a; \$a}, 'Shklitza';
1372     $ref = $obj;
1373
1374     is ($obj, "CLiK KLAK");
1375     is ($ref, "CLiK KLAK");
1376
1377     weaken $ref;
1378     is ($ref, "CLiK KLAK");
1379
1380     bless $obj, 'Ksshfwoom';
1381
1382     like ($obj, qr/^Ksshfwoom=/);
1383     like ($ref, qr/^Ksshfwoom=/);
1384
1385     undef $obj;
1386     is ($ref, undef);
1387 }
1388
1389 {
1390     package bit;
1391     # bit operations have overloadable assignment variants too
1392
1393     sub new { bless \$_[1], $_[0] }
1394
1395     use overload
1396           "&=" => sub { bit->new($_[0]->val . ' & ' . $_[1]->val) }, 
1397           "^=" => sub { bit->new($_[0]->val . ' ^ ' . $_[1]->val) },
1398           "|"  => sub { bit->new($_[0]->val . ' | ' . $_[1]->val) }, # |= by fallback
1399           ;
1400
1401     sub val { ${$_[0]} }
1402
1403     package main;
1404
1405     my $a = bit->new(my $va = 'a');
1406     my $b = bit->new(my $vb = 'b');
1407
1408     $a &= $b;
1409     is($a->val, 'a & b', "overloaded &= works");
1410
1411     my $c = bit->new(my $vc = 'c');
1412
1413     $b ^= $c;
1414     is($b->val, 'b ^ c', "overloaded ^= works");
1415
1416     my $d = bit->new(my $vd = 'd');
1417
1418     $c |= $d;
1419     is($c->val, 'c | d', "overloaded |= (by fallback) works");
1420 }
1421
1422 {
1423     # comparison operators with nomethod (bug 41546)
1424     my $warning = "";
1425     my $method;
1426
1427     package nomethod_false;
1428     use overload nomethod => sub { $method = 'nomethod'; 0 };
1429
1430     package nomethod_true;
1431     use overload nomethod => sub { $method= 'nomethod'; 'true' };
1432
1433     package main;
1434     local $^W = 1;
1435     local $SIG{__WARN__} = sub { $warning = $_[0] };
1436
1437     my $f = bless [], 'nomethod_false';
1438     ($warning, $method) = ("", "");
1439     is($f eq 'whatever', 0, 'nomethod makes eq return 0');
1440     is($method, 'nomethod');
1441
1442     my $t = bless [], 'nomethod_true';
1443     ($warning, $method) = ("", "");
1444     is($t eq 'whatever', 'true', 'nomethod makes eq return "true"');
1445     is($method, 'nomethod');
1446     is($warning, "", 'nomethod eq need not return number');
1447
1448     eval q{ 
1449         package nomethod_false;
1450         use overload cmp => sub { $method = 'cmp'; 0 };
1451     };
1452     $f = bless [], 'nomethod_false';
1453     ($warning, $method) = ("", "");
1454     ok($f eq 'whatever', 'eq falls back to cmp (nomethod not called)');
1455     is($method, 'cmp');
1456
1457     eval q{
1458         package nomethod_true;
1459         use overload cmp => sub { $method = 'cmp'; 'true' };
1460     };
1461     $t = bless [], 'nomethod_true';
1462     ($warning, $method) = ("", "");
1463     ok($t eq 'whatever', 'eq falls back to cmp (nomethod not called)');
1464     is($method, 'cmp');
1465     like($warning, qr/isn't numeric/, 'cmp should return number');
1466
1467 }
1468
1469 {
1470     # nomethod called for '!' after attempted fallback
1471     my $nomethod_called = 0;
1472
1473     package nomethod_not;
1474     use overload nomethod => sub { $nomethod_called = 'yes'; };
1475
1476     package main;
1477     my $o = bless [], 'nomethod_not';
1478     my $res = ! $o;
1479
1480     is($nomethod_called, 'yes', "nomethod() is called for '!'");
1481     is($res, 'yes', "nomethod(..., '!') return value propagates");
1482 }
1483
1484 {
1485     # Subtle bug pre 5.10, as a side effect of the overloading flag being
1486     # stored on the reference rather than the referent. Despite the fact that
1487     # objects can only be accessed via references (even internally), the
1488     # referent actually knows that it's blessed, not the references. So taking
1489     # a new, unrelated, reference to it gives an object. However, the
1490     # overloading-or-not flag was on the reference prior to 5.10, and taking
1491     # a new reference didn't (use to) copy it.
1492
1493     package kayo;
1494
1495     use overload '""' => sub {${$_[0]}};
1496
1497     sub Pie {
1498         return "$_[0], $_[1]";
1499     }
1500
1501     package main;
1502
1503     my $class = 'kayo';
1504     my $string = 'bam';
1505     my $crunch_eth = bless \$string, $class;
1506
1507     is("$crunch_eth", $string);
1508     is ($crunch_eth->Pie("Meat"), "$string, Meat");
1509
1510     my $wham_eth = \$string;
1511
1512     is("$wham_eth", $string,
1513        'This reference did not have overloading in 5.8.8 and earlier');
1514     is ($crunch_eth->Pie("Apple"), "$string, Apple");
1515
1516     my $class = ref $wham_eth;
1517     $class =~ s/=.*//;
1518
1519     # Bless it back into its own class!
1520     bless $wham_eth, $class;
1521
1522     is("$wham_eth", $string);
1523     is ($crunch_eth->Pie("Blackbird"), "$string, Blackbird");
1524 }
1525
1526 {
1527     package numify_int;
1528     use overload "0+" => sub { $_[0][0] += 1; 42 };
1529     package numify_self;
1530     use overload "0+" => sub { $_[0][0]++; $_[0] };
1531     package numify_other;
1532     use overload "0+" => sub { $_[0][0]++; $_[0][1] = bless [], 'numify_int' };
1533     package numify_by_fallback;
1534     use overload fallback => 1;
1535
1536     package main;
1537     my $o = bless [], 'numify_int';
1538     is(int($o), 42, 'numifies to integer');
1539     is($o->[0], 1, 'int() numifies only once');
1540
1541     my $aref = [];
1542     my $num_val = int($aref);
1543     my $r = bless $aref, 'numify_self';
1544     is(int($r), $num_val, 'numifies to self');
1545     is($r->[0], 1, 'int() numifies once when returning self');
1546
1547     my $s = bless [], 'numify_other';
1548     is(int($s), 42, 'numifies to numification of other object');
1549     is($s->[0], 1, 'int() numifies once when returning other object');
1550     is($s->[1][0], 1, 'returned object numifies too');
1551
1552     my $m = bless $aref, 'numify_by_fallback';
1553     is(int($m), $num_val, 'numifies to usual reference value');
1554     is(abs($m), $num_val, 'numifies to usual reference value');
1555     is(-$m, -$num_val, 'numifies to usual reference value');
1556     is(0+$m, $num_val, 'numifies to usual reference value');
1557     is($m+0, $num_val, 'numifies to usual reference value');
1558     is($m+$m, 2*$num_val, 'numifies to usual reference value');
1559     is(0-$m, -$num_val, 'numifies to usual reference value');
1560     is(1*$m, $num_val, 'numifies to usual reference value');
1561     is(int($m/1), $num_val, 'numifies to usual reference value');
1562     is($m%100, $num_val%100, 'numifies to usual reference value');
1563     is($m**1, $num_val, 'numifies to usual reference value');
1564
1565     is(abs($aref), $num_val, 'abs() of ref');
1566     is(-$aref, -$num_val, 'negative of ref');
1567     is(0+$aref, $num_val, 'ref addition');
1568     is($aref+0, $num_val, 'ref addition');
1569     is($aref+$aref, 2*$num_val, 'ref addition');
1570     is(0-$aref, -$num_val, 'subtraction of ref');
1571     is(1*$aref, $num_val, 'multiplicaton of ref');
1572     is(int($aref/1), $num_val, 'division of ref');
1573     is($aref%100, $num_val%100, 'modulo of ref');
1574     is($aref**1, $num_val, 'exponentiation of ref');
1575 }
1576
1577 {
1578     package CopyConstructorFallback;
1579     use overload
1580         '++'        => sub { "$_[0]"; $_[0] },
1581         fallback    => 1;
1582     sub new { bless {} => shift }
1583
1584     package main;
1585
1586     my $o = CopyConstructorFallback->new;
1587     my $x = $o++; # would segfault
1588     my $y = ++$o;
1589     is($x, $o, "copy constructor falls back to assignment (postinc)");
1590     is($y, $o, "copy constructor falls back to assignment (preinc)");
1591 }
1592
1593 # only scalar 'x' should currently overload
1594
1595 {
1596     package REPEAT;
1597
1598     my ($x,$n, $nm);
1599
1600     use overload
1601         'x'        => sub { $x++; 1 },
1602         '0+'       => sub { $n++; 1 },
1603         'nomethod' => sub { $nm++; 1 },
1604         'fallback' => 0,
1605     ;
1606
1607     my $s = bless {};
1608
1609     package main;
1610
1611     my @a;
1612     my $count = 3;
1613
1614     ($x,$n,$nm) = (0,0,0);
1615     @a = ((1,2,$s) x $count);
1616     is("$x-$n-$nm", "0-0-0", 'repeat 1');
1617
1618     ($x,$n,$nm) = (0,0,0);
1619     @a = ((1,$s,3) x $count);
1620     is("$x-$n-$nm", "0-0-0", 'repeat 2');
1621
1622     ($x,$n,$nm) = (0,0,0);
1623     @a = ((1,2,3) x $s);
1624     is("$x-$n-$nm", "0-1-0", 'repeat 3');
1625 }
1626
1627
1628
1629 # RT #57012: magic items need to have mg_get() called before testing for
1630 # overload. Lack of this means that overloaded values returned by eg a
1631 # tied array didn't call overload methods.
1632 # We test here both a tied array and scalar, since the implementation of
1633 # tied  arrays (and hashes) is such that in rvalue context, mg_get is
1634 # called prior to executing the op, while it isn't for a tied scalar.
1635
1636 {
1637
1638     my @terms;
1639     my %subs;
1640     my $funcs;
1641     my $use_int;
1642
1643     BEGIN {
1644         # A note on what methods to expect to be called, and
1645         # how many times FETCH/STORE is called:
1646         #
1647         # Mutating ops (+=, ++ etc) trigger a copy ('='), since
1648         # the code can't distingish between something that's been copied:
1649         #    $a = foo->new(0); $b = $a; refcnt($$b) == 2
1650         # and overloaded objects stored in ties which will have extra
1651         # refcounts due to the tied_obj magic and entries on the tmps
1652         # stack when returning from FETCH etc. So we always copy.
1653
1654         # This accounts for a '=', and an extra STORE.
1655         # We also have a FETCH returning the final value from the eval,
1656         # plus a FETCH in the overload subs themselves: ($_[0][0])
1657         # triggers one. However, tied agregates have a mechanism to prevent
1658         # multiple fetches between STOREs, which means that the tied
1659         # hash skips doing a FETCH during '='.
1660
1661         for (qw(+ - * / % ** << >> x . & | ^)) {
1662             my $e = "%s $_= 3";
1663             $subs{"$_="} = $e;
1664             # ARRAY  FETCH: initial,        sub+=, eval-return,
1665             # SCALAR FETCH: initial, sub=,  sub+=, eval-return,
1666             # STORE:        copy, mutator
1667             push @terms, [ 18, $e, "$_=", '(=)', 3, 4, 2 ];
1668             $e = "%s $_ 3";
1669             $subs{$_} = $e;
1670             # ARRAY  FETCH: initial
1671             # SCALAR FETCH: initial eval-return,
1672             push @terms, [ 18, $e, $_, '', 1, 2, 0 ];
1673         }
1674         for (qw(++ --)) {
1675             my $pre  = "$_%s";
1676             my $post = "%s$_";
1677             $subs{$_} = $pre;
1678             push @terms,
1679                 # ARRAY  FETCH: initial,        sub+=, eval-return,
1680                 # SCALAR FETCH: initial, sub=,  sub+=, eval-return,
1681                 # STORE:        copy, mutator
1682                 [ 18, $pre,  $_, '(=)("")', 3, 4, 2 ],
1683                 # ARRAY  FETCH: initial,        sub+=
1684                 # SCALAR FETCH: initial, sub=,  sub+=
1685                 # STORE:        copy, mutator
1686                 [ 18, $post, $_, '(=)("")', 2, 3, 2 ];
1687         }
1688
1689         # For the non-mutator ops, we have a initial FETCH,
1690         # an extra FETCH within the sub itself for the scalar option,
1691         # and no STOREs
1692
1693         for (qw(< <= >  >= == != lt le gt ge eq ne <=> cmp)) {
1694             my $e = "%s $_ 3";
1695             $subs{$_} = $e;
1696             push @terms, [ 3, $e, $_, '', 1, 2, 0 ];
1697         }
1698         for (qw(atan2)) {
1699             my $e = "$_ %s, 3";
1700             $subs{$_} = $e;
1701             push @terms, [ 18, $e, $_, '', 1, 2, 0 ];
1702         }
1703         for (qw(cos sin exp abs log sqrt int ! ~)) {
1704             my $e = "$_(%s)";
1705             $subs{$_} = $e;
1706             push @terms, [ 1.23, $e, $_, '', 1, 2, 0 ];
1707         }
1708         for (qw(-)) {
1709             my $e = "$_(%s)";
1710             $subs{neg} = $e;
1711             push @terms, [ 18, $e, 'neg', '', 1, 2, 0 ];
1712         }
1713         my $e = '(%s) ? 1 : 0';
1714         $subs{bool} = $e;
1715         push @terms, [ 18, $e, 'bool', '', 1, 2, 0 ];
1716
1717         # note: this is testing unary qr, not binary =~
1718         $subs{qr} = '(%s)';
1719         push @terms, [ qr/abc/, '"abc" =~ (%s)', 'qr', '', 1, 2, 0 ];
1720
1721         $e = '"abc" ~~ (%s)';
1722         $subs{'~~'} = $e;
1723         push @terms, [ "abc", $e, '~~', '', 1, 1, 0 ];
1724
1725         $subs{'-X'} = 'do { my $f = (%s);'
1726                     . '$_[1] eq "r" ? (-r ($f)) :'
1727                     . '$_[1] eq "e" ? (-e ($f)) :'
1728                     . '$_[1] eq "f" ? (-f ($f)) :'
1729                     . '$_[1] eq "l" ? (-l ($f)) :'
1730                     . '$_[1] eq "t" ? (-t ($f)) :'
1731                     . '$_[1] eq "T" ? (-T ($f)) : 0;}';
1732         # Note - we don't care what these filetests return, as
1733         # long as the tied and untied versions return the same value.
1734         # The flags below are chosen to test all uses of tryAMAGICftest_MG
1735         for (qw(r e f l t T)) {
1736             push @terms, [ 'TEST', "-$_ (%s)", '-X', '', 1, 2, 0 ];
1737         }
1738
1739         $subs{'${}'} = '%s';
1740         push @terms, [ do {my $s=99; \$s}, '${%s}', '${}', '', 1, 2, 0 ];
1741
1742         # we skip testing '@{}' here because too much of this test
1743         # framework involves array deredfences!
1744
1745         $subs{'%{}'} = '%s';
1746         push @terms, [ {qw(a 1 b 2 c 3)}, 'join "", sort keys %%{%s}', '%{}',
1747                 '', 1, 2, 0 ];
1748
1749         $subs{'&{}'} = '%s';
1750         push @terms, [ sub {99}, 'do {&{%s} for 1,2}', '&{})(&{}', '', 2, 4, 0 ];
1751
1752         our $RT57012A = 88;
1753         our $RT57012B;
1754         $subs{'*{}'} = '%s';
1755         push @terms, [ \*RT57012A, '*RT57012B = *{%s}; our $RT57012B',
1756                 '*{}', '', 1, 2, 0 ];
1757
1758         # XXX TODO: '<>'
1759
1760         for my $sub (keys %subs) {
1761             my $term = $subs{$sub};
1762             my $t = sprintf $term, '$_[0][0]';
1763             $subs{$sub} = eval
1764                 "sub { \$funcs .= '($sub)'; my \$r; if (\$use_int) {"
1765                 . "use integer; \$r = ($t) } else { \$r = ($t) } \$r }";
1766             die $@ if $@;
1767         }
1768     }
1769
1770     my $fetches;
1771     my $stores;
1772
1773     package RT57012_OV;
1774
1775     my $other;
1776     use overload
1777         %subs,
1778         "="   => sub { $other .= '(=)';  bless [ $_[0][0] ] },
1779         '0+'  => sub { $other .= '(0+)'; 0 + $_[0][0] },
1780         '""'  => sub { $other .= '("")'; "$_[0][0]"   },
1781         ;
1782
1783     package RT57012_TIE_S;
1784
1785     my $tie_val;
1786     sub TIESCALAR { bless [ bless [ $tie_val ], 'RT57012_OV' ] }
1787     sub FETCH     { $fetches++; $_[0][0] }
1788     sub STORE     { $stores++;  $_[0][0] = $_[1] }
1789
1790     package RT57012_TIE_A;
1791
1792     sub TIEARRAY  { bless [] }
1793     sub FETCH     { $fetches++; $_[0][0] }
1794     sub STORE     { $stores++;  $_[0][$_[1]] = $_[2] }
1795
1796     package main;
1797
1798     for my $term (@terms) {
1799         my ($val, $sub_term, $exp_funcs, $exp_side,
1800             $exp_fetch_a, $exp_fetch_s, $exp_store) = @$term;
1801
1802         $tie_val = $val;
1803         for my $int ('', 'use integer; ') {
1804             $use_int = ($int ne '');
1805             for my $var ('$ta[0]', '$ts') {
1806                 my $exp_fetch = ($var eq '$ts') ? $exp_fetch_s : $exp_fetch_a;
1807                 tie my $ts, 'RT57012_TIE_S';
1808                 tie my @ta, 'RT57012_TIE_A';
1809                 $ta[0] = bless [ $val ], 'RT57012_OV';
1810                 my $x = $val;
1811                 my $tied_term  = $int . sprintf $sub_term, $var;
1812                 my $plain_term = $int . sprintf $sub_term, '$x';
1813
1814                 $other = ''; $funcs = '';
1815
1816                 $fetches = 0;
1817                 $stores = 0;
1818                 my $res = eval $tied_term;
1819                 $res = "$res";
1820                 my $exp = eval $plain_term;
1821                 $exp = "$exp";
1822                 is ($res, $exp, "tied '$tied_term' return value");
1823                 is ($funcs, "($exp_funcs)", "tied '$tied_term' methods called");
1824                 is ($other, $exp_side, "tied '$tied_term' side effects called");
1825                 is ($fetches, $exp_fetch, "tied '$tied_term' FETCH count");
1826                 is ($stores, $exp_store, "tied '$tied_term' STORE count");
1827             }
1828         }
1829     }
1830 }
1831
1832 # EOF