xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/overload.t (revision 0:68f95e015346)
1*0Sstevel@tonic-gate#!./perl
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gateBEGIN {
4*0Sstevel@tonic-gate    chdir 't' if -d 't';
5*0Sstevel@tonic-gate    @INC = '../lib';
6*0Sstevel@tonic-gate}
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gatepackage Oscalar;
9*0Sstevel@tonic-gateuse overload (
10*0Sstevel@tonic-gate				# Anonymous subroutines:
11*0Sstevel@tonic-gate'+'	=>	sub {new Oscalar $ {$_[0]}+$_[1]},
12*0Sstevel@tonic-gate'-'	=>	sub {new Oscalar
13*0Sstevel@tonic-gate		       $_[2]? $_[1]-${$_[0]} : ${$_[0]}-$_[1]},
14*0Sstevel@tonic-gate'<=>'	=>	sub {new Oscalar
15*0Sstevel@tonic-gate		       $_[2]? $_[1]-${$_[0]} : ${$_[0]}-$_[1]},
16*0Sstevel@tonic-gate'cmp'	=>	sub {new Oscalar
17*0Sstevel@tonic-gate		       $_[2]? ($_[1] cmp ${$_[0]}) : (${$_[0]} cmp $_[1])},
18*0Sstevel@tonic-gate'*'	=>	sub {new Oscalar ${$_[0]}*$_[1]},
19*0Sstevel@tonic-gate'/'	=>	sub {new Oscalar
20*0Sstevel@tonic-gate		       $_[2]? $_[1]/${$_[0]} :
21*0Sstevel@tonic-gate			 ${$_[0]}/$_[1]},
22*0Sstevel@tonic-gate'%'	=>	sub {new Oscalar
23*0Sstevel@tonic-gate		       $_[2]? $_[1]%${$_[0]} : ${$_[0]}%$_[1]},
24*0Sstevel@tonic-gate'**'	=>	sub {new Oscalar
25*0Sstevel@tonic-gate		       $_[2]? $_[1]**${$_[0]} : ${$_[0]}-$_[1]},
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gateqw(
28*0Sstevel@tonic-gate""	stringify
29*0Sstevel@tonic-gate0+	numify)			# Order of arguments unsignificant
30*0Sstevel@tonic-gate);
31*0Sstevel@tonic-gate
32*0Sstevel@tonic-gatesub new {
33*0Sstevel@tonic-gate  my $foo = $_[1];
34*0Sstevel@tonic-gate  bless \$foo, $_[0];
35*0Sstevel@tonic-gate}
36*0Sstevel@tonic-gate
37*0Sstevel@tonic-gatesub stringify { "${$_[0]}" }
38*0Sstevel@tonic-gatesub numify { 0 + "${$_[0]}" }	# Not needed, additional overhead
39*0Sstevel@tonic-gate				# comparing to direct compilation based on
40*0Sstevel@tonic-gate				# stringify
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gatepackage main;
43*0Sstevel@tonic-gate
44*0Sstevel@tonic-gateour $test = 0;
45*0Sstevel@tonic-gate$| = 1;
46*0Sstevel@tonic-gateprint "1..",&last,"\n";
47*0Sstevel@tonic-gate
48*0Sstevel@tonic-gatesub test {
49*0Sstevel@tonic-gate  $test++;
50*0Sstevel@tonic-gate  if (@_ > 1) {
51*0Sstevel@tonic-gate    my $comment = "";
52*0Sstevel@tonic-gate    $comment = " # " . $_ [2] if @_ > 2;
53*0Sstevel@tonic-gate    if ($_[0] eq $_[1]) {
54*0Sstevel@tonic-gate        print "ok $test$comment\n";
55*0Sstevel@tonic-gate        return 1;
56*0Sstevel@tonic-gate    } else {
57*0Sstevel@tonic-gate      $comment .= ": '$_[0]' ne '$_[1]'";
58*0Sstevel@tonic-gate        print "not ok $test$comment\n";
59*0Sstevel@tonic-gate        return 0;
60*0Sstevel@tonic-gate    }
61*0Sstevel@tonic-gate  } else {
62*0Sstevel@tonic-gate    if (shift) {
63*0Sstevel@tonic-gate        print "ok $test\n";
64*0Sstevel@tonic-gate        return 1;
65*0Sstevel@tonic-gate    } else {
66*0Sstevel@tonic-gate      print "not ok $test\n";
67*0Sstevel@tonic-gate        return 0;
68*0Sstevel@tonic-gate    }
69*0Sstevel@tonic-gate  }
70*0Sstevel@tonic-gate}
71*0Sstevel@tonic-gate
72*0Sstevel@tonic-gate$a = new Oscalar "087";
73*0Sstevel@tonic-gate$b= "$a";
74*0Sstevel@tonic-gate
75*0Sstevel@tonic-gate# All test numbers in comments are off by 1.
76*0Sstevel@tonic-gate# So much for hard-wiring them in :-) To fix this:
77*0Sstevel@tonic-gatetest(1);			# 1
78*0Sstevel@tonic-gate
79*0Sstevel@tonic-gatetest ($b eq $a);		# 2
80*0Sstevel@tonic-gatetest ($b eq "087");		# 3
81*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 4
82*0Sstevel@tonic-gatetest ($a eq $a);		# 5
83*0Sstevel@tonic-gatetest ($a eq "087");		# 6
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gate$c = $a + 7;
86*0Sstevel@tonic-gate
87*0Sstevel@tonic-gatetest (ref $c eq "Oscalar");	# 7
88*0Sstevel@tonic-gatetest (!($c eq $a));		# 8
89*0Sstevel@tonic-gatetest ($c eq "94");		# 9
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate$b=$a;
92*0Sstevel@tonic-gate
93*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 10
94*0Sstevel@tonic-gate
95*0Sstevel@tonic-gate$b++;
96*0Sstevel@tonic-gate
97*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 11
98*0Sstevel@tonic-gatetest ( $a eq "087");		# 12
99*0Sstevel@tonic-gatetest ( $b eq "88");		# 13
100*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 14
101*0Sstevel@tonic-gate
102*0Sstevel@tonic-gate$c=$b;
103*0Sstevel@tonic-gate$c-=$a;
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gatetest (ref $c eq "Oscalar");	# 15
106*0Sstevel@tonic-gatetest ( $a eq "087");		# 16
107*0Sstevel@tonic-gatetest ( $c eq "1");		# 17
108*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 18
109*0Sstevel@tonic-gate
110*0Sstevel@tonic-gate$b=1;
111*0Sstevel@tonic-gate$b+=$a;
112*0Sstevel@tonic-gate
113*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 19
114*0Sstevel@tonic-gatetest ( $a eq "087");		# 20
115*0Sstevel@tonic-gatetest ( $b eq "88");		# 21
116*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 22
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gateeval q[ package Oscalar; use overload ('++' => sub { $ {$_[0]}++;$_[0] } ) ];
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate$b=$a;
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 23
123*0Sstevel@tonic-gate
124*0Sstevel@tonic-gate$b++;
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 24
127*0Sstevel@tonic-gatetest ( $a eq "087");		# 25
128*0Sstevel@tonic-gatetest ( $b eq "88");		# 26
129*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 27
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gatepackage Oscalar;
132*0Sstevel@tonic-gate$dummy=bless \$dummy;		# Now cache of method should be reloaded
133*0Sstevel@tonic-gatepackage main;
134*0Sstevel@tonic-gate
135*0Sstevel@tonic-gate$b=$a;
136*0Sstevel@tonic-gate$b++;
137*0Sstevel@tonic-gate
138*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 28
139*0Sstevel@tonic-gatetest ( $a eq "087");		# 29
140*0Sstevel@tonic-gatetest ( $b eq "88");		# 30
141*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 31
142*0Sstevel@tonic-gate
143*0Sstevel@tonic-gateundef $b;			# Destroying updates tables too...
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gateeval q[package Oscalar; use overload ('++' => sub { $ {$_[0]} += 2; $_[0] } ) ];
146*0Sstevel@tonic-gate
147*0Sstevel@tonic-gate$b=$a;
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 32
150*0Sstevel@tonic-gate
151*0Sstevel@tonic-gate$b++;
152*0Sstevel@tonic-gate
153*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 33
154*0Sstevel@tonic-gatetest ( $a eq "087");		# 34
155*0Sstevel@tonic-gatetest ( $b eq "88");		# 35
156*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 36
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gatepackage Oscalar;
159*0Sstevel@tonic-gate$dummy=bless \$dummy;		# Now cache of method should be reloaded
160*0Sstevel@tonic-gatepackage main;
161*0Sstevel@tonic-gate
162*0Sstevel@tonic-gate$b++;
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 37
165*0Sstevel@tonic-gatetest ( $a eq "087");		# 38
166*0Sstevel@tonic-gatetest ( $b eq "90");		# 39
167*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 40
168*0Sstevel@tonic-gate
169*0Sstevel@tonic-gate$b=$a;
170*0Sstevel@tonic-gate$b++;
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 41
173*0Sstevel@tonic-gatetest ( $a eq "087");		# 42
174*0Sstevel@tonic-gatetest ( $b eq "89");		# 43
175*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 44
176*0Sstevel@tonic-gate
177*0Sstevel@tonic-gate
178*0Sstevel@tonic-gatetest ($b? 1:0);			# 45
179*0Sstevel@tonic-gate
180*0Sstevel@tonic-gateeval q[ package Oscalar; use overload ('=' => sub {$main::copies++;
181*0Sstevel@tonic-gate						   package Oscalar;
182*0Sstevel@tonic-gate						   local $new=$ {$_[0]};
183*0Sstevel@tonic-gate						   bless \$new } ) ];
184*0Sstevel@tonic-gate
185*0Sstevel@tonic-gate$b=new Oscalar "$a";
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 46
188*0Sstevel@tonic-gatetest ( $a eq "087");		# 47
189*0Sstevel@tonic-gatetest ( $b eq "087");		# 48
190*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 49
191*0Sstevel@tonic-gate
192*0Sstevel@tonic-gate$b++;
193*0Sstevel@tonic-gate
194*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 50
195*0Sstevel@tonic-gatetest ( $a eq "087");		# 51
196*0Sstevel@tonic-gatetest ( $b eq "89");		# 52
197*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 53
198*0Sstevel@tonic-gatetest ($copies == 0);		# 54
199*0Sstevel@tonic-gate
200*0Sstevel@tonic-gate$b+=1;
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 55
203*0Sstevel@tonic-gatetest ( $a eq "087");		# 56
204*0Sstevel@tonic-gatetest ( $b eq "90");		# 57
205*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 58
206*0Sstevel@tonic-gatetest ($copies == 0);		# 59
207*0Sstevel@tonic-gate
208*0Sstevel@tonic-gate$b=$a;
209*0Sstevel@tonic-gate$b+=1;
210*0Sstevel@tonic-gate
211*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 60
212*0Sstevel@tonic-gatetest ( $a eq "087");		# 61
213*0Sstevel@tonic-gatetest ( $b eq "88");		# 62
214*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 63
215*0Sstevel@tonic-gatetest ($copies == 0);		# 64
216*0Sstevel@tonic-gate
217*0Sstevel@tonic-gate$b=$a;
218*0Sstevel@tonic-gate$b++;
219*0Sstevel@tonic-gate
220*0Sstevel@tonic-gatetest (ref $b eq "Oscalar") || print ref $b,"=ref(b)\n";	# 65
221*0Sstevel@tonic-gatetest ( $a eq "087");		# 66
222*0Sstevel@tonic-gatetest ( $b eq "89");		# 67
223*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 68
224*0Sstevel@tonic-gatetest ($copies == 1);		# 69
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gateeval q[package Oscalar; use overload ('+=' => sub {$ {$_[0]} += 3*$_[1];
227*0Sstevel@tonic-gate						   $_[0] } ) ];
228*0Sstevel@tonic-gate$c=new Oscalar;			# Cause rehash
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gate$b=$a;
231*0Sstevel@tonic-gate$b+=1;
232*0Sstevel@tonic-gate
233*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 70
234*0Sstevel@tonic-gatetest ( $a eq "087");		# 71
235*0Sstevel@tonic-gatetest ( $b eq "90");		# 72
236*0Sstevel@tonic-gatetest (ref $a eq "Oscalar");	# 73
237*0Sstevel@tonic-gatetest ($copies == 2);		# 74
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gate$b+=$b;
240*0Sstevel@tonic-gate
241*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 75
242*0Sstevel@tonic-gatetest ( $b eq "360");		# 76
243*0Sstevel@tonic-gatetest ($copies == 2);		# 77
244*0Sstevel@tonic-gate$b=-$b;
245*0Sstevel@tonic-gate
246*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 78
247*0Sstevel@tonic-gatetest ( $b eq "-360");		# 79
248*0Sstevel@tonic-gatetest ($copies == 2);		# 80
249*0Sstevel@tonic-gate
250*0Sstevel@tonic-gate$b=abs($b);
251*0Sstevel@tonic-gate
252*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 81
253*0Sstevel@tonic-gatetest ( $b eq "360");		# 82
254*0Sstevel@tonic-gatetest ($copies == 2);		# 83
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gate$b=abs($b);
257*0Sstevel@tonic-gate
258*0Sstevel@tonic-gatetest (ref $b eq "Oscalar");	# 84
259*0Sstevel@tonic-gatetest ( $b eq "360");		# 85
260*0Sstevel@tonic-gatetest ($copies == 2);		# 86
261*0Sstevel@tonic-gate
262*0Sstevel@tonic-gateeval q[package Oscalar;
263*0Sstevel@tonic-gate       use overload ('x' => sub {new Oscalar ( $_[2] ? "_.$_[1]._" x $ {$_[0]}
264*0Sstevel@tonic-gate					      : "_.${$_[0]}._" x $_[1])}) ];
265*0Sstevel@tonic-gate
266*0Sstevel@tonic-gate$a=new Oscalar "yy";
267*0Sstevel@tonic-gate$a x= 3;
268*0Sstevel@tonic-gatetest ($a eq "_.yy.__.yy.__.yy._"); # 87
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gateeval q[package Oscalar;
271*0Sstevel@tonic-gate       use overload ('.' => sub {new Oscalar ( $_[2] ?
272*0Sstevel@tonic-gate					      "_.$_[1].__.$ {$_[0]}._"
273*0Sstevel@tonic-gate					      : "_.$ {$_[0]}.__.$_[1]._")}) ];
274*0Sstevel@tonic-gate
275*0Sstevel@tonic-gate$a=new Oscalar "xx";
276*0Sstevel@tonic-gate
277*0Sstevel@tonic-gatetest ("b${a}c" eq "_._.b.__.xx._.__.c._"); # 88
278*0Sstevel@tonic-gate
279*0Sstevel@tonic-gate# Check inheritance of overloading;
280*0Sstevel@tonic-gate{
281*0Sstevel@tonic-gate  package OscalarI;
282*0Sstevel@tonic-gate  @ISA = 'Oscalar';
283*0Sstevel@tonic-gate}
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gate$aI = new OscalarI "$a";
286*0Sstevel@tonic-gatetest (ref $aI eq "OscalarI");	# 89
287*0Sstevel@tonic-gatetest ("$aI" eq "xx");		# 90
288*0Sstevel@tonic-gatetest ($aI eq "xx");		# 91
289*0Sstevel@tonic-gatetest ("b${aI}c" eq "_._.b.__.xx._.__.c._");		# 92
290*0Sstevel@tonic-gate
291*0Sstevel@tonic-gate# Here we test blessing to a package updates hash
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gateeval "package Oscalar; no overload '.'";
294*0Sstevel@tonic-gate
295*0Sstevel@tonic-gatetest ("b${a}" eq "_.b.__.xx._"); # 93
296*0Sstevel@tonic-gate$x="1";
297*0Sstevel@tonic-gatebless \$x, Oscalar;
298*0Sstevel@tonic-gatetest ("b${a}c" eq "bxxc");	# 94
299*0Sstevel@tonic-gatenew Oscalar 1;
300*0Sstevel@tonic-gatetest ("b${a}c" eq "bxxc");	# 95
301*0Sstevel@tonic-gate
302*0Sstevel@tonic-gate# Negative overloading:
303*0Sstevel@tonic-gate
304*0Sstevel@tonic-gate$na = eval { ~$a };
305*0Sstevel@tonic-gatetest($@ =~ /no method found/);	# 96
306*0Sstevel@tonic-gate
307*0Sstevel@tonic-gate# Check AUTOLOADING:
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gate*Oscalar::AUTOLOAD =
310*0Sstevel@tonic-gate  sub { *{"Oscalar::$AUTOLOAD"} = sub {"_!_" . shift() . "_!_"} ;
311*0Sstevel@tonic-gate	goto &{"Oscalar::$AUTOLOAD"}};
312*0Sstevel@tonic-gate
313*0Sstevel@tonic-gateeval "package Oscalar; sub comple; use overload '~' => 'comple'";
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate$na = eval { ~$a };		# Hash was not updated
316*0Sstevel@tonic-gatetest($@ =~ /no method found/);	# 97
317*0Sstevel@tonic-gate
318*0Sstevel@tonic-gatebless \$x, Oscalar;
319*0Sstevel@tonic-gate
320*0Sstevel@tonic-gate$na = eval { ~$a };		# Hash updated
321*0Sstevel@tonic-gatewarn "`$na', $@" if $@;
322*0Sstevel@tonic-gatetest !$@;			# 98
323*0Sstevel@tonic-gatetest($na eq '_!_xx_!_');	# 99
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate$na = 0;
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gate$na = eval { ~$aI };		# Hash was not updated
328*0Sstevel@tonic-gatetest($@ =~ /no method found/);	# 100
329*0Sstevel@tonic-gate
330*0Sstevel@tonic-gatebless \$x, OscalarI;
331*0Sstevel@tonic-gate
332*0Sstevel@tonic-gate$na = eval { ~$aI };
333*0Sstevel@tonic-gateprint $@;
334*0Sstevel@tonic-gate
335*0Sstevel@tonic-gatetest !$@;			# 101
336*0Sstevel@tonic-gatetest($na eq '_!_xx_!_');	# 102
337*0Sstevel@tonic-gate
338*0Sstevel@tonic-gateeval "package Oscalar; sub rshft; use overload '>>' => 'rshft'";
339*0Sstevel@tonic-gate
340*0Sstevel@tonic-gate$na = eval { $aI >> 1 };	# Hash was not updated
341*0Sstevel@tonic-gatetest($@ =~ /no method found/);	# 103
342*0Sstevel@tonic-gate
343*0Sstevel@tonic-gatebless \$x, OscalarI;
344*0Sstevel@tonic-gate
345*0Sstevel@tonic-gate$na = 0;
346*0Sstevel@tonic-gate
347*0Sstevel@tonic-gate$na = eval { $aI >> 1 };
348*0Sstevel@tonic-gateprint $@;
349*0Sstevel@tonic-gate
350*0Sstevel@tonic-gatetest !$@;			# 104
351*0Sstevel@tonic-gatetest($na eq '_!_xx_!_');	# 105
352*0Sstevel@tonic-gate
353*0Sstevel@tonic-gate# warn overload::Method($a, '0+'), "\n";
354*0Sstevel@tonic-gatetest (overload::Method($a, '0+') eq \&Oscalar::numify); # 106
355*0Sstevel@tonic-gatetest (overload::Method($aI,'0+') eq \&Oscalar::numify); # 107
356*0Sstevel@tonic-gatetest (overload::Overloaded($aI)); # 108
357*0Sstevel@tonic-gatetest (!overload::Overloaded('overload')); # 109
358*0Sstevel@tonic-gate
359*0Sstevel@tonic-gatetest (! defined overload::Method($aI, '<<')); # 110
360*0Sstevel@tonic-gatetest (! defined overload::Method($a, '<')); # 111
361*0Sstevel@tonic-gate
362*0Sstevel@tonic-gatetest (overload::StrVal($aI) =~ /^OscalarI=SCALAR\(0x[\da-fA-F]+\)$/); # 112
363*0Sstevel@tonic-gatetest (overload::StrVal(\$aI) eq "@{[\$aI]}"); # 113
364*0Sstevel@tonic-gate
365*0Sstevel@tonic-gate# Check overloading by methods (specified deep in the ISA tree).
366*0Sstevel@tonic-gate{
367*0Sstevel@tonic-gate  package OscalarII;
368*0Sstevel@tonic-gate  @ISA = 'OscalarI';
369*0Sstevel@tonic-gate  sub Oscalar::lshft {"_<<_" . shift() . "_<<_"}
370*0Sstevel@tonic-gate  eval "package OscalarI; use overload '<<' => 'lshft', '|' => 'lshft'";
371*0Sstevel@tonic-gate}
372*0Sstevel@tonic-gate
373*0Sstevel@tonic-gate$aaII = "087";
374*0Sstevel@tonic-gate$aII = \$aaII;
375*0Sstevel@tonic-gatebless $aII, 'OscalarII';
376*0Sstevel@tonic-gatebless \$fake, 'OscalarI';		# update the hash
377*0Sstevel@tonic-gatetest(($aI | 3) eq '_<<_xx_<<_');	# 114
378*0Sstevel@tonic-gate# warn $aII << 3;
379*0Sstevel@tonic-gatetest(($aII << 3) eq '_<<_087_<<_');	# 115
380*0Sstevel@tonic-gate
381*0Sstevel@tonic-gate{
382*0Sstevel@tonic-gate  BEGIN { $int = 7; overload::constant 'integer' => sub {$int++; shift}; }
383*0Sstevel@tonic-gate  $out = 2**10;
384*0Sstevel@tonic-gate}
385*0Sstevel@tonic-gatetest($int, 9);		# 116
386*0Sstevel@tonic-gatetest($out, 1024);		# 117
387*0Sstevel@tonic-gate
388*0Sstevel@tonic-gate$foo = 'foo';
389*0Sstevel@tonic-gate$foo1 = 'f\'o\\o';
390*0Sstevel@tonic-gate{
391*0Sstevel@tonic-gate  BEGIN { $q = $qr = 7; 
392*0Sstevel@tonic-gate	  overload::constant 'q' => sub {$q++; push @q, shift, ($_[1] || 'none'); shift},
393*0Sstevel@tonic-gate			     'qr' => sub {$qr++; push @qr, shift, ($_[1] || 'none'); shift}; }
394*0Sstevel@tonic-gate  $out = 'foo';
395*0Sstevel@tonic-gate  $out1 = 'f\'o\\o';
396*0Sstevel@tonic-gate  $out2 = "a\a$foo,\,";
397*0Sstevel@tonic-gate  /b\b$foo.\./;
398*0Sstevel@tonic-gate}
399*0Sstevel@tonic-gate
400*0Sstevel@tonic-gatetest($out, 'foo');		# 118
401*0Sstevel@tonic-gatetest($out, $foo);		# 119
402*0Sstevel@tonic-gatetest($out1, 'f\'o\\o');		# 120
403*0Sstevel@tonic-gatetest($out1, $foo1);		# 121
404*0Sstevel@tonic-gatetest($out2, "a\afoo,\,");	# 122
405*0Sstevel@tonic-gatetest("@q", "foo q f'o\\\\o q a\\a qq ,\\, qq");	# 123
406*0Sstevel@tonic-gatetest($q, 11);			# 124
407*0Sstevel@tonic-gatetest("@qr", "b\\b qq .\\. qq");	# 125
408*0Sstevel@tonic-gatetest($qr, 9);			# 126
409*0Sstevel@tonic-gate
410*0Sstevel@tonic-gate{
411*0Sstevel@tonic-gate  $_ = '!<b>!foo!<-.>!';
412*0Sstevel@tonic-gate  BEGIN { overload::constant 'q' => sub {push @q1, shift, ($_[1] || 'none'); "_<" . (shift) . ">_"},
413*0Sstevel@tonic-gate			     'qr' => sub {push @qr1, shift, ($_[1] || 'none'); "!<" . (shift) . ">!"}; }
414*0Sstevel@tonic-gate  $out = 'foo';
415*0Sstevel@tonic-gate  $out1 = 'f\'o\\o';
416*0Sstevel@tonic-gate  $out2 = "a\a$foo,\,";
417*0Sstevel@tonic-gate  $res = /b\b$foo.\./;
418*0Sstevel@tonic-gate  $a = <<EOF;
419*0Sstevel@tonic-gateoups
420*0Sstevel@tonic-gateEOF
421*0Sstevel@tonic-gate  $b = <<'EOF';
422*0Sstevel@tonic-gateoups1
423*0Sstevel@tonic-gateEOF
424*0Sstevel@tonic-gate  $c = bareword;
425*0Sstevel@tonic-gate  m'try it';
426*0Sstevel@tonic-gate  s'first part'second part';
427*0Sstevel@tonic-gate  s/yet another/tail here/;
428*0Sstevel@tonic-gate  tr/A-Z/a-z/;
429*0Sstevel@tonic-gate}
430*0Sstevel@tonic-gate
431*0Sstevel@tonic-gatetest($out, '_<foo>_');		# 117
432*0Sstevel@tonic-gatetest($out1, '_<f\'o\\o>_');		# 128
433*0Sstevel@tonic-gatetest($out2, "_<a\a>_foo_<,\,>_");	# 129
434*0Sstevel@tonic-gatetest("@q1", "foo q f'o\\\\o q a\\a qq ,\\, qq oups
435*0Sstevel@tonic-gate qq oups1
436*0Sstevel@tonic-gate q second part q tail here s A-Z tr a-z tr");	# 130
437*0Sstevel@tonic-gatetest("@qr1", "b\\b qq .\\. qq try it q first part q yet another qq");	# 131
438*0Sstevel@tonic-gatetest($res, 1);			# 132
439*0Sstevel@tonic-gatetest($a, "_<oups
440*0Sstevel@tonic-gate>_");	# 133
441*0Sstevel@tonic-gatetest($b, "_<oups1
442*0Sstevel@tonic-gate>_");	# 134
443*0Sstevel@tonic-gatetest($c, "bareword");	# 135
444*0Sstevel@tonic-gate
445*0Sstevel@tonic-gate{
446*0Sstevel@tonic-gate  package symbolic;		# Primitive symbolic calculator
447*0Sstevel@tonic-gate  use overload nomethod => \&wrap, '""' => \&str, '0+' => \&num,
448*0Sstevel@tonic-gate      '=' => \&cpy, '++' => \&inc, '--' => \&dec;
449*0Sstevel@tonic-gate
450*0Sstevel@tonic-gate  sub new { shift; bless ['n', @_] }
451*0Sstevel@tonic-gate  sub cpy {
452*0Sstevel@tonic-gate    my $self = shift;
453*0Sstevel@tonic-gate    bless [@$self], ref $self;
454*0Sstevel@tonic-gate  }
455*0Sstevel@tonic-gate  sub inc { $_[0] = bless ['++', $_[0], 1]; }
456*0Sstevel@tonic-gate  sub dec { $_[0] = bless ['--', $_[0], 1]; }
457*0Sstevel@tonic-gate  sub wrap {
458*0Sstevel@tonic-gate    my ($obj, $other, $inv, $meth) = @_;
459*0Sstevel@tonic-gate    if ($meth eq '++' or $meth eq '--') {
460*0Sstevel@tonic-gate      @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference
461*0Sstevel@tonic-gate      return $obj;
462*0Sstevel@tonic-gate    }
463*0Sstevel@tonic-gate    ($obj, $other) = ($other, $obj) if $inv;
464*0Sstevel@tonic-gate    bless [$meth, $obj, $other];
465*0Sstevel@tonic-gate  }
466*0Sstevel@tonic-gate  sub str {
467*0Sstevel@tonic-gate    my ($meth, $a, $b) = @{+shift};
468*0Sstevel@tonic-gate    $a = 'u' unless defined $a;
469*0Sstevel@tonic-gate    if (defined $b) {
470*0Sstevel@tonic-gate      "[$meth $a $b]";
471*0Sstevel@tonic-gate    } else {
472*0Sstevel@tonic-gate      "[$meth $a]";
473*0Sstevel@tonic-gate    }
474*0Sstevel@tonic-gate  } 
475*0Sstevel@tonic-gate  my %subr = ( 'n' => sub {$_[0]} );
476*0Sstevel@tonic-gate  foreach my $op (split " ", $overload::ops{with_assign}) {
477*0Sstevel@tonic-gate    $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
478*0Sstevel@tonic-gate  }
479*0Sstevel@tonic-gate  my @bins = qw(binary 3way_comparison num_comparison str_comparison);
480*0Sstevel@tonic-gate  foreach my $op (split " ", "@overload::ops{ @bins }") {
481*0Sstevel@tonic-gate    $subr{$op} = eval "sub {shift() $op shift()}";
482*0Sstevel@tonic-gate  }
483*0Sstevel@tonic-gate  foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
484*0Sstevel@tonic-gate    $subr{$op} = eval "sub {$op shift()}";
485*0Sstevel@tonic-gate  }
486*0Sstevel@tonic-gate  $subr{'++'} = $subr{'+'};
487*0Sstevel@tonic-gate  $subr{'--'} = $subr{'-'};
488*0Sstevel@tonic-gate  
489*0Sstevel@tonic-gate  sub num {
490*0Sstevel@tonic-gate    my ($meth, $a, $b) = @{+shift};
491*0Sstevel@tonic-gate    my $subr = $subr{$meth} 
492*0Sstevel@tonic-gate      or die "Do not know how to ($meth) in symbolic";
493*0Sstevel@tonic-gate    $a = $a->num if ref $a eq __PACKAGE__;
494*0Sstevel@tonic-gate    $b = $b->num if ref $b eq __PACKAGE__;
495*0Sstevel@tonic-gate    $subr->($a,$b);
496*0Sstevel@tonic-gate  }
497*0Sstevel@tonic-gate  sub TIESCALAR { my $pack = shift; $pack->new(@_) }
498*0Sstevel@tonic-gate  sub FETCH { shift }
499*0Sstevel@tonic-gate  sub nop {  }		# Around a bug
500*0Sstevel@tonic-gate  sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; }
501*0Sstevel@tonic-gate  sub STORE { 
502*0Sstevel@tonic-gate    my $obj = shift; 
503*0Sstevel@tonic-gate    $#$obj = 1; 
504*0Sstevel@tonic-gate    $obj->[1] = shift;
505*0Sstevel@tonic-gate  }
506*0Sstevel@tonic-gate}
507*0Sstevel@tonic-gate
508*0Sstevel@tonic-gate{
509*0Sstevel@tonic-gate  my $foo = new symbolic 11;
510*0Sstevel@tonic-gate  my $baz = $foo++;
511*0Sstevel@tonic-gate  test( (sprintf "%d", $foo), '12');
512*0Sstevel@tonic-gate  test( (sprintf "%d", $baz), '11');
513*0Sstevel@tonic-gate  my $bar = $foo;
514*0Sstevel@tonic-gate  $baz = ++$foo;
515*0Sstevel@tonic-gate  test( (sprintf "%d", $foo), '13');
516*0Sstevel@tonic-gate  test( (sprintf "%d", $bar), '12');
517*0Sstevel@tonic-gate  test( (sprintf "%d", $baz), '13');
518*0Sstevel@tonic-gate  my $ban = $foo;
519*0Sstevel@tonic-gate  $baz = ($foo += 1);
520*0Sstevel@tonic-gate  test( (sprintf "%d", $foo), '14');
521*0Sstevel@tonic-gate  test( (sprintf "%d", $bar), '12');
522*0Sstevel@tonic-gate  test( (sprintf "%d", $baz), '14');
523*0Sstevel@tonic-gate  test( (sprintf "%d", $ban), '13');
524*0Sstevel@tonic-gate  $baz = 0;
525*0Sstevel@tonic-gate  $baz = $foo++;
526*0Sstevel@tonic-gate  test( (sprintf "%d", $foo), '15');
527*0Sstevel@tonic-gate  test( (sprintf "%d", $baz), '14');
528*0Sstevel@tonic-gate  test( "$foo", '[++ [+= [++ [++ [n 11] 1] 1] 1] 1]');
529*0Sstevel@tonic-gate}
530*0Sstevel@tonic-gate
531*0Sstevel@tonic-gate{
532*0Sstevel@tonic-gate  my $iter = new symbolic 2;
533*0Sstevel@tonic-gate  my $side = new symbolic 1;
534*0Sstevel@tonic-gate  my $cnt = $iter;
535*0Sstevel@tonic-gate  
536*0Sstevel@tonic-gate  while ($cnt) {
537*0Sstevel@tonic-gate    $cnt = $cnt - 1;		# The "simple" way
538*0Sstevel@tonic-gate    $side = (sqrt(1 + $side**2) - 1)/$side;
539*0Sstevel@tonic-gate  }
540*0Sstevel@tonic-gate  my $pi = $side*(2**($iter+2));
541*0Sstevel@tonic-gate  test "$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]';
542*0Sstevel@tonic-gate  test( (sprintf "%f", $pi), '3.182598');
543*0Sstevel@tonic-gate}
544*0Sstevel@tonic-gate
545*0Sstevel@tonic-gate{
546*0Sstevel@tonic-gate  my $iter = new symbolic 2;
547*0Sstevel@tonic-gate  my $side = new symbolic 1;
548*0Sstevel@tonic-gate  my $cnt = $iter;
549*0Sstevel@tonic-gate  
550*0Sstevel@tonic-gate  while ($cnt--) {
551*0Sstevel@tonic-gate    $side = (sqrt(1 + $side**2) - 1)/$side;
552*0Sstevel@tonic-gate  }
553*0Sstevel@tonic-gate  my $pi = $side*(2**($iter+2));
554*0Sstevel@tonic-gate  test "$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]';
555*0Sstevel@tonic-gate  test( (sprintf "%f", $pi), '3.182598');
556*0Sstevel@tonic-gate}
557*0Sstevel@tonic-gate
558*0Sstevel@tonic-gate{
559*0Sstevel@tonic-gate  my ($a, $b);
560*0Sstevel@tonic-gate  symbolic->vars($a, $b);
561*0Sstevel@tonic-gate  my $c = sqrt($a**2 + $b**2);
562*0Sstevel@tonic-gate  $a = 3; $b = 4;
563*0Sstevel@tonic-gate  test( (sprintf "%d", $c), '5');
564*0Sstevel@tonic-gate  $a = 12; $b = 5;
565*0Sstevel@tonic-gate  test( (sprintf "%d", $c), '13');
566*0Sstevel@tonic-gate}
567*0Sstevel@tonic-gate
568*0Sstevel@tonic-gate{
569*0Sstevel@tonic-gate  package symbolic1;		# Primitive symbolic calculator
570*0Sstevel@tonic-gate  # Mutator inc/dec
571*0Sstevel@tonic-gate  use overload nomethod => \&wrap, '""' => \&str, '0+' => \&num, '=' => \&cpy;
572*0Sstevel@tonic-gate
573*0Sstevel@tonic-gate  sub new { shift; bless ['n', @_] }
574*0Sstevel@tonic-gate  sub cpy {
575*0Sstevel@tonic-gate    my $self = shift;
576*0Sstevel@tonic-gate    bless [@$self], ref $self;
577*0Sstevel@tonic-gate  }
578*0Sstevel@tonic-gate  sub wrap {
579*0Sstevel@tonic-gate    my ($obj, $other, $inv, $meth) = @_;
580*0Sstevel@tonic-gate    if ($meth eq '++' or $meth eq '--') {
581*0Sstevel@tonic-gate      @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference
582*0Sstevel@tonic-gate      return $obj;
583*0Sstevel@tonic-gate    }
584*0Sstevel@tonic-gate    ($obj, $other) = ($other, $obj) if $inv;
585*0Sstevel@tonic-gate    bless [$meth, $obj, $other];
586*0Sstevel@tonic-gate  }
587*0Sstevel@tonic-gate  sub str {
588*0Sstevel@tonic-gate    my ($meth, $a, $b) = @{+shift};
589*0Sstevel@tonic-gate    $a = 'u' unless defined $a;
590*0Sstevel@tonic-gate    if (defined $b) {
591*0Sstevel@tonic-gate      "[$meth $a $b]";
592*0Sstevel@tonic-gate    } else {
593*0Sstevel@tonic-gate      "[$meth $a]";
594*0Sstevel@tonic-gate    }
595*0Sstevel@tonic-gate  } 
596*0Sstevel@tonic-gate  my %subr = ( 'n' => sub {$_[0]} );
597*0Sstevel@tonic-gate  foreach my $op (split " ", $overload::ops{with_assign}) {
598*0Sstevel@tonic-gate    $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
599*0Sstevel@tonic-gate  }
600*0Sstevel@tonic-gate  my @bins = qw(binary 3way_comparison num_comparison str_comparison);
601*0Sstevel@tonic-gate  foreach my $op (split " ", "@overload::ops{ @bins }") {
602*0Sstevel@tonic-gate    $subr{$op} = eval "sub {shift() $op shift()}";
603*0Sstevel@tonic-gate  }
604*0Sstevel@tonic-gate  foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
605*0Sstevel@tonic-gate    $subr{$op} = eval "sub {$op shift()}";
606*0Sstevel@tonic-gate  }
607*0Sstevel@tonic-gate  $subr{'++'} = $subr{'+'};
608*0Sstevel@tonic-gate  $subr{'--'} = $subr{'-'};
609*0Sstevel@tonic-gate  
610*0Sstevel@tonic-gate  sub num {
611*0Sstevel@tonic-gate    my ($meth, $a, $b) = @{+shift};
612*0Sstevel@tonic-gate    my $subr = $subr{$meth} 
613*0Sstevel@tonic-gate      or die "Do not know how to ($meth) in symbolic";
614*0Sstevel@tonic-gate    $a = $a->num if ref $a eq __PACKAGE__;
615*0Sstevel@tonic-gate    $b = $b->num if ref $b eq __PACKAGE__;
616*0Sstevel@tonic-gate    $subr->($a,$b);
617*0Sstevel@tonic-gate  }
618*0Sstevel@tonic-gate  sub TIESCALAR { my $pack = shift; $pack->new(@_) }
619*0Sstevel@tonic-gate  sub FETCH { shift }
620*0Sstevel@tonic-gate  sub nop {  }		# Around a bug
621*0Sstevel@tonic-gate  sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; }
622*0Sstevel@tonic-gate  sub STORE { 
623*0Sstevel@tonic-gate    my $obj = shift; 
624*0Sstevel@tonic-gate    $#$obj = 1; 
625*0Sstevel@tonic-gate    $obj->[1] = shift;
626*0Sstevel@tonic-gate  }
627*0Sstevel@tonic-gate}
628*0Sstevel@tonic-gate
629*0Sstevel@tonic-gate{
630*0Sstevel@tonic-gate  my $foo = new symbolic1 11;
631*0Sstevel@tonic-gate  my $baz = $foo++;
632*0Sstevel@tonic-gate  test( (sprintf "%d", $foo), '12');
633*0Sstevel@tonic-gate  test( (sprintf "%d", $baz), '11');
634*0Sstevel@tonic-gate  my $bar = $foo;
635*0Sstevel@tonic-gate  $baz = ++$foo;
636*0Sstevel@tonic-gate  test( (sprintf "%d", $foo), '13');
637*0Sstevel@tonic-gate  test( (sprintf "%d", $bar), '12');
638*0Sstevel@tonic-gate  test( (sprintf "%d", $baz), '13');
639*0Sstevel@tonic-gate  my $ban = $foo;
640*0Sstevel@tonic-gate  $baz = ($foo += 1);
641*0Sstevel@tonic-gate  test( (sprintf "%d", $foo), '14');
642*0Sstevel@tonic-gate  test( (sprintf "%d", $bar), '12');
643*0Sstevel@tonic-gate  test( (sprintf "%d", $baz), '14');
644*0Sstevel@tonic-gate  test( (sprintf "%d", $ban), '13');
645*0Sstevel@tonic-gate  $baz = 0;
646*0Sstevel@tonic-gate  $baz = $foo++;
647*0Sstevel@tonic-gate  test( (sprintf "%d", $foo), '15');
648*0Sstevel@tonic-gate  test( (sprintf "%d", $baz), '14');
649*0Sstevel@tonic-gate  test( "$foo", '[++ [+= [++ [++ [n 11] 1] 1] 1] 1]');
650*0Sstevel@tonic-gate}
651*0Sstevel@tonic-gate
652*0Sstevel@tonic-gate{
653*0Sstevel@tonic-gate  my $iter = new symbolic1 2;
654*0Sstevel@tonic-gate  my $side = new symbolic1 1;
655*0Sstevel@tonic-gate  my $cnt = $iter;
656*0Sstevel@tonic-gate  
657*0Sstevel@tonic-gate  while ($cnt) {
658*0Sstevel@tonic-gate    $cnt = $cnt - 1;		# The "simple" way
659*0Sstevel@tonic-gate    $side = (sqrt(1 + $side**2) - 1)/$side;
660*0Sstevel@tonic-gate  }
661*0Sstevel@tonic-gate  my $pi = $side*(2**($iter+2));
662*0Sstevel@tonic-gate  test "$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]';
663*0Sstevel@tonic-gate  test( (sprintf "%f", $pi), '3.182598');
664*0Sstevel@tonic-gate}
665*0Sstevel@tonic-gate
666*0Sstevel@tonic-gate{
667*0Sstevel@tonic-gate  my $iter = new symbolic1 2;
668*0Sstevel@tonic-gate  my $side = new symbolic1 1;
669*0Sstevel@tonic-gate  my $cnt = $iter;
670*0Sstevel@tonic-gate  
671*0Sstevel@tonic-gate  while ($cnt--) {
672*0Sstevel@tonic-gate    $side = (sqrt(1 + $side**2) - 1)/$side;
673*0Sstevel@tonic-gate  }
674*0Sstevel@tonic-gate  my $pi = $side*(2**($iter+2));
675*0Sstevel@tonic-gate  test "$side", '[/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]] 2]]] 1] [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]';
676*0Sstevel@tonic-gate  test( (sprintf "%f", $pi), '3.182598');
677*0Sstevel@tonic-gate}
678*0Sstevel@tonic-gate
679*0Sstevel@tonic-gate{
680*0Sstevel@tonic-gate  my ($a, $b);
681*0Sstevel@tonic-gate  symbolic1->vars($a, $b);
682*0Sstevel@tonic-gate  my $c = sqrt($a**2 + $b**2);
683*0Sstevel@tonic-gate  $a = 3; $b = 4;
684*0Sstevel@tonic-gate  test( (sprintf "%d", $c), '5');
685*0Sstevel@tonic-gate  $a = 12; $b = 5;
686*0Sstevel@tonic-gate  test( (sprintf "%d", $c), '13');
687*0Sstevel@tonic-gate}
688*0Sstevel@tonic-gate
689*0Sstevel@tonic-gate{
690*0Sstevel@tonic-gate  package two_face;		# Scalars with separate string and
691*0Sstevel@tonic-gate                                # numeric values.
692*0Sstevel@tonic-gate  sub new { my $p = shift; bless [@_], $p }
693*0Sstevel@tonic-gate  use overload '""' => \&str, '0+' => \&num, fallback => 1;
694*0Sstevel@tonic-gate  sub num {shift->[1]}
695*0Sstevel@tonic-gate  sub str {shift->[0]}
696*0Sstevel@tonic-gate}
697*0Sstevel@tonic-gate
698*0Sstevel@tonic-gate{
699*0Sstevel@tonic-gate  my $seven = new two_face ("vii", 7);
700*0Sstevel@tonic-gate  test( (sprintf "seven=$seven, seven=%d, eight=%d", $seven, $seven+1),
701*0Sstevel@tonic-gate	'seven=vii, seven=7, eight=8');
702*0Sstevel@tonic-gate  test( scalar ($seven =~ /i/), '1')
703*0Sstevel@tonic-gate}
704*0Sstevel@tonic-gate
705*0Sstevel@tonic-gate{
706*0Sstevel@tonic-gate  package sorting;
707*0Sstevel@tonic-gate  use overload 'cmp' => \&comp;
708*0Sstevel@tonic-gate  sub new { my ($p, $v) = @_; bless \$v, $p }
709*0Sstevel@tonic-gate  sub comp { my ($x,$y) = @_; ($$x * 3 % 10) <=> ($$y * 3 % 10) or $$x cmp $$y }
710*0Sstevel@tonic-gate}
711*0Sstevel@tonic-gate{
712*0Sstevel@tonic-gate  my @arr = map sorting->new($_), 0..12;
713*0Sstevel@tonic-gate  my @sorted1 = sort @arr;
714*0Sstevel@tonic-gate  my @sorted2 = map $$_, @sorted1;
715*0Sstevel@tonic-gate  test "@sorted2", '0 10 7 4 1 11 8 5 12 2 9 6 3';
716*0Sstevel@tonic-gate}
717*0Sstevel@tonic-gate{
718*0Sstevel@tonic-gate  package iterator;
719*0Sstevel@tonic-gate  use overload '<>' => \&iter;
720*0Sstevel@tonic-gate  sub new { my ($p, $v) = @_; bless \$v, $p }
721*0Sstevel@tonic-gate  sub iter { my ($x) = @_; return undef if $$x < 0; return $$x--; }
722*0Sstevel@tonic-gate}
723*0Sstevel@tonic-gate
724*0Sstevel@tonic-gate# XXX iterator overload not intended to work with CORE::GLOBAL?
725*0Sstevel@tonic-gateif (defined &CORE::GLOBAL::glob) {
726*0Sstevel@tonic-gate  test '1', '1';	# 175
727*0Sstevel@tonic-gate  test '1', '1';	# 176
728*0Sstevel@tonic-gate  test '1', '1';	# 177
729*0Sstevel@tonic-gate}
730*0Sstevel@tonic-gateelse {
731*0Sstevel@tonic-gate  my $iter = iterator->new(5);
732*0Sstevel@tonic-gate  my $acc = '';
733*0Sstevel@tonic-gate  my $out;
734*0Sstevel@tonic-gate  $acc .= " $out" while $out = <${iter}>;
735*0Sstevel@tonic-gate  test $acc, ' 5 4 3 2 1 0';	# 175
736*0Sstevel@tonic-gate  $iter = iterator->new(5);
737*0Sstevel@tonic-gate  test scalar <${iter}>, '5';	# 176
738*0Sstevel@tonic-gate  $acc = '';
739*0Sstevel@tonic-gate  $acc .= " $out" while $out = <$iter>;
740*0Sstevel@tonic-gate  test $acc, ' 4 3 2 1 0';	# 177
741*0Sstevel@tonic-gate}
742*0Sstevel@tonic-gate{
743*0Sstevel@tonic-gate  package deref;
744*0Sstevel@tonic-gate  use overload '%{}' => \&hderef, '&{}' => \&cderef, 
745*0Sstevel@tonic-gate    '*{}' => \&gderef, '${}' => \&sderef, '@{}' => \&aderef;
746*0Sstevel@tonic-gate  sub new { my ($p, $v) = @_; bless \$v, $p }
747*0Sstevel@tonic-gate  sub deref {
748*0Sstevel@tonic-gate    my ($self, $key) = (shift, shift);
749*0Sstevel@tonic-gate    my $class = ref $self;
750*0Sstevel@tonic-gate    bless $self, 'deref::dummy'; # Disable overloading of %{} 
751*0Sstevel@tonic-gate    my $out = $self->{$key};
752*0Sstevel@tonic-gate    bless $self, $class;	# Restore overloading
753*0Sstevel@tonic-gate    $out;
754*0Sstevel@tonic-gate  }
755*0Sstevel@tonic-gate  sub hderef {shift->deref('h')}
756*0Sstevel@tonic-gate  sub aderef {shift->deref('a')}
757*0Sstevel@tonic-gate  sub cderef {shift->deref('c')}
758*0Sstevel@tonic-gate  sub gderef {shift->deref('g')}
759*0Sstevel@tonic-gate  sub sderef {shift->deref('s')}
760*0Sstevel@tonic-gate}
761*0Sstevel@tonic-gate{
762*0Sstevel@tonic-gate  my $deref = bless { h => { foo => 5 , fake => 23 },
763*0Sstevel@tonic-gate		      c => sub {return shift() + 34},
764*0Sstevel@tonic-gate		      's' => \123,
765*0Sstevel@tonic-gate		      a => [11..13],
766*0Sstevel@tonic-gate		      g => \*srt,
767*0Sstevel@tonic-gate		    }, 'deref';
768*0Sstevel@tonic-gate  # Hash:
769*0Sstevel@tonic-gate  my @cont = sort %$deref;
770*0Sstevel@tonic-gate  if ("\t" eq "\011") { # ascii
771*0Sstevel@tonic-gate      test "@cont", '23 5 fake foo';	# 178
772*0Sstevel@tonic-gate  } 
773*0Sstevel@tonic-gate  else {                # ebcdic alpha-numeric sort order
774*0Sstevel@tonic-gate      test "@cont", 'fake foo 23 5';	# 178
775*0Sstevel@tonic-gate  }
776*0Sstevel@tonic-gate  my @keys = sort keys %$deref;
777*0Sstevel@tonic-gate  test "@keys", 'fake foo';	# 179
778*0Sstevel@tonic-gate  my @val = sort values %$deref;
779*0Sstevel@tonic-gate  test "@val", '23 5';		# 180
780*0Sstevel@tonic-gate  test $deref->{foo}, 5;	# 181
781*0Sstevel@tonic-gate  test defined $deref->{bar}, ''; # 182
782*0Sstevel@tonic-gate  my $key;
783*0Sstevel@tonic-gate  @keys = ();
784*0Sstevel@tonic-gate  push @keys, $key while $key = each %$deref;
785*0Sstevel@tonic-gate  @keys = sort @keys;
786*0Sstevel@tonic-gate  test "@keys", 'fake foo';	# 183  
787*0Sstevel@tonic-gate  test exists $deref->{bar}, ''; # 184
788*0Sstevel@tonic-gate  test exists $deref->{foo}, 1; # 185
789*0Sstevel@tonic-gate  # Code:
790*0Sstevel@tonic-gate  test $deref->(5), 39;		# 186
791*0Sstevel@tonic-gate  test &$deref(6), 40;		# 187
792*0Sstevel@tonic-gate  sub xxx_goto { goto &$deref }
793*0Sstevel@tonic-gate  test xxx_goto(7), 41;		# 188
794*0Sstevel@tonic-gate  my $srt = bless { c => sub {$b <=> $a}
795*0Sstevel@tonic-gate		  }, 'deref';
796*0Sstevel@tonic-gate  *srt = \&$srt;
797*0Sstevel@tonic-gate  my @sorted = sort srt 11, 2, 5, 1, 22;
798*0Sstevel@tonic-gate  test "@sorted", '22 11 5 2 1'; # 189
799*0Sstevel@tonic-gate  # Scalar
800*0Sstevel@tonic-gate  test $$deref, 123;		# 190
801*0Sstevel@tonic-gate  # Code
802*0Sstevel@tonic-gate  @sorted = sort $srt 11, 2, 5, 1, 22;
803*0Sstevel@tonic-gate  test "@sorted", '22 11 5 2 1'; # 191
804*0Sstevel@tonic-gate  # Array
805*0Sstevel@tonic-gate  test "@$deref", '11 12 13';	# 192
806*0Sstevel@tonic-gate  test $#$deref, '2';		# 193
807*0Sstevel@tonic-gate  my $l = @$deref;
808*0Sstevel@tonic-gate  test $l, 3;			# 194
809*0Sstevel@tonic-gate  test $deref->[2], '13';		# 195
810*0Sstevel@tonic-gate  $l = pop @$deref;
811*0Sstevel@tonic-gate  test $l, 13;			# 196
812*0Sstevel@tonic-gate  $l = 1;
813*0Sstevel@tonic-gate  test $deref->[$l], '12';	# 197
814*0Sstevel@tonic-gate  # Repeated dereference
815*0Sstevel@tonic-gate  my $double = bless { h => $deref,
816*0Sstevel@tonic-gate		     }, 'deref';
817*0Sstevel@tonic-gate  test $double->{foo}, 5;	# 198
818*0Sstevel@tonic-gate}
819*0Sstevel@tonic-gate
820*0Sstevel@tonic-gate{
821*0Sstevel@tonic-gate  package two_refs;
822*0Sstevel@tonic-gate  use overload '%{}' => \&gethash, '@{}' => sub { ${shift()} };
823*0Sstevel@tonic-gate  sub new { 
824*0Sstevel@tonic-gate    my $p = shift; 
825*0Sstevel@tonic-gate    bless \ [@_], $p;
826*0Sstevel@tonic-gate  }
827*0Sstevel@tonic-gate  sub gethash {
828*0Sstevel@tonic-gate    my %h;
829*0Sstevel@tonic-gate    my $self = shift;
830*0Sstevel@tonic-gate    tie %h, ref $self, $self;
831*0Sstevel@tonic-gate    \%h;
832*0Sstevel@tonic-gate  }
833*0Sstevel@tonic-gate
834*0Sstevel@tonic-gate  sub TIEHASH { my $p = shift; bless \ shift, $p }
835*0Sstevel@tonic-gate  my %fields;
836*0Sstevel@tonic-gate  my $i = 0;
837*0Sstevel@tonic-gate  $fields{$_} = $i++ foreach qw{zero one two three};
838*0Sstevel@tonic-gate  sub STORE { 
839*0Sstevel@tonic-gate    my $self = ${shift()};
840*0Sstevel@tonic-gate    my $key = $fields{shift()};
841*0Sstevel@tonic-gate    defined $key or die "Out of band access";
842*0Sstevel@tonic-gate    $$self->[$key] = shift;
843*0Sstevel@tonic-gate  }
844*0Sstevel@tonic-gate  sub FETCH { 
845*0Sstevel@tonic-gate    my $self = ${shift()};
846*0Sstevel@tonic-gate    my $key = $fields{shift()};
847*0Sstevel@tonic-gate    defined $key or die "Out of band access";
848*0Sstevel@tonic-gate    $$self->[$key];
849*0Sstevel@tonic-gate  }
850*0Sstevel@tonic-gate}
851*0Sstevel@tonic-gate
852*0Sstevel@tonic-gatemy $bar = new two_refs 3,4,5,6;
853*0Sstevel@tonic-gate$bar->[2] = 11;
854*0Sstevel@tonic-gatetest $bar->{two}, 11;		# 199
855*0Sstevel@tonic-gate$bar->{three} = 13;
856*0Sstevel@tonic-gatetest $bar->[3], 13;		# 200
857*0Sstevel@tonic-gate
858*0Sstevel@tonic-gate{
859*0Sstevel@tonic-gate  package two_refs_o;
860*0Sstevel@tonic-gate  @ISA = ('two_refs');
861*0Sstevel@tonic-gate}
862*0Sstevel@tonic-gate
863*0Sstevel@tonic-gate$bar = new two_refs_o 3,4,5,6;
864*0Sstevel@tonic-gate$bar->[2] = 11;
865*0Sstevel@tonic-gatetest $bar->{two}, 11;		# 201
866*0Sstevel@tonic-gate$bar->{three} = 13;
867*0Sstevel@tonic-gatetest $bar->[3], 13;		# 202
868*0Sstevel@tonic-gate
869*0Sstevel@tonic-gate{
870*0Sstevel@tonic-gate  package two_refs1;
871*0Sstevel@tonic-gate  use overload '%{}' => sub { ${shift()}->[1] },
872*0Sstevel@tonic-gate               '@{}' => sub { ${shift()}->[0] };
873*0Sstevel@tonic-gate  sub new { 
874*0Sstevel@tonic-gate    my $p = shift; 
875*0Sstevel@tonic-gate    my $a = [@_];
876*0Sstevel@tonic-gate    my %h;
877*0Sstevel@tonic-gate    tie %h, $p, $a;
878*0Sstevel@tonic-gate    bless \ [$a, \%h], $p;
879*0Sstevel@tonic-gate  }
880*0Sstevel@tonic-gate  sub gethash {
881*0Sstevel@tonic-gate    my %h;
882*0Sstevel@tonic-gate    my $self = shift;
883*0Sstevel@tonic-gate    tie %h, ref $self, $self;
884*0Sstevel@tonic-gate    \%h;
885*0Sstevel@tonic-gate  }
886*0Sstevel@tonic-gate
887*0Sstevel@tonic-gate  sub TIEHASH { my $p = shift; bless \ shift, $p }
888*0Sstevel@tonic-gate  my %fields;
889*0Sstevel@tonic-gate  my $i = 0;
890*0Sstevel@tonic-gate  $fields{$_} = $i++ foreach qw{zero one two three};
891*0Sstevel@tonic-gate  sub STORE { 
892*0Sstevel@tonic-gate    my $a = ${shift()};
893*0Sstevel@tonic-gate    my $key = $fields{shift()};
894*0Sstevel@tonic-gate    defined $key or die "Out of band access";
895*0Sstevel@tonic-gate    $a->[$key] = shift;
896*0Sstevel@tonic-gate  }
897*0Sstevel@tonic-gate  sub FETCH { 
898*0Sstevel@tonic-gate    my $a = ${shift()};
899*0Sstevel@tonic-gate    my $key = $fields{shift()};
900*0Sstevel@tonic-gate    defined $key or die "Out of band access";
901*0Sstevel@tonic-gate    $a->[$key];
902*0Sstevel@tonic-gate  }
903*0Sstevel@tonic-gate}
904*0Sstevel@tonic-gate
905*0Sstevel@tonic-gate$bar = new two_refs_o 3,4,5,6;
906*0Sstevel@tonic-gate$bar->[2] = 11;
907*0Sstevel@tonic-gatetest $bar->{two}, 11;		# 203
908*0Sstevel@tonic-gate$bar->{three} = 13;
909*0Sstevel@tonic-gatetest $bar->[3], 13;		# 204
910*0Sstevel@tonic-gate
911*0Sstevel@tonic-gate{
912*0Sstevel@tonic-gate  package two_refs1_o;
913*0Sstevel@tonic-gate  @ISA = ('two_refs1');
914*0Sstevel@tonic-gate}
915*0Sstevel@tonic-gate
916*0Sstevel@tonic-gate$bar = new two_refs1_o 3,4,5,6;
917*0Sstevel@tonic-gate$bar->[2] = 11;
918*0Sstevel@tonic-gatetest $bar->{two}, 11;		# 205
919*0Sstevel@tonic-gate$bar->{three} = 13;
920*0Sstevel@tonic-gatetest $bar->[3], 13;		# 206
921*0Sstevel@tonic-gate
922*0Sstevel@tonic-gate{
923*0Sstevel@tonic-gate  package B;
924*0Sstevel@tonic-gate  use overload bool => sub { ${+shift} };
925*0Sstevel@tonic-gate}
926*0Sstevel@tonic-gate
927*0Sstevel@tonic-gatemy $aaa;
928*0Sstevel@tonic-gate{ my $bbbb = 0; $aaa = bless \$bbbb, B }
929*0Sstevel@tonic-gate
930*0Sstevel@tonic-gatetest !$aaa, 1;			# 207
931*0Sstevel@tonic-gate
932*0Sstevel@tonic-gateunless ($aaa) {
933*0Sstevel@tonic-gate  test 'ok', 'ok';		# 208
934*0Sstevel@tonic-gate} else {
935*0Sstevel@tonic-gate  test 'is not', 'ok';		# 208
936*0Sstevel@tonic-gate}
937*0Sstevel@tonic-gate
938*0Sstevel@tonic-gate# check that overload isn't done twice by join
939*0Sstevel@tonic-gate{ my $c = 0;
940*0Sstevel@tonic-gate  package Join;
941*0Sstevel@tonic-gate  use overload '""' => sub { $c++ };
942*0Sstevel@tonic-gate  my $x = join '', bless([]), 'pq', bless([]);
943*0Sstevel@tonic-gate  main::test $x, '0pq1';		# 209
944*0Sstevel@tonic-gate};
945*0Sstevel@tonic-gate
946*0Sstevel@tonic-gate# Test module-specific warning
947*0Sstevel@tonic-gate{
948*0Sstevel@tonic-gate    # check the Odd number of arguments for overload::constant warning
949*0Sstevel@tonic-gate    my $a = "" ;
950*0Sstevel@tonic-gate    local $SIG{__WARN__} = sub {$a = $_[0]} ;
951*0Sstevel@tonic-gate    $x = eval ' overload::constant "integer" ; ' ;
952*0Sstevel@tonic-gate    test($a eq "") ; # 210
953*0Sstevel@tonic-gate    use warnings 'overload' ;
954*0Sstevel@tonic-gate    $x = eval ' overload::constant "integer" ; ' ;
955*0Sstevel@tonic-gate    test($a =~ /^Odd number of arguments for overload::constant at/) ; # 211
956*0Sstevel@tonic-gate}
957*0Sstevel@tonic-gate
958*0Sstevel@tonic-gate{
959*0Sstevel@tonic-gate    # check the `$_[0]' is not an overloadable type warning
960*0Sstevel@tonic-gate    my $a = "" ;
961*0Sstevel@tonic-gate    local $SIG{__WARN__} = sub {$a = $_[0]} ;
962*0Sstevel@tonic-gate    $x = eval ' overload::constant "fred" => sub {} ; ' ;
963*0Sstevel@tonic-gate    test($a eq "") ; # 212
964*0Sstevel@tonic-gate    use warnings 'overload' ;
965*0Sstevel@tonic-gate    $x = eval ' overload::constant "fred" => sub {} ; ' ;
966*0Sstevel@tonic-gate    test($a =~ /^`fred' is not an overloadable type at/); # 213
967*0Sstevel@tonic-gate}
968*0Sstevel@tonic-gate
969*0Sstevel@tonic-gate{
970*0Sstevel@tonic-gate    # check the `$_[1]' is not a code reference warning
971*0Sstevel@tonic-gate    my $a = "" ;
972*0Sstevel@tonic-gate    local $SIG{__WARN__} = sub {$a = $_[0]} ;
973*0Sstevel@tonic-gate    $x = eval ' overload::constant "integer" => 1; ' ;
974*0Sstevel@tonic-gate    test($a eq "") ; # 214
975*0Sstevel@tonic-gate    use warnings 'overload' ;
976*0Sstevel@tonic-gate    $x = eval ' overload::constant "integer" => 1; ' ;
977*0Sstevel@tonic-gate    test($a =~ /^`1' is not a code reference at/); # 215
978*0Sstevel@tonic-gate}
979*0Sstevel@tonic-gate
980*0Sstevel@tonic-gate{
981*0Sstevel@tonic-gate  my $c = 0;
982*0Sstevel@tonic-gate  package ov_int1;
983*0Sstevel@tonic-gate  use overload '""'    => sub { 3+shift->[0] },
984*0Sstevel@tonic-gate               '0+'    => sub { 10+shift->[0] },
985*0Sstevel@tonic-gate               'int'   => sub { 100+shift->[0] };
986*0Sstevel@tonic-gate  sub new {my $p = shift; bless [shift], $p}
987*0Sstevel@tonic-gate
988*0Sstevel@tonic-gate  package ov_int2;
989*0Sstevel@tonic-gate  use overload '""'    => sub { 5+shift->[0] },
990*0Sstevel@tonic-gate               '0+'    => sub { 30+shift->[0] },
991*0Sstevel@tonic-gate               'int'   => sub { 'ov_int1'->new(1000+shift->[0]) };
992*0Sstevel@tonic-gate  sub new {my $p = shift; bless [shift], $p}
993*0Sstevel@tonic-gate
994*0Sstevel@tonic-gate  package noov_int;
995*0Sstevel@tonic-gate  use overload '""'    => sub { 2+shift->[0] },
996*0Sstevel@tonic-gate               '0+'    => sub { 9+shift->[0] };
997*0Sstevel@tonic-gate  sub new {my $p = shift; bless [shift], $p}
998*0Sstevel@tonic-gate
999*0Sstevel@tonic-gate  package main;
1000*0Sstevel@tonic-gate
1001*0Sstevel@tonic-gate  my $x = new noov_int 11;
1002*0Sstevel@tonic-gate  my $int_x = int $x;
1003*0Sstevel@tonic-gate  main::test("$int_x" eq 20);			# 216
1004*0Sstevel@tonic-gate  $x = new ov_int1 31;
1005*0Sstevel@tonic-gate  $int_x = int $x;
1006*0Sstevel@tonic-gate  main::test("$int_x" eq 131);			# 217
1007*0Sstevel@tonic-gate  $x = new ov_int2 51;
1008*0Sstevel@tonic-gate  $int_x = int $x;
1009*0Sstevel@tonic-gate  main::test("$int_x" eq 1054);			# 218
1010*0Sstevel@tonic-gate}
1011*0Sstevel@tonic-gate
1012*0Sstevel@tonic-gate# make sure that we don't inifinitely recurse
1013*0Sstevel@tonic-gate{
1014*0Sstevel@tonic-gate  my $c = 0;
1015*0Sstevel@tonic-gate  package Recurse;
1016*0Sstevel@tonic-gate  use overload '""'    => sub { shift },
1017*0Sstevel@tonic-gate               '0+'    => sub { shift },
1018*0Sstevel@tonic-gate               'bool'  => sub { shift },
1019*0Sstevel@tonic-gate               fallback => 1;
1020*0Sstevel@tonic-gate  my $x = bless([]);
1021*0Sstevel@tonic-gate  main::test("$x" =~ /Recurse=ARRAY/);		# 219
1022*0Sstevel@tonic-gate  main::test($x);                               # 220
1023*0Sstevel@tonic-gate  main::test($x+0 =~ /Recurse=ARRAY/);		# 221
1024*0Sstevel@tonic-gate}
1025*0Sstevel@tonic-gate
1026*0Sstevel@tonic-gate# BugID 20010422.003
1027*0Sstevel@tonic-gatepackage Foo;
1028*0Sstevel@tonic-gate
1029*0Sstevel@tonic-gateuse overload
1030*0Sstevel@tonic-gate  'bool' => sub { return !$_[0]->is_zero() || undef; }
1031*0Sstevel@tonic-gate;
1032*0Sstevel@tonic-gate 
1033*0Sstevel@tonic-gatesub is_zero
1034*0Sstevel@tonic-gate  {
1035*0Sstevel@tonic-gate  my $self = shift;
1036*0Sstevel@tonic-gate  return $self->{var} == 0;
1037*0Sstevel@tonic-gate  }
1038*0Sstevel@tonic-gate
1039*0Sstevel@tonic-gatesub new
1040*0Sstevel@tonic-gate  {
1041*0Sstevel@tonic-gate  my $class = shift;
1042*0Sstevel@tonic-gate  my $self =  {};
1043*0Sstevel@tonic-gate  $self->{var} = shift;
1044*0Sstevel@tonic-gate  bless $self,$class;
1045*0Sstevel@tonic-gate  }
1046*0Sstevel@tonic-gate
1047*0Sstevel@tonic-gatepackage main;
1048*0Sstevel@tonic-gate
1049*0Sstevel@tonic-gateuse strict;
1050*0Sstevel@tonic-gate
1051*0Sstevel@tonic-gatemy $r = Foo->new(8);
1052*0Sstevel@tonic-gate$r = Foo->new(0);
1053*0Sstevel@tonic-gate
1054*0Sstevel@tonic-gatetest(($r || 0) == 0); # 222
1055*0Sstevel@tonic-gate
1056*0Sstevel@tonic-gatepackage utf8_o;
1057*0Sstevel@tonic-gate
1058*0Sstevel@tonic-gateuse overload 
1059*0Sstevel@tonic-gate  '""'  =>  sub { return $_[0]->{var}; }
1060*0Sstevel@tonic-gate  ;
1061*0Sstevel@tonic-gate  
1062*0Sstevel@tonic-gatesub new
1063*0Sstevel@tonic-gate  {
1064*0Sstevel@tonic-gate    my $class = shift;
1065*0Sstevel@tonic-gate    my $self =  {};
1066*0Sstevel@tonic-gate    $self->{var} = shift;
1067*0Sstevel@tonic-gate    bless $self,$class;
1068*0Sstevel@tonic-gate  }
1069*0Sstevel@tonic-gate
1070*0Sstevel@tonic-gatepackage main;
1071*0Sstevel@tonic-gate
1072*0Sstevel@tonic-gate
1073*0Sstevel@tonic-gatemy $utfvar = new utf8_o 200.2.1;
1074*0Sstevel@tonic-gatetest("$utfvar" eq 200.2.1); # 223 - stringify
1075*0Sstevel@tonic-gatetest("a$utfvar" eq "a".200.2.1); # 224 - overload via sv_2pv_flags
1076*0Sstevel@tonic-gate
1077*0Sstevel@tonic-gate# 225..227 -- more %{} tests.  Hangs in 5.6.0, okay in later releases.
1078*0Sstevel@tonic-gate# Basically this example implements strong encapsulation: if Hderef::import()
1079*0Sstevel@tonic-gate# were to eval the overload code in the caller's namespace, the privatisation
1080*0Sstevel@tonic-gate# would be quite transparent.
1081*0Sstevel@tonic-gatepackage Hderef;
1082*0Sstevel@tonic-gateuse overload '%{}' => sub { (caller(0))[0] eq 'Foo' ? $_[0] : die "zap" };
1083*0Sstevel@tonic-gatepackage Foo;
1084*0Sstevel@tonic-gate@Foo::ISA = 'Hderef';
1085*0Sstevel@tonic-gatesub new { bless {}, shift }
1086*0Sstevel@tonic-gatesub xet { @_ == 2 ? $_[0]->{$_[1]} :
1087*0Sstevel@tonic-gate	  @_ == 3 ? ($_[0]->{$_[1]} = $_[2]) : undef }
1088*0Sstevel@tonic-gatepackage main;
1089*0Sstevel@tonic-gatemy $a = Foo->new;
1090*0Sstevel@tonic-gate$a->xet('b', 42);
1091*0Sstevel@tonic-gateprint $a->xet('b') == 42 ? "ok 225\n" : "not ok 225\n";
1092*0Sstevel@tonic-gateprint defined eval { $a->{b} } ? "not ok 226\n" : "ok 226\n";
1093*0Sstevel@tonic-gateprint $@ =~ /zap/ ? "ok 227\n" : "not ok 227\n";
1094*0Sstevel@tonic-gate
1095*0Sstevel@tonic-gateprint overload::StrVal(qr/a/) =~ /^Regexp=SCALAR\(0x[0-9a-f]+\)$/ ? "ok 228\n" : "not ok 228\n";
1096*0Sstevel@tonic-gate
1097*0Sstevel@tonic-gate{
1098*0Sstevel@tonic-gate   package t229;
1099*0Sstevel@tonic-gate   use overload '='  => sub { 42 },
1100*0Sstevel@tonic-gate                '++' => sub { my $x = ${$_[0]}; $_[0] };
1101*0Sstevel@tonic-gate   sub new { my $x = 42; bless \$x }
1102*0Sstevel@tonic-gate
1103*0Sstevel@tonic-gate   my $warn;
1104*0Sstevel@tonic-gate   {  
1105*0Sstevel@tonic-gate     local $SIG{__WARN__} = sub { $warn++ };
1106*0Sstevel@tonic-gate      my $x = t229->new;
1107*0Sstevel@tonic-gate      my $y = $x;
1108*0Sstevel@tonic-gate      eval { $y++ };
1109*0Sstevel@tonic-gate   }
1110*0Sstevel@tonic-gate   print $warn ? "not ok 229\n" : "ok 229\n";
1111*0Sstevel@tonic-gate}
1112*0Sstevel@tonic-gate
1113*0Sstevel@tonic-gate{
1114*0Sstevel@tonic-gate    package Numify;
1115*0Sstevel@tonic-gate    use overload (qw(0+ numify fallback 1));
1116*0Sstevel@tonic-gate
1117*0Sstevel@tonic-gate    sub new {
1118*0Sstevel@tonic-gate        my $val = $_[1];
1119*0Sstevel@tonic-gate        bless \$val, $_[0];
1120*0Sstevel@tonic-gate    }
1121*0Sstevel@tonic-gate
1122*0Sstevel@tonic-gate    sub numify { ${$_[0]} }
1123*0Sstevel@tonic-gate}
1124*0Sstevel@tonic-gate
1125*0Sstevel@tonic-gate# These are all check that overloaded values rather than reference addressess
1126*0Sstevel@tonic-gate# are what is getting tested.
1127*0Sstevel@tonic-gatemy ($two, $one, $un, $deux) = map {new Numify $_} 2, 1, 1, 2;
1128*0Sstevel@tonic-gatemy ($ein, $zwei) = (1, 2);
1129*0Sstevel@tonic-gate
1130*0Sstevel@tonic-gatemy %map = (one => 1, un => 1, ein => 1, deux => 2, two => 2, zwei => 2);
1131*0Sstevel@tonic-gateforeach my $op (qw(<=> == != < <= > >=)) {
1132*0Sstevel@tonic-gate    foreach my $l (keys %map) {
1133*0Sstevel@tonic-gate        foreach my $r (keys %map) {
1134*0Sstevel@tonic-gate            my $ocode = "\$$l $op \$$r";
1135*0Sstevel@tonic-gate            my $rcode = "$map{$l} $op $map{$r}";
1136*0Sstevel@tonic-gate
1137*0Sstevel@tonic-gate            my $got = eval $ocode;
1138*0Sstevel@tonic-gate            die if $@;
1139*0Sstevel@tonic-gate            my $expect = eval $rcode;
1140*0Sstevel@tonic-gate            die if $@;
1141*0Sstevel@tonic-gate            test ($got, $expect, $ocode) or print "# $rcode\n";
1142*0Sstevel@tonic-gate        }
1143*0Sstevel@tonic-gate    }
1144*0Sstevel@tonic-gate}
1145*0Sstevel@tonic-gate
1146*0Sstevel@tonic-gate# Last test is:
1147*0Sstevel@tonic-gatesub last {476}
1148