This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #61520] Segfault in debugger with tr// and UTF8
[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 => 577;
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     my $twenty_three = 23;
1186     # Check that constant overloading propagates into evals
1187     BEGIN { overload::constant integer => sub { 23 } }
1188     is(eval "17", $twenty_three);
1189 }
1190
1191 {
1192     package Sklorsh;
1193     use overload
1194         bool     => sub { shift->is_cool };
1195
1196     sub is_cool {
1197         $_[0]->{name} eq 'cool';
1198     }
1199
1200     sub delete {
1201         undef %{$_[0]};
1202         bless $_[0], 'Brap';
1203         return 1;
1204     }
1205
1206     sub delete_with_self {
1207         my $self = shift;
1208         undef %$self;
1209         bless $self, 'Brap';
1210         return 1;
1211     }
1212
1213     package Brap;
1214
1215     1;
1216
1217     package main;
1218
1219     my $obj;
1220     $obj = bless {name => 'cool'}, 'Sklorsh';
1221     $obj->delete;
1222     ok(eval {if ($obj) {1}; 1}, $@ || 'reblessed into nonexistent namespace');
1223
1224     $obj = bless {name => 'cool'}, 'Sklorsh';
1225     $obj->delete_with_self;
1226     ok (eval {if ($obj) {1}; 1}, $@);
1227     
1228     my $a = $b = {name => 'hot'};
1229     bless $b, 'Sklorsh';
1230     is(ref $a, 'Sklorsh');
1231     is(ref $b, 'Sklorsh');
1232     ok(!$b, "Expect overloaded boolean");
1233     ok(!$a, "Expect overloaded boolean");
1234 }
1235
1236 {
1237     package Flrbbbbb;
1238     use overload
1239         bool     => sub { shift->{truth} eq 'yes' },
1240         '0+'     => sub { shift->{truth} eq 'yes' ? '1' : '0' },
1241         '!'      => sub { shift->{truth} eq 'no' },
1242         fallback => 1;
1243
1244     sub new { my $class = shift; bless { truth => shift }, $class }
1245
1246     package main;
1247
1248     my $yes = Flrbbbbb->new('yes');
1249     my $x;
1250     $x = 1 if $yes;                     is($x, 1);
1251     $x = 2 unless $yes;                 is($x, 1);
1252     $x = 3 if !$yes;                    is($x, 1);
1253     $x = 4 unless !$yes;                is($x, 4);
1254
1255     my $no = Flrbbbbb->new('no');
1256     $x = 0;
1257     $x = 1 if $no;                      is($x, 0);
1258     $x = 2 unless $no;                  is($x, 2);
1259     $x = 3 if !$no;                     is($x, 3);
1260     $x = 4 unless !$no;                 is($x, 3);
1261
1262     $x = 0;
1263     $x = 1 if !$no && $yes;             is($x, 1);
1264     $x = 2 unless !$no && $yes;         is($x, 1);
1265     $x = 3 if $no || !$yes;             is($x, 1);
1266     $x = 4 unless $no || !$yes;         is($x, 4);
1267
1268     $x = 0;
1269     $x = 1 if !$no || !$yes;            is($x, 1);
1270     $x = 2 unless !$no || !$yes;        is($x, 1);
1271     $x = 3 if !$no && !$yes;            is($x, 1);
1272     $x = 4 unless !$no && !$yes;        is($x, 4);
1273 }
1274
1275 {
1276     use Scalar::Util 'weaken';
1277
1278     package Shklitza;
1279     use overload '""' => sub {"CLiK KLAK"};
1280
1281     package Ksshfwoom;
1282
1283     package main;
1284
1285     my ($obj, $ref);
1286     $obj = bless do {my $a; \$a}, 'Shklitza';
1287     $ref = $obj;
1288
1289     is ($obj, "CLiK KLAK");
1290     is ($ref, "CLiK KLAK");
1291
1292     weaken $ref;
1293     is ($ref, "CLiK KLAK");
1294
1295     bless $obj, 'Ksshfwoom';
1296
1297     like ($obj, qr/^Ksshfwoom=/);
1298     like ($ref, qr/^Ksshfwoom=/);
1299
1300     undef $obj;
1301     is ($ref, undef);
1302 }
1303
1304 {
1305     package bit;
1306     # bit operations have overloadable assignment variants too
1307
1308     sub new { bless \$_[1], $_[0] }
1309
1310     use overload
1311           "&=" => sub { bit->new($_[0]->val . ' & ' . $_[1]->val) }, 
1312           "^=" => sub { bit->new($_[0]->val . ' ^ ' . $_[1]->val) },
1313           "|"  => sub { bit->new($_[0]->val . ' | ' . $_[1]->val) }, # |= by fallback
1314           ;
1315
1316     sub val { ${$_[0]} }
1317
1318     package main;
1319
1320     my $a = bit->new(my $va = 'a');
1321     my $b = bit->new(my $vb = 'b');
1322
1323     $a &= $b;
1324     is($a->val, 'a & b', "overloaded &= works");
1325
1326     my $c = bit->new(my $vc = 'c');
1327
1328     $b ^= $c;
1329     is($b->val, 'b ^ c', "overloaded ^= works");
1330
1331     my $d = bit->new(my $vd = 'd');
1332
1333     $c |= $d;
1334     is($c->val, 'c | d', "overloaded |= (by fallback) works");
1335 }
1336
1337 {
1338     # comparison operators with nomethod
1339     my $warning = "";
1340     my $method;
1341
1342     package nomethod_false;
1343     use overload nomethod => sub { $method = 'nomethod'; 0 };
1344
1345     package nomethod_true;
1346     use overload nomethod => sub { $method= 'nomethod'; 'true' };
1347
1348     package main;
1349     local $^W = 1;
1350     local $SIG{__WARN__} = sub { $warning = $_[0] };
1351
1352     my $f = bless [], 'nomethod_false';
1353     ($warning, $method) = ("", "");
1354     is($f eq 'whatever', 0, 'nomethod makes eq return 0');
1355     is($method, 'nomethod');
1356
1357     my $t = bless [], 'nomethod_true';
1358     ($warning, $method) = ("", "");
1359     is($t eq 'whatever', 'true', 'nomethod makes eq return "true"');
1360     is($method, 'nomethod');
1361     is($warning, "", 'nomethod eq need not return number');
1362
1363     eval q{ 
1364         package nomethod_false;
1365         use overload cmp => sub { $method = 'cmp'; 0 };
1366     };
1367     $f = bless [], 'nomethod_false';
1368     ($warning, $method) = ("", "");
1369     ok($f eq 'whatever', 'eq falls back to cmp (nomethod not called)');
1370     is($method, 'cmp');
1371
1372     eval q{
1373         package nomethod_true;
1374         use overload cmp => sub { $method = 'cmp'; 'true' };
1375     };
1376     $t = bless [], 'nomethod_true';
1377     ($warning, $method) = ("", "");
1378     ok($t eq 'whatever', 'eq falls back to cmp (nomethod not called)');
1379     is($method, 'cmp');
1380     like($warning, qr/isn't numeric/, 'cmp should return number');
1381
1382 }
1383
1384 {
1385     # Subtle bug pre 5.10, as a side effect of the overloading flag being
1386     # stored on the reference rather than the referent. Despite the fact that
1387     # objects can only be accessed via references (even internally), the
1388     # referent actually knows that it's blessed, not the references. So taking
1389     # a new, unrelated, reference to it gives an object. However, the
1390     # overloading-or-not flag was on the reference prior to 5.10, and taking
1391     # a new reference didn't (use to) copy it.
1392
1393     package kayo;
1394
1395     use overload '""' => sub {${$_[0]}};
1396
1397     sub Pie {
1398         return "$_[0], $_[1]";
1399     }
1400
1401     package main;
1402
1403     my $class = 'kayo';
1404     my $string = 'bam';
1405     my $crunch_eth = bless \$string, $class;
1406
1407     is("$crunch_eth", $string);
1408     is ($crunch_eth->Pie("Meat"), "$string, Meat");
1409
1410     my $wham_eth = \$string;
1411
1412     is("$wham_eth", $string,
1413        'This reference did not have overloading in 5.8.8 and earlier');
1414     is ($crunch_eth->Pie("Apple"), "$string, Apple");
1415
1416     my $class = ref $wham_eth;
1417     $class =~ s/=.*//;
1418
1419     # Bless it back into its own class!
1420     bless $wham_eth, $class;
1421
1422     is("$wham_eth", $string);
1423     is ($crunch_eth->Pie("Blackbird"), "$string, Blackbird");
1424 }
1425
1426 {
1427     package numify_int;
1428     use overload "0+" => sub { $_[0][0] += 1; 42 };
1429     package numify_self;
1430     use overload "0+" => sub { $_[0][0]++; $_[0] };
1431     package numify_other;
1432     use overload "0+" => sub { $_[0][0]++; $_[0][1] = bless [], 'numify_int' };
1433     package numify_by_fallback;
1434     use overload fallback => 1;
1435
1436     package main;
1437     my $o = bless [], 'numify_int';
1438     is(int($o), 42, 'numifies to integer');
1439     is($o->[0], 1, 'int() numifies only once');
1440
1441     my $aref = [];
1442     my $num_val = int($aref);
1443     my $r = bless $aref, 'numify_self';
1444     is(int($r), $num_val, 'numifies to self');
1445     is($r->[0], 1, 'int() numifies once when returning self');
1446
1447     my $s = bless [], 'numify_other';
1448     is(int($s), 42, 'numifies to numification of other object');
1449     is($s->[0], 1, 'int() numifies once when returning other object');
1450     is($s->[1][0], 1, 'returned object numifies too');
1451
1452     my $m = bless $aref, 'numify_by_fallback';
1453     is(int($m), $num_val, 'numifies to usual reference value');
1454     is(abs($m), $num_val, 'numifies to usual reference value');
1455     is(-$m, -$num_val, 'numifies to usual reference value');
1456     is(0+$m, $num_val, 'numifies to usual reference value');
1457     is($m+0, $num_val, 'numifies to usual reference value');
1458     is($m+$m, 2*$num_val, 'numifies to usual reference value');
1459     is(0-$m, -$num_val, 'numifies to usual reference value');
1460     is(1*$m, $num_val, 'numifies to usual reference value');
1461     is($m/1, $num_val, 'numifies to usual reference value');
1462     is($m%100, $num_val%100, 'numifies to usual reference value');
1463     is($m**1, $num_val, 'numifies to usual reference value');
1464
1465     is(abs($aref), $num_val, 'abs() of ref');
1466     is(-$aref, -$num_val, 'negative of ref');
1467     is(0+$aref, $num_val, 'ref addition');
1468     is($aref+0, $num_val, 'ref addition');
1469     is($aref+$aref, 2*$num_val, 'ref addition');
1470     is(0-$aref, -$num_val, 'subtraction of ref');
1471     is(1*$aref, $num_val, 'multiplicaton of ref');
1472     is($aref/1, $num_val, 'division of ref');
1473     is($aref%100, $num_val%100, 'modulo of ref');
1474     is($aref**1, $num_val, 'exponentiation of ref');
1475 }
1476
1477 {
1478     package CopyConstructorFallback;
1479     use overload
1480         '++'        => sub { "$_[0]"; $_[0] },
1481         fallback    => 1;
1482     sub new { bless {} => shift }
1483
1484     package main;
1485
1486     my $o = CopyConstructorFallback->new;
1487     my $x = $o++; # would segfault
1488     my $y = ++$o;
1489     is($x, $o, "copy constructor falls back to assignment (postinc)");
1490     is($y, $o, "copy constructor falls back to assignment (preinc)");
1491 }
1492
1493 # EOF