File Coverage

blib/lib/Contextual/Return.pm
Criterion Covered Total %
statement 769 1077 71.4
branch 305 558 54.6
condition 74 169 43.7
subroutine 81 94 86.1
pod 5 6 83.3
total 1234 1904 64.8


line stmt bran cond sub pod time code
1             package Contextual::Return;
2 31     31   65988 use warnings;
  31         37  
  31         890  
3 31     31   108 use strict;
  31         36  
  31         1305  
4             our $VERSION = '0.004012';
5              
6             my %attrs_of;
7              
8             # This is localized as caller to hide the interim blocks...
9             my $smart_caller;
10              
11             # Fake out Carp::*, and Scalar::Util::blessed() very early...
12             BEGIN {
13 31     31   96 no warnings 'redefine';
  31         36  
  31         9006  
14              
15 31     31   76 my $fallback_caller = *CORE::GLOBAL::caller{CODE};
16 31 50       91 if (!defined $fallback_caller) {
17             *CORE::GLOBAL::caller = sub (;$) {
18 142     142   665645 my ($height) = @_;
19 142         203 $height++;
20 142         749 my @caller = CORE::caller($height);
21 142 100       487 if ( CORE::caller() eq 'DB' ) {
22             # Oops, redo picking up @DB::args
23             package DB;
24 7         23 @caller = CORE::caller($height);
25             }
26              
27 142 100       367 return if ! @caller; # empty
28 141 100       553 return $caller[0] if ! wantarray; # scalar context
29 88 100       806 return @_ ? @caller : @caller[0..2]; # extra info or regular
30 31         132 };
31             }
32             $smart_caller = sub (;$) {
33 35   100     315 my ($uplevels) = $_[0] || 0;
34 35         29 my @caller;
35 35 100       48 if (CORE::caller eq 'DB') {
36             package DB;
37 18 50       19 if ($fallback_caller) {
38 0 0       0 @caller = $fallback_caller->($uplevels + 5 + $Contextual::Return::uplevel)
39             if $Contextual::Return::uplevel;
40 0         0 @caller = $fallback_caller->($uplevels + 4);
41             }
42             else {
43 18 50       31 @caller = CORE::caller($uplevels + 5 + $Contextual::Return::uplevel)
44             if $Contextual::Return::uplevel;
45 18         45 @caller = CORE::caller($uplevels + 4);
46             }
47             }
48             else {
49 17 50       20 if ($fallback_caller) {
50 0 0       0 @caller = $fallback_caller->($uplevels + 5 + $Contextual::Return::uplevel)
51             if $Contextual::Return::uplevel;
52 0         0 @caller = $fallback_caller->($uplevels + 4);
53             }
54             else {
55 17 50       38 @caller = CORE::caller($uplevels + 5 + $Contextual::Return::uplevel)
56             if $Contextual::Return::uplevel;
57 17         61 @caller = CORE::caller($uplevels + 4);
58             }
59             }
60 35 100       125 return if ! @caller; # empty
61 29 100       71 return $caller[0] if ! wantarray; # scalar context
62 24 100       406 return @_ ? @caller : @caller[0..2]; # extra info or regular
63 31         114 };
64              
65 31     31   131 use Carp;
  31         32  
  31         4805  
66 31         50 my $real_carp = *Carp::carp{CODE};
67 31         34 my $real_croak = *Carp::croak{CODE};
68              
69             *Carp::carp = sub {
70 1 50   1   3 goto &{$real_carp} if !$Contextual::Return::uplevel;
  1         8  
71 0         0 warn _in_context(@_);
72 31         145 };
73              
74             *Carp::croak = sub {
75 6 100   6   16 goto &{$real_croak} if !$Contextual::Return::uplevel;
  2         19  
76 4         7 die _in_context(@_);
77 31         110 };
78              
79             # Scalar::Util::blessed()...
80 31     31   123 use Scalar::Util 'refaddr';
  31         42  
  31         3196  
81              
82             # Remember the current blessed()...
83 31         38 my $original_blessing = *Scalar::Util::blessed{CODE};
84              
85             # ...and replace it...
86             *Scalar::Util::blessed = sub($) {
87 31     31   127 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31     16   42  
  31         4883  
  16         21  
88              
89             # Are we operating on a CRV???
90 16   100     40 my $attrs = $attrs_of{refaddr $_[0] or q{}};
91              
92             # If not, use the original code...
93 16 100       25 goto &{$original_blessing} if !$attrs;
  2         13  
94              
95             # Does this object have a BLESSED handler???
96 14 100       22 if (exists $attrs->{BLESSED}) {
97 2         1 return $attrs->{BLESSED}->(@{$attrs->{args}});
  2         5  
98             }
99              
100             # Otherwise, find the appropriate scalar handler...
101             handler:
102 12         14 for my $context (qw( OBJREF LAZY REF SCALAR VALUE NONVOID DEFAULT )) {
103 68 100       92 my $handler = $attrs->{$context}
104             or next handler;
105              
106 12         10 my $obj_ref = eval { $handler->(@{$attrs->{args}}) };
  12         10  
  12         21  
107              
108 12         38 my $was_blessed = $original_blessing->($obj_ref);
109 12 100       37 return $was_blessed if $was_blessed;
110             }
111              
112             # Otherwise, simulate unblessed status...
113 6         15 return undef;
114 31         4298 };
115             }
116              
117              
118              
119             sub _in_context {
120 40     40   67 my $msg = join q{}, @_;
121              
122             # Start looking in caller...
123 40         33 my $stack_frame = 1;
124 40         123 my ($package, $file, $line, $sub) = CORE::caller($stack_frame++);
125              
126 40         72 my ($orig_package, $prev_package) = ($package) x 2;
127 40         58 my $LOC = qq{at $file line $line};
128              
129             # Walk up stack...
130             STACK_FRAME:
131 40         39 while (1) {
132 141         267 my ($package, $file, $line, $sub) = CORE::caller($stack_frame++);
133              
134             # Fall off the top of the stack...
135 141 100       195 last STACK_FRAME if !defined $package;
136              
137             # Ignore this module (and any helpers)...
138 123 100       193 next STACK_FRAME if $package =~ m{^Contextual::Return}xms;
139              
140             # Track the call up the stack...
141 100         104 $LOC = qq{at $file line $line};
142              
143             # Ignore any @CARP_NOT'ed packages
144             next STACK_FRAME
145 31 100   31   134 if do { no strict 'refs'; *{$package.'::CARP_NOT'}{ARRAY}; };
  31         33  
  31         9332  
  100         68  
  100         57  
  100         219  
146              
147             # Ignore transitions within original caller...
148             next STACK_FRAME
149 70 100 66     199 if $package eq $orig_package && $prev_package eq $orig_package;
150              
151             # If we get a transition out of the original package, we're there...
152 22         23 last STACK_FRAME;
153             }
154              
155             # Insert location details...
156 40 100       351 $msg =~ s//$LOC/g or $msg =~ s/[^\S\n]*$/ $LOC/;
157 40         97 $msg =~ s/$/\n/;
158 40         147 return $msg;
159             }
160              
161             # Indentation corresponds to inherited fall-back relationships...
162             my @CONTEXTS = qw(
163             DEFAULT
164             VOID
165             NONVOID
166             LIST
167             SCALAR
168             VALUE
169             STR
170             NUM
171             BOOL
172             PUREBOOL
173             REF
174             SCALARREF
175             ARRAYREF
176             CODEREF
177             HASHREF
178             GLOBREF
179             OBJREF
180             METHOD
181             BLESSED
182             );
183              
184             my @ALL_EXPORTS = (
185             @CONTEXTS,
186             qw(
187             LAZY RESULT RVALUE METHOD FAIL
188             FIXED RECOVER LVALUE RETOBJ FAIL_WITH
189             ACTIVE CLEANUP NVALUE STRICT BLESSED
190             )
191             );
192              
193             my %STD_NAME_FOR = map { $_ => $_ } @ALL_EXPORTS;
194              
195             sub import {
196             # Load utility module for failure handlers...
197 68 50   68   15285 if (require Contextual::Return::Failure) {
198 68         193 *FAIL = \&Contextual::Return::Failure::_FAIL;
199 68         142 *FAIL_WITH = \&Contextual::Return::Failure::_FAIL_WITH;
200             }
201              
202             # Don't need the package name...
203 68         130 shift @_;
204              
205             # If args, export nothing by default; otherwise export all...
206 68 100       1030 my %exports = @_ ? () : %STD_NAME_FOR;
207              
208             # All args are export either selectors and/or renamers...
209 68         283 while (my $selector = shift @_) {
210 15         20 my $next_arg = $_[0];
211             my $renamer = (defined $next_arg
212             && !ref $next_arg
213 15 100 100     76 && !exists $STD_NAME_FOR{$next_arg})
214             ? shift(@_)
215             : undef;
216 15         42 %exports = (%exports, _add_exports_for($selector, $renamer));
217             }
218              
219             # Loop through possible exports, exporting anything requested...
220 66         104 my $caller = CORE::caller;
221             EXPORT:
222 66         375 for my $subname (keys %exports) {
223 31     31   133 no strict qw( refs );
  31         45  
  31         5070  
224 1992         1170 *{$caller.'::'.$exports{$subname}} = \&{$subname};
  1992         16673  
  1992         2052  
225             }
226             };
227              
228             sub _add_exports_for {
229 15     15   19 my ($selector, $renamer) = @_;
230              
231             # If no renamer, use original name...
232 15   100     38 $renamer ||= '%s';
233              
234             # Handle different types of selector...
235 15   100     48 my $selector_type = ref($selector) || 'literal';
236              
237             # Array selector recursively export each element...
238 15 50       41 if ($selector_type eq 'ARRAY') {
    100          
    100          
239 0         0 return map { _add_exports_for($_,$renamer) } @{$selector};
  0         0  
  0         0  
240             }
241             elsif ($selector_type eq 'Regexp') {
242 4         8 my @selected = grep {/$selector/} @ALL_EXPORTS;
  136         219  
243 4 100       15 if (!@selected) {
244 1         5 Carp::carp("use Contextual::Return $selector didn't export anything");
245             }
246 31     31   16985 no if $] >= 5.022, warnings => 'redundant';
  31         231  
  31         129  
247 4         201 return map { $_ => sprintf($renamer, $_) } @selected;
  72         117  
248             }
249             elsif ($selector_type eq 'literal') {
250             Carp::croak "Can't export $selector: no such handler"
251 10 100       22 if !exists $STD_NAME_FOR{$selector};
252 31     31   3328 no if $] >= 5.022, warnings => 'redundant';
  31         35  
  31         104  
253 9         83 return ( $selector => sprintf($renamer, $selector) );
254             }
255             else {
256 1         4 Carp::croak "Can't use $selector_type as export specifier";
257             }
258             }
259              
260              
261             # Let handlers access the result object they're inside...
262              
263             sub RETOBJ() {
264 1     1 0 3 our $__RETOBJ__;
265 1         2 return $__RETOBJ__;
266             }
267              
268              
269 31     31   3418 use Scalar::Util qw( refaddr );
  31         79  
  31         4070  
270              
271             # Override return value in a C::R handler...
272             sub RESULT(;&) {
273 40     40 1 1244 my ($block) = @_;
274              
275             # Determine call context and arg list...
276 40         43 my $args = \@DB::args;
277 40         33 my $context = do { package DB; (CORE::caller 1)[5]; };
  40         185  
278              
279             # No args -> return appropriate value...
280 40 100       68 if (!@_) {
281 1 0       4 return $context ? @{ $Contextual::Return::__RESULT__ || [] }
  0 50       0  
282             : $Contextual::Return::__RESULT__->[0]
283             ;
284             }
285              
286             # Hide from caller() and the enclosing eval{}...
287              
288             # Evaluate block in context and cache result...
289 39         34 local $Contextual::Return::uplevel = $Contextual::Return::uplevel+1;
290 31     31   122 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         35  
  31         4416  
  39         40  
291             $Contextual::Return::__RESULT__
292 5         14 = $context ? [ $block->(@{$args}) ]
293 33         51 : defined $context ? [ scalar $block->(@{$args}) ]
294 39 100       70 : do { $block->(@{$args}); [] }
  1 100       1  
  1         3  
  1         2  
295             ;
296              
297 39         143 return;
298             }
299              
300             sub RVALUE(&;@) :lvalue;
301             sub LVALUE(&;@) :lvalue;
302             sub NVALUE(&;@) :lvalue;
303              
304             my %opposite_of = (
305             'RVALUE' => 'LVALUE or NVALUE',
306             'LVALUE' => 'RVALUE or NVALUE',
307             'NVALUE' => 'LVALUE or RVALUE',
308             );
309              
310              
311             BEGIN {
312 31     31   62 for my $subname (qw( RVALUE LVALUE NVALUE) ) {
313 31     31   127 no strict 'refs';
  31         31  
  31         5760  
314 93         1103 *{$subname} = sub(&;@) :lvalue { # (handler, return_lvalue);
315 28     28   82 my $handler = shift;
316 28         20 my $impl;
317 28         23 my $args = \@DB::args; { package DB; ()=CORE::caller(1); };
  28         20  
  28         67  
318 28 100 33     95 if (@_==0) {
    50          
319 10         33 $impl = tie $_[0], 'Contextual::Return::Lvalue',
320             $subname => $handler, args=>$args;
321             }
322             elsif (@_==1 and $impl = tied $_[0]) {
323             die _in_context "Can't install two $subname handlers"
324 18 50       34 if exists $impl->{$subname};
325 18         16 $impl->{$subname} = $handler;
326             }
327             else {
328 0 0       0 my $vals = join q{, }, map { tied $_ ? keys %{tied $_}
  0 0       0  
  0         0  
329             : defined $_ ? $_
330             : 'undef'
331             } @_;
332 0         0 die _in_context "Expected a $opposite_of{$subname} block ",
333             "after the $subname block ",
334             "but found instead: $vals\n";
335             }
336              
337             # Handle void context calls...
338 28 50 66     43 if (!defined wantarray && $impl->{NVALUE}) {
339             # Fake out caller() and Carp...
340 1         2 local $Contextual::Return::uplevel = 1;
341 31     31   122 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         29  
  31         2939  
  1         2  
342              
343             # Call and clear handler...
344 1         2 local $Contextual::Return::__RETOBJ__ = $impl;
345 1         1 $impl->{NVALUE}( @{$impl->{args}} );
  1         4  
346 1         168 delete $impl->{NVALUE};
347             }
348 28         57 $_[0];
349             }
350 93         318 }
351             }
352              
353             for my $modifier_name (qw< STRICT FIXED ACTIVE >) {
354 31     31   121 no strict 'refs';
  31         31  
  31         2101  
355             *{$modifier_name} = sub ($) {
356 21     21   21 my ($crv) = @_;
357 21   50     47 my $attrs = $attrs_of{refaddr $crv or q{}};
358              
359             # Track context...
360 21         13 my $wantarray = wantarray;
361 31     31   13097 use Want;
  31         40555  
  31         2587  
362 21   66     49 $attrs->{want_pure_bool} ||= Want::want('BOOL');
363              
364             # Remember the modification...
365 21         825 $attrs->{$modifier_name} = 1;
366              
367             # Prepare for exception handling...
368 21         23 my $recover = $attrs->{RECOVER};
369 21         19 local $Contextual::Return::uplevel = 2;
370 31     31   185 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         33  
  31         18255  
  21         26  
371              
372             # Handle list context directly, if possible...
373 21 100       32 if ($wantarray) {
374 2         4 local $Contextual::Return::__RESULT__;
375             # List or ancestral handlers...
376             handler:
377 2         6 for my $context (qw(LIST VALUE NONVOID DEFAULT)) {
378             my $handler = $attrs->{$context}
379             or $attrs->{STRICT} and last handler
380 2 0 0     6 or next handler;
      33        
381              
382 2         2 my @rv = eval { $handler->(@{$attrs->{args}}) };
  2         3  
  2         5  
383 2 50       16 if ($recover) {
    50          
384 0 0       0 if (!$Contextual::Return::__RESULT__) {
385 0         0 $Contextual::Return::__RESULT__ = [@rv];
386             }
387 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
388             }
389             elsif ($@) {
390 0         0 die $@;
391             }
392              
393 2 50       14 return @rv if !$Contextual::Return::__RESULT__;
394 0         0 return @{$Contextual::Return::__RESULT__};
  0         0  
395             }
396             # Convert to list from arrayref handler...
397 0 0 0     0 if (!$attrs->{STRICT} and my $handler = $attrs->{ARRAYREF}) {
398 0         0 my $array_ref = eval { $handler->(@{$attrs->{args}}) };
  0         0  
  0         0  
399              
400 0 0       0 if ($recover) {
    0          
401 0 0       0 if (!$Contextual::Return::__RESULT__) {
402 0         0 $Contextual::Return::__RESULT__ = [$array_ref];
403             }
404 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
405             }
406             elsif ($@) {
407 0         0 die $@;
408             }
409              
410             # Array ref may be returned directly, or via RESULT{}...
411 0 0       0 $array_ref = $Contextual::Return::__RESULT__->[0]
412             if $Contextual::Return::__RESULT__;
413              
414 0 0 0     0 return @{$array_ref} if (ref $array_ref||q{}) eq 'ARRAY';
  0         0  
415             }
416             # Return scalar object as one-elem list, if possible...
417             handler:
418 0         0 for my $context (qw(BOOL STR NUM VALUE SCALAR LAZY)) {
419 0 0       0 last handler if $attrs->{STRICT};
420 0 0       0 return $crv if exists $attrs->{$context};
421             }
422 0         0 $@ = _in_context "Can't call $attrs->{sub} in a list context";
423 0 0       0 if ($recover) {
424 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
425             }
426             else {
427 0         0 die $@;
428             }
429             }
430              
431             # Handle void context directly...
432 19 100       33 if (!defined $wantarray) {
433             handler:
434 1         3 for my $context (qw< VOID DEFAULT >) {
435             my $handler = $attrs->{$context}
436             or $attrs->{STRICT} and last handler
437 1 0 50     6 or next handler;
      33        
438              
439 0         0 eval { $attrs->{$context}->(@{$attrs->{args}}) };
  0         0  
  0         0  
440 0 0       0 if ($recover) {
    0          
441 0         0 $recover->(@{$attrs->{args}});
  0         0  
442             }
443             elsif ($@) {
444 0         0 die $@;
445             }
446 0         0 last handler;
447             }
448 1 50       3 if ($attrs->{STRICT}) {
449 1         5 $@ = _in_context "Can't call $attrs->{sub} in a void context";
450 1 50       3 if ($recover) {
451 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
452             }
453             else {
454 1         9 die $@;
455             }
456             }
457 0         0 return;
458             }
459              
460             # Otherwise, let someone else handle it...
461 18         52 return $crv;
462             }
463             }
464              
465             sub LIST (;&$) {
466 144     144 1 179 my ($block, $crv) = @_;
467              
468             # Handle simple context tests...
469 144 100       246 return !!(CORE::caller 1)[5] if !@_;
470              
471             # Ensure we have an object...
472 142         104 my $attrs;
473 142 100       284 if (!refaddr $crv) {
474 12         14 my $args = \@DB::args; { package DB; ()=CORE::caller(1); };
  12         12  
  12         47  
475 12         30 my $subname = (CORE::caller(1))[3];
476 12 50       26 if (!defined $subname) {
477 0         0 $subname = 'bare LIST {...}';
478             }
479 12         18 $crv = bless \my $scalar, 'Contextual::Return::Value';
480 12         48 $attrs = $attrs_of{refaddr $crv} = { args => $args, sub => $subname };
481             }
482             else {
483 130         198 $attrs = $attrs_of{refaddr $crv};
484             }
485 142         123 local $Contextual::Return::__RETOBJ__ = $crv;
486              
487             # Handle repetitions...
488             die _in_context "Can't install two LIST handlers"
489 142 100       221 if exists $attrs->{LIST};
490              
491             # Identify contexts...
492 141         132 my $wantarray = wantarray;
493 31     31   141 use Want;
  31         41  
  31         1882  
494 141   33     374 $attrs->{want_pure_bool} ||= Want::want('BOOL');
495              
496             # Prepare for exception handling...
497 141         4198 my $recover = $attrs->{RECOVER};
498 141         131 local $Contextual::Return::uplevel = 2;
499 31     31   109 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         34  
  31         12375  
  141         177  
500              
501             # Handle list context directly...
502 141 100       194 if ($wantarray) {
503 2         2 local $Contextual::Return::__RESULT__;
504              
505 2         5 my @rv = eval { $block->(@{$attrs->{args}}) };
  2         2  
  2         6  
506 2 50       12 if ($recover) {
    50          
507 0 0       0 if (!$Contextual::Return::__RESULT__) {
508 0         0 $Contextual::Return::__RESULT__ = [@rv];
509             }
510 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
511             }
512             elsif ($@) {
513 0         0 die $@;
514             }
515              
516 2 50       12 return @rv if !$Contextual::Return::__RESULT__;
517 0         0 return @{$Contextual::Return::__RESULT__};
  0         0  
518             }
519              
520             # Handle void context directly...
521 139 50       196 if (!defined $wantarray) {
522             handler:
523 0         0 for my $context (qw< VOID DEFAULT >) {
524             my $handler = $attrs->{$context}
525             or $attrs->{STRICT} and last handler
526 0 0 0     0 or next handler;
      0        
527              
528 0         0 eval { $attrs->{$context}->(@{$attrs->{args}}) };
  0         0  
  0         0  
529 0 0       0 if ($recover) {
    0          
530 0         0 $recover->(@{$attrs->{args}});
  0         0  
531             }
532             elsif ($@) {
533 0         0 die $@;
534             }
535 0         0 last handler;
536             }
537 0 0       0 if ($attrs->{STRICT}) {
538 0         0 $@ = _in_context "Can't call $attrs->{sub} in a void context";
539 0 0       0 if ($recover) {
540 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
541             }
542             else {
543 0         0 die $@;
544             }
545             }
546 0         0 return;
547             }
548              
549             # Otherwise, cache handler...
550 139         157 $attrs->{LIST} = $block;
551 139         270 return $crv;
552             }
553              
554              
555             sub VOID (;&$) {
556 62     62 1 2936 my ($block, $crv) = @_;
557              
558             # Handle simple context tests...
559 62 100       128 return !defined( (CORE::caller 1)[5] ) if !@_;
560              
561             # Ensure we have an object...
562 56         39 my $attrs;
563 56 100       120 if (!refaddr $crv) {
564 6         12 my $args = \@DB::args; { package DB; ()=CORE::caller(1); };
  6         6  
  6         28  
565 6         16 my $subname = (CORE::caller(1))[3];
566 6 50       12 if (!defined $subname) {
567 0         0 $subname = 'bare VOID {...}';
568             }
569 6         18 $crv = bless \my $scalar, 'Contextual::Return::Value';
570 6         26 $attrs = $attrs_of{refaddr $crv} = { args => $args, sub => $subname };
571             }
572             else {
573 50         74 $attrs = $attrs_of{refaddr $crv};
574             }
575 56         44 local $Contextual::Return::__RETOBJ__ = $crv;
576              
577             # Handle repetitions...
578             die _in_context "Can't install two VOID handlers"
579 56 50       95 if exists $attrs->{VOID};
580              
581             # Identify contexts...
582 56         51 my $wantarray = wantarray;
583 31     31   144 use Want;
  31         35  
  31         1821  
584 56   66     167 $attrs->{want_pure_bool} ||= Want::want('BOOL');
585              
586             # Prepare for exception handling...
587 56         2179 my $recover = $attrs->{RECOVER};
588 56         43 local $Contextual::Return::uplevel = 2;
589 31     31   105 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         42  
  31         11192  
  56         92  
590              
591             # Handle list context directly, if possible...
592 56 100       80 if ($wantarray) {
593 6         13 local $Contextual::Return::__RESULT__;
594             # List or ancestral handlers...
595             handler:
596 6         20 for my $context (qw(LIST VALUE NONVOID DEFAULT)) {
597             my $handler = $attrs->{$context}
598             or $attrs->{STRICT} and last handler
599 6 0 0     13 or next handler;
      33        
600              
601 6         6 my @rv = eval { $handler->(@{$attrs->{args}}) };
  6         6  
  6         14  
602 6 50       36 if ($recover) {
    50          
603 0 0       0 if (!$Contextual::Return::__RESULT__) {
604 0         0 $Contextual::Return::__RESULT__ = [@rv];
605             }
606 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
607             }
608             elsif ($@) {
609 0         0 die $@;
610             }
611              
612 6 100       19 return @rv if !$Contextual::Return::__RESULT__;
613 3         3 return @{$Contextual::Return::__RESULT__};
  3         11  
614             }
615             # Convert to list from arrayref handler...
616 0 0 0     0 if (!$attrs->{STRICT} and my $handler = $attrs->{ARRAYREF}) {
617 0         0 my $array_ref = eval { $handler->(@{$attrs->{args}}) };
  0         0  
  0         0  
618              
619 0 0       0 if ($recover) {
    0          
620 0 0       0 if (!$Contextual::Return::__RESULT__) {
621 0         0 $Contextual::Return::__RESULT__ = [$array_ref];
622             }
623 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
624             }
625             elsif ($@) {
626 0         0 die $@;
627             }
628              
629             # Array ref may be returned directly, or via RESULT{}...
630 0 0       0 $array_ref = $Contextual::Return::__RESULT__->[0]
631             if $Contextual::Return::__RESULT__;
632              
633 0 0 0     0 return @{$array_ref} if (ref $array_ref||q{}) eq 'ARRAY';
  0         0  
634             }
635             # Return scalar object as one-elem list, if possible...
636             handler:
637 0         0 for my $context (qw(BOOL STR NUM VALUE SCALAR LAZY)) {
638 0 0       0 last handler if $attrs->{STRICT};
639 0 0       0 return $crv if exists $attrs->{$context};
640             }
641 0         0 $@ = _in_context "Can't call $attrs->{sub} in a list context";
642 0 0       0 if ($recover) {
643 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
644             }
645             else {
646 0         0 die $@;
647             }
648             }
649              
650             # Handle void context directly...
651 50 100       76 if (!defined $wantarray) {
652 2         3 eval { $block->(@{$attrs->{args}}) };
  2         3  
  2         6  
653              
654 2 50       12 if ($recover) {
    50          
655 0         0 $recover->(@{$attrs->{args}});
  0         0  
656             }
657             elsif ($@) {
658 0         0 die $@;
659             }
660              
661 2         5 return;
662             }
663              
664             # Otherwise, cache handler...
665 48         47 $attrs->{VOID} = $block;
666 48         403 return $crv;
667             }
668              
669             for my $context (qw( SCALAR NONVOID )) {
670 31     31   126 no strict qw( refs );
  31         36  
  31         5446  
671             *{$context} = sub (;&$) {
672 138     138   213 my ($block, $crv) = @_;
673              
674             # Handle simple context tests...
675 138 100       257 if (!@_) {
676 3         7 my $callers_context = (CORE::caller 1)[5];
677 3   33     23 return defined $callers_context
678             && ($context eq 'NONVOID' || !$callers_context);
679             }
680              
681             # Ensure we have an object...
682 135         102 my $attrs;
683 135 100       271 if (!refaddr $crv) {
684 11         18 my $args = \@DB::args; { package DB; ()=CORE::caller(1); };
  11         11  
  11         50  
685 11         28 my $subname = (CORE::caller(1))[3];
686 11 50       26 if (!defined $subname) {
687 0         0 $subname = "bare $context {...}";
688             }
689 11         26 $crv = bless \my $scalar, 'Contextual::Return::Value';
690 11         57 $attrs = $attrs_of{refaddr $crv}
691             = { args => $args, sub => $subname };
692             }
693             else {
694 124         196 $attrs = $attrs_of{refaddr $crv};
695             }
696 135         113 local $Contextual::Return::__RETOBJ__ = $crv;
697              
698             # Make sure this block is a possibility too...
699             die _in_context "Can't install two $context handlers"
700 135 50       231 if exists $attrs->{$context};
701 135         147 $attrs->{$context} = $block;
702              
703             # Identify contexts...
704 135         125 my $wantarray = wantarray;
705 31     31   125 use Want ();
  31         35  
  31         1358  
706 135   33     397 $attrs->{want_pure_bool} ||= Want::want('BOOL');
707              
708             # Prepare for exception handling...
709 135         4295 my $recover = $attrs->{RECOVER};
710 135         123 local $Contextual::Return::uplevel = 2;
711 31     31   104 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         42  
  31         13644  
  135         164  
712              
713             # Handle list context directly, if possible...
714 135 100       209 if ($wantarray) {
715 2         2 local $Contextual::Return::__RESULT__;
716              
717             # List or ancestral handlers...
718             handler:
719 2         5 for my $context (qw(LIST VALUE NONVOID DEFAULT)) {
720             my $handler = $attrs->{$context}
721             or $attrs->{STRICT} and last handler
722 7 50 50     27 or next handler;
      66        
723              
724 1         2 my @rv = eval { $handler->(@{$attrs->{args}}) };
  1         1  
  1         2  
725 1 50       6 if ($recover) {
    50          
726 0 0       0 if (!$Contextual::Return::__RESULT__) {
727 0         0 $Contextual::Return::__RESULT__ = [@rv];
728             }
729 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
730             }
731             elsif ($@) {
732 0         0 die $@;
733             }
734              
735 1 50       11 return @rv if !$Contextual::Return::__RESULT__;
736 0         0 return @{$Contextual::Return::__RESULT__};
  0         0  
737             }
738             # Convert to list from arrayref handler...
739 1 50 33     7 if (!$attrs->{STRICT} and my $handler = $attrs->{ARRAYREF}) {
740              
741 0         0 my $array_ref = eval { $handler->(@{$attrs->{args}}) };
  0         0  
  0         0  
742 0 0       0 if ($recover) {
    0          
743 0 0       0 if (!$Contextual::Return::__RESULT__) {
744 0         0 $Contextual::Return::__RESULT__ = [$array_ref];
745             }
746 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
747             }
748             elsif ($@) {
749 0         0 die $@;
750             }
751              
752             # Array ref may be returned directly, or via RESULT{}...
753 0 0       0 $array_ref = $Contextual::Return::__RESULT__->[0]
754             if $Contextual::Return::__RESULT__;
755              
756 0 0 0     0 return @{$array_ref} if (ref $array_ref||q{}) eq 'ARRAY';
  0         0  
757             }
758             # Return scalar object as one-elem list, if possible...
759             handler:
760 1         3 for my $context (qw(BOOL STR NUM VALUE SCALAR LAZY)) {
761 5 50       7 last if $attrs->{STRICT};
762 5 100       31 return $crv if exists $attrs->{$context};
763             }
764 0         0 die _in_context "Can't call $attrs->{sub} in a list context";
765             }
766              
767             # Handle void context directly...
768 133 100       191 if (!defined $wantarray) {
769             handler:
770 1         2 for my $context (qw< VOID DEFAULT >) {
771             my $handler = $attrs->{$context}
772             or $attrs->{STRICT} and last handler
773 1 0 0     14 or next handler;
      33        
774              
775 1         2 eval { $handler->(@{$attrs->{args}}) };
  1         2  
  1         4  
776 1 50       13 if ($recover) {
    50          
777 0         0 $recover->(@{$attrs->{args}});
  0         0  
778             }
779             elsif ($@) {
780 1         6 die $@;
781             }
782              
783 0         0 last handler;
784             }
785 0 0       0 if ($attrs->{STRICT}) {
786 0         0 $@ = _in_context "Can't call $attrs->{sub} in a void context";
787 0 0       0 if ($recover) {
788 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
789             }
790             else {
791 0         0 die $@;
792             }
793             }
794 0         0 return;
795             }
796              
797             # Otherwise, defer evaluation by returning an object...
798 132         318 return $crv;
799             }
800             }
801              
802             handler:
803             for my $context_name (@CONTEXTS, qw< RECOVER _internal_LIST CLEANUP >) {
804             next handler if $context_name eq 'LIST' # These
805             || $context_name eq 'VOID' # four
806             || $context_name eq 'SCALAR' # handled
807             || $context_name eq 'NONVOID'; # separately
808              
809 31     31   141 no strict qw( refs );
  31         37  
  31         5206  
810             *{$context_name} = sub (&;$) {
811 1125     1125   4699 my ($block, $crv) = @_;
812              
813             # Ensure we have an object...
814 1125         767 my $attrs;
815 1125 100       1947 if (!refaddr $crv) {
816 219         266 my $args = \@DB::args; { package DB; ()=CORE::caller(1); };
  219         192  
  219         843  
817 219         516 my $subname = (CORE::caller(1))[3];
818 219 50       484 if (!defined $subname) {
819 0         0 $subname = "bare $context_name {...}";
820             }
821 219         397 $crv = bless \my $scalar, 'Contextual::Return::Value';
822 219         820 $attrs = $attrs_of{refaddr $crv}
823             = { args => $args, sub => $subname };
824             }
825             else {
826 906         1237 $attrs = $attrs_of{refaddr $crv};
827             }
828 1125         838 local $Contextual::Return::__RETOBJ__ = $crv;
829              
830             # Make sure this block is a possibility too...
831 1125 50       1617 if ($context_name ne '_internal_LIST') {
832             die _in_context "Can't install two $context_name handlers"
833 1125 50       1583 if exists $attrs->{$context_name};
834 1125         1171 $attrs->{$context_name} = $block;
835             }
836              
837             # Identify contexts...
838 1125         907 my $wantarray = wantarray;
839 31     31   128 use Want ();
  31         36  
  31         1481  
840 1125   66     2668 $attrs->{want_pure_bool} ||= Want::want('BOOL');
841              
842             # Prepare for exception handling...
843 1125         37072 my $recover = $attrs->{RECOVER};
844 1125         877 local $Contextual::Return::uplevel = 2;
845 31     31   441 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         42  
  31         18908  
  1125         1268  
846              
847             # Handle list context directly, if possible...
848 1125 100       1454 if ($wantarray) {
849 15 50       42 local $Contextual::Return::__RESULT__
850             = $context_name eq 'RECOVER' ? $Contextual::Return::__RESULT__
851             : undef
852             ;
853              
854             # List or ancestral handlers...
855             handler:
856 15         31 for my $context (qw(LIST VALUE NONVOID DEFAULT)) {
857             my $handler = $attrs->{$context}
858             or $attrs->{STRICT} and last handler
859 36 50 50     147 or next handler;
      66        
860              
861 12         21 my @rv = eval { $handler->(@{$attrs->{args}}) };
  12         17  
  12         34  
862 12 100       77 if ($recover) {
    100          
863 2 50       5 if (!$Contextual::Return::__RESULT__) {
864 2         4 $Contextual::Return::__RESULT__ = [@rv];
865             }
866 2         3 () = $recover->(@{$attrs->{args}});
  2         6  
867             }
868             elsif ($@) {
869 3         11 die $@;
870             }
871              
872 9 100       631 return @rv if !$Contextual::Return::__RESULT__;
873 3         3 return @{$Contextual::Return::__RESULT__};
  3         31  
874             }
875             # Convert to list from arrayref handler...
876 3 100 66     26 if (!$attrs->{STRICT} and my $handler = $attrs->{ARRAYREF}) {
877 1         1 local $Contextual::Return::uplevel = 2;
878              
879             # Array ref may be returned directly, or via RESULT{}...
880 1         2 my $array_ref = eval { $handler->(@{$attrs->{args}}) };
  1         1  
  1         3  
881 1 50       417 if ($recover) {
    50          
882 0 0       0 if (!$Contextual::Return::__RESULT__) {
883 0         0 $Contextual::Return::__RESULT__ = [$array_ref];
884             }
885 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
886             }
887             elsif ($@) {
888 0         0 die $@;
889             }
890              
891 1 50       3 $array_ref = $Contextual::Return::__RESULT__->[0]
892             if $Contextual::Return::__RESULT__;
893              
894 1 50 50     5 return @{$array_ref} if (ref $array_ref||q{}) eq 'ARRAY';
  1         5  
895             }
896             # Return scalar object as one-elem list, if possible...
897             handler:
898 2         3 for my $context (qw(BOOL STR NUM VALUE SCALAR LAZY)) {
899 5 50       7 last if $attrs->{STRICT};
900 5 100       17 return $crv if exists $attrs->{$context};
901             }
902 0         0 $@ = _in_context "Can't call $attrs->{sub} in a list context";
903 0 0       0 if ($recover) {
904 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
905             }
906             else {
907 0         0 die $@;
908             }
909             }
910              
911             # Handle void context directly...
912 1110 100       1394 if (!defined $wantarray) {
913             handler:
914 6         13 for my $context (qw(VOID DEFAULT)) {
915 9 100       23 if (!$attrs->{$context}) {
916 3 50       7 last handler if $attrs->{STRICT};
917 3         3 next handler;
918             }
919              
920 6         10 eval { $attrs->{$context}->(@{$attrs->{args}}) };
  6         6  
  6         16  
921              
922 6 100       33 if ($recover) {
    100          
923 1         1 $recover->(@{$attrs->{args}});
  1         2  
924             }
925             elsif ($@) {
926 4         21 die $@;
927             }
928              
929 2         347 last handler;
930             }
931 2 50       7 if ($attrs->{STRICT}) {
932 0         0 $@ = _in_context "Can't call $attrs->{sub} in a void context";
933 0 0       0 if ($recover) {
934 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
935             }
936             else {
937 0         0 die $@;
938             }
939             }
940 2         5 return;
941             }
942              
943             # Otherwise, defer evaluation by returning an object...
944 1104         2465 return $crv;
945             }
946             }
947              
948             # Alias LAZY to SCALAR...
949             *LAZY = *SCALAR;
950              
951              
952             # Set $Data::Dumper::Freezer to 'Contextual::Return::FREEZE' to be able to
953             # dump contextual return values...
954              
955             my %operator_impl;
956              
957             my $no_handler_message = qr{
958             ^ Can't [ ] call [ ] .*? [ ] in [ ] [\w]+ [ ] context
959             | ^ [\w:]+ [ ] can't [ ] return [ ] a [ ] \w+ [ ] reference
960             }xms;
961              
962             sub _flag_self_ref_in {
963 0     0   0 my ($data_ref, $obj_ref) = @_;
964 0         0 my $type = ref $data_ref;
965 0 0       0 return if !$type;
966 0 0       0 for my $ref ( $type eq 'SCALAR' ? ${$data_ref} : $type eq 'ARRAY' ? @{$data_ref} : ()) {
  0 0       0  
  0         0  
967 31     31   144 no warnings 'numeric', 'uninitialized';
  31         36  
  31         4948  
968 0 0       0 if (refaddr($ref) == refaddr($obj_ref)) {
969 0         0 $ref = '<<>>';
970             }
971             }
972             }
973              
974             sub FREEZE {
975 0     0 1 0 my ($self) = @_;
976 0         0 my $attrs_ref = $attrs_of{refaddr $self};
977 0         0 my $args_ref = $attrs_ref->{args};
978              
979 0         0 my @no_handler;
980              
981             # Call appropriate operator handler, defusing and recording exceptions...
982             my $overloaded = sub {
983 0     0   0 my ($context, $op) = @_;
984              
985             # Try the operator...
986 0         0 my $retval = eval { $operator_impl{$op}->($self,@{$args_ref}) };
  0         0  
  0         0  
987              
988             # Detect and report internal exceptions...
989 0 0       0 if (my $exception = $@) {
990 0 0       0 if ($exception =~ $no_handler_message) {
991 0         0 push @no_handler, $context;
992 0         0 return ();
993             }
994 0         0 chomp $exception;
995 0         0 return { $context => "<<>>" };
996             }
997              
998             # Detect self-referential overloadings (to avoid infinite recursion)...
999             {
1000 31     31   135 no warnings 'numeric', 'uninitialized';
  31         33  
  31         14558  
  0         0  
1001 0 0 0     0 if (ref $retval eq 'REF' && eval{ ${$retval} == ${$self} }) {
  0         0  
  0         0  
  0         0  
1002 0         0 return { $context => "<<>>" };
1003             }
1004             }
1005              
1006             # Normal return of contextual value labelled by context...
1007 0         0 return { $context => $retval };
1008 0         0 };
1009              
1010 0         0 my @values;
1011              
1012             # Where did this value originate?
1013 0         0 push @values, { ISA => 'Contextual::Return::Value' };
1014 0         0 push @values, { FROM => $attrs_ref->{sub} };
1015              
1016             # Does it return a value in void context?
1017 0 0 0     0 if (exists $attrs_ref->{VOID} || exists $attrs_ref->{DEFAULT}) {
1018 0         0 push @values, { VOID => undef };
1019             }
1020             else {
1021 0         0 push @no_handler, 'VOID';
1022             }
1023              
1024             # Generate list context value by "pretend" LIST handler...
1025 0   0 0   0 push @values, { LIST => eval{ [ _internal_LIST(sub{}, $self) ] } // do{ chomp $@; "<<>>"} };
  0         0  
  0         0  
  0         0  
1026 0         0 _flag_self_ref_in($values[-1]{LIST}, $self);
1027              
1028             # Generate scalar context values by calling appropriate handler...
1029 0         0 push @values, $overloaded->( STR => q{""} );
1030 0         0 push @values, $overloaded->( NUM => '0+' );
1031 0         0 push @values, $overloaded->( BOOL => 'bool' );
1032 0         0 push @values, $overloaded->( SCALARREF => '${}' );
1033 0         0 _flag_self_ref_in($values[-1]{SCALARREF}, $self);
1034 0         0 push @values, $overloaded->( ARRAYREF => '@{}' );
1035 0         0 _flag_self_ref_in($values[-1]{ARRAYREF}, $self);
1036 0         0 push @values, $overloaded->( CODEREF => '&{}' );
1037 0         0 push @values, $overloaded->( HASHREF => '%{}' );
1038 0         0 push @values, $overloaded->( GLOBREF => '*{}' );
1039              
1040             # Are there handlers for various "generic" super-contexts...
1041 0         0 my @fallbacks = grep { $attrs_ref->{$_} }
  0         0  
1042             qw< DEFAULT NONVOID SCALAR VALUE REF RECOVER >;
1043              
1044 0         0 push @values, { NO_HANDLER => \@no_handler };
1045 0         0 push @values, { FALLBACKS => \@fallbacks };
1046              
1047             # Temporarily replace object being dumped, by values found...
1048 0         0 $_[0] = \@values;
1049             }
1050              
1051             # Call this method on a contextual return value object to debug it...
1052              
1053             sub DUMP {
1054 0 0   0 1 0 if (eval{ require Data::Dumper; 1; }) {
  0         0  
  0         0  
1055 0         0 my ($crv) = @_;
1056 0 0       0 if (eval{ ref($crv)->isa('Contextual::Return::Value')}) {
  0         0  
1057 0         0 Contextual::Return::FREEZE($crv);
1058             }
1059 0         0 local $Data::Dumper::Terse = 1;
1060 0         0 local $Data::Dumper::Indent = 1;
1061 0         0 my $dump = Data::Dumper::Dumper($crv);
1062 0         0 $dump =~ s<,\n \{><,ZZZZ{>msg;
1063 0         0 $dump =~ s<\n\s+>< >msg;
1064 0         0 $dump =~ s<,ZZZZ\{><\n {>msg;
1065 0         0 return $dump;
1066             }
1067             else {
1068 0         0 Carp::carp("Can't DUMP contextual return value (no Data::Dumper!)");
1069 0         0 return;
1070             }
1071             }
1072              
1073              
1074             package Contextual::Return::Value;
1075 31     31   675 BEGIN { *_in_context = *Contextual::Return::_in_context; }
1076 31     31   147 use Scalar::Util qw( refaddr );
  31         36  
  31         2129  
1077              
1078             BEGIN {
1079             %operator_impl = (
1080             q{""} => sub {
1081 39     39   664 my ($self) = @_;
1082 39         55 local $Contextual::Return::__RETOBJ__ = $self;
1083 31     31   118 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         33  
  31         8469  
  39         66  
1084              
1085 39         108 my $attrs = $attrs_of{refaddr $self};
1086             handler:
1087 39         81 for my $context (qw(STR SCALAR LAZY VALUE NONVOID DEFAULT NUM)) {
1088             my $handler = $attrs->{$context}
1089             or $attrs->{STRICT} and last handler
1090 95 50 50     281 or next handler;
      66        
1091              
1092 39         38 local $Contextual::Return::__RESULT__;
1093 39         58 local $Contextual::Return::uplevel = 2;
1094 39         58 my $rv = eval { $handler->(@{$attrs->{args}}) };
  39         54  
  39         100  
1095              
1096 39 100       673 if (my $recover = $attrs->{RECOVER}) {
    100          
1097 4 50       9 if (!$Contextual::Return::__RESULT__) {
1098 4         6 $Contextual::Return::__RESULT__ = [$rv];
1099             }
1100 4         5 scalar $recover->(@{$attrs->{args}});
  4         11  
1101             }
1102             elsif ($@) {
1103 3         11 die $@;
1104             }
1105              
1106 36 100       581 if ($Contextual::Return::__RESULT__) {
1107 8         13 $rv = $Contextual::Return::__RESULT__->[0];
1108             }
1109              
1110 36 100       154 if ( $attrs->{FIXED} ) {
    50          
1111 2         4 $_[0] = $rv;
1112             }
1113             elsif ( !$attrs->{ACTIVE} ) {
1114 34     0   114 $attrs->{$context} = sub { $rv };
  0         0  
1115             }
1116 36         213 return $rv;
1117             }
1118 0         0 $@ = _in_context "Can't use return value of $attrs->{sub} as a string";
1119 0 0       0 if (my $recover = $attrs->{RECOVER}) {
1120 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1121             }
1122             else {
1123 0         0 die $@;
1124             }
1125             },
1126              
1127             q{0+} => sub {
1128 30     30   604 my ($self) = @_;
1129 30         46 local $Contextual::Return::__RETOBJ__ = $self;
1130 31     31   121 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         31  
  31         7818  
  30         50  
1131 30         92 my $attrs = $attrs_of{refaddr $self};
1132             handler:
1133 30         62 for my $context (qw(NUM SCALAR LAZY VALUE NONVOID DEFAULT STR)) {
1134             my $handler = $attrs->{$context}
1135             or $attrs->{STRICT} and last handler
1136 50 50 50     170 or next handler;
      66        
1137              
1138 30         39 local $Contextual::Return::__RESULT__;
1139 30         44 local $Contextual::Return::uplevel = 2;
1140 30         52 my $rv = eval { $handler->(@{$attrs->{args}}) };
  30         36  
  30         80  
1141              
1142 30 100       183 if (my $recover = $attrs->{RECOVER}) {
    100          
1143 5 50       13 if (!$Contextual::Return::__RESULT__) {
1144 5         9 $Contextual::Return::__RESULT__ = [$rv];
1145             }
1146 5         8 scalar $recover->(@{$attrs->{args}});
  5         12  
1147             }
1148             elsif ($@) {
1149 3         11 die $@;
1150             }
1151              
1152 27 100       602 if ($Contextual::Return::__RESULT__) {
1153 9         20 $rv = $Contextual::Return::__RESULT__->[0];
1154             }
1155              
1156 27 100       116 if ( $attrs->{FIXED} ) {
    50          
1157 1         1 $_[0] = $rv;
1158             }
1159             elsif ( !$attrs->{ACTIVE} ) {
1160 26     1   91 $attrs->{$context} = sub { $rv };
  1         2  
1161             }
1162 27         136 return $rv;
1163             }
1164 0         0 $@ = _in_context "Can't use return value of $attrs->{sub} as a number";
1165 0 0       0 if (my $recover = $attrs->{RECOVER}) {
1166 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1167             }
1168             else {
1169 0         0 die $@;
1170             }
1171             },
1172              
1173             q{bool} => sub {
1174 34     34   1093 my ($self) = @_;
1175 34         50 local $Contextual::Return::__RETOBJ__ = $self;
1176 31     31   118 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         41  
  31         10938  
  34         54  
1177 34         101 my $attrs = $attrs_of{refaddr $self};
1178              
1179             # Handle Calls in Pure Boolean context...
1180 34 100       112 my @PUREBOOL = $attrs->{want_pure_bool} ? ('PUREBOOL') : ();
1181 34         50 $attrs->{want_pure_bool} = 0;
1182              
1183             handler:
1184 34         68 for my $context (@PUREBOOL, qw(BOOL STR NUM SCALAR LAZY VALUE NONVOID DEFAULT)) {
1185             my $handler = $attrs->{$context}
1186             or $context eq 'BOOL' and $attrs->{STRICT} and last handler
1187 57 50 66     202 or next handler;
      50        
      66        
1188              
1189 35         46 local $Contextual::Return::__RESULT__;
1190 35         49 local $Contextual::Return::uplevel = 2;
1191 35         67 my $outer_sig_warn = $SIG{__WARN__};
1192             local $SIG{__WARN__}
1193 1 50   1   6 = sub{ return if $_[0] =~ /^Exiting \S+ via next/;
1194 1 50       3 goto &{$outer_sig_warn} if $outer_sig_warn;
  1         8  
1195 0         0 warn @_;
1196 35         523 };
1197 35         62 my $rv = eval { $handler->(@{$attrs->{args}}) };
  35         37  
  35         94  
1198              
1199 34 100       1154 if (my $recover = $attrs->{RECOVER}) {
    50          
1200 4 50       12 if (!$Contextual::Return::__RESULT__) {
1201 4         6 $Contextual::Return::__RESULT__ = [$rv];
1202             }
1203 4         6 scalar $recover->(@{$attrs->{args}});
  4         11  
1204             }
1205             elsif ($@) {
1206 0         0 die $@;
1207             }
1208              
1209 34 100       950 if ($Contextual::Return::__RESULT__) {
1210 8         14 $rv = $Contextual::Return::__RESULT__->[0];
1211             }
1212              
1213 34 100       125 if ( $attrs->{FIXED} ) {
    50          
1214 1         2 $_[0] = $rv;
1215             }
1216             elsif ( !$attrs->{ACTIVE} ) {
1217 33     3   127 $attrs->{$context} = sub { $rv };
  3         8  
1218             }
1219 34         340 return $rv;
1220             }
1221 0         0 $@ = _in_context "Can't use return value of $attrs->{sub} as a boolean";
1222 0 0       0 if (my $recover = $attrs->{RECOVER}) {
1223 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1224             }
1225             else {
1226 0         0 die $@;
1227             }
1228             },
1229             '${}' => sub {
1230 24     24   557 my ($self) = @_;
1231 24         30 local $Contextual::Return::__RETOBJ__ = $self;
1232 31     31   133 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         46  
  31         9167  
  24         32  
1233 24         61 my $attrs = $attrs_of{refaddr $self};
1234             handler:
1235 24         42 for my $context (qw(SCALARREF REF NONVOID DEFAULT)) {
1236             my $handler = $attrs->{$context}
1237             or $attrs->{STRICT} and last handler
1238 48 50 100     160 or next handler;
      66        
1239              
1240 15         17 local $Contextual::Return::__RESULT__;
1241 15         19 local $Contextual::Return::uplevel = 2;
1242 15         22 my $rv = eval { $handler->(@{$attrs->{args}}) };
  15         16  
  15         42  
1243              
1244 15 100       99 if (my $recover = $attrs->{RECOVER}) {
    50          
1245 1 50       2 if (!$Contextual::Return::__RESULT__) {
1246 1         2 $Contextual::Return::__RESULT__ = [$rv];
1247             }
1248 1         1 scalar $recover->(@{$attrs->{args}});
  1         3  
1249             }
1250             elsif ($@) {
1251 0         0 die $@;
1252             }
1253              
1254 15 100       308 if ($Contextual::Return::__RESULT__) {
1255 5         8 $rv = $Contextual::Return::__RESULT__->[0];
1256             }
1257              
1258             # Catch bad behaviour...
1259 15 50 33     52 die _in_context "$context block did not return ",
1260             "a suitable reference to the scalar dereference"
1261             if ref($rv) ne 'SCALAR' && ref($rv) ne 'OBJ';
1262              
1263 15 100       56 if ( $attrs->{FIXED} ) {
    50          
1264 1         2 $_[0] = $rv;
1265             }
1266             elsif ( !$attrs->{ACTIVE} ) {
1267 14     0   45 $attrs->{$context} = sub { $rv };
  0         0  
1268             }
1269 15         93 return $rv;
1270             }
1271              
1272 9 100       19 if ($attrs->{STRICT}) {
1273 1         6 $@ = _in_context "Call to $attrs->{sub} didn't return a scalar reference, as required ";
1274 1 50       5 if (my $recover = $attrs->{RECOVER}) {
1275 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1276             }
1277             else {
1278 1         8 die $@;
1279             }
1280             }
1281              
1282 8 100       16 if ( $attrs->{FIXED} ) {
1283 1         3 $_[0] = \$self;
1284             }
1285 8         27 return \$self;
1286             },
1287             '@{}' => sub {
1288 22     22   560 my ($self) = @_;
1289 22         42 local $Contextual::Return::__RETOBJ__ = $self;
1290 31     31   140 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         33  
  31         12706  
  22         35  
1291 22         66 my $attrs = $attrs_of{refaddr $self};
1292 22         27 local $Contextual::Return::__RESULT__;
1293             handler:
1294 22         40 for my $context (qw(ARRAYREF REF)) {
1295             my $handler = $attrs->{$context}
1296             or $attrs->{STRICT} and last handler
1297 28 50 100     122 or next handler;
      66        
1298              
1299 15         19 local $Contextual::Return::uplevel = 2;
1300 15         30 my $rv = eval { $handler->(@{$attrs->{args}}) };
  15         19  
  15         40  
1301              
1302 15 100       451 if (my $recover = $attrs->{RECOVER}) {
    50          
1303 1 50       3 if (!$Contextual::Return::__RESULT__) {
1304 1         1 $Contextual::Return::__RESULT__ = [$rv];
1305             }
1306 1         2 scalar $recover->(@{$attrs->{args}});
  1         2  
1307             }
1308             elsif ($@) {
1309 0         0 die $@;
1310             }
1311              
1312 15 100       299 if ($Contextual::Return::__RESULT__) {
1313 5         9 $rv = $Contextual::Return::__RESULT__->[0];
1314             }
1315              
1316             # Catch bad behaviour...
1317 15 50 33     56 die _in_context "$context block did not return ",
1318             "a suitable reference to the array dereference"
1319             if ref($rv) ne 'ARRAY' && ref($rv) ne 'OBJ';
1320              
1321 15 100       61 if ( $attrs->{FIXED} ) {
    50          
1322 1         2 $_[0] = $rv;
1323             }
1324             elsif ( !$attrs->{ACTIVE} ) {
1325 14     0   52 $attrs->{$context} = sub { $rv };
  0         0  
1326             }
1327 15         83 return $rv;
1328             }
1329             handler:
1330 7         17 for my $context (qw(LIST VALUE NONVOID DEFAULT)) {
1331 9 100       21 last handler if $attrs->{STRICT};
1332 8 100       20 my $handler = $attrs->{$context}
1333             or next handler;
1334              
1335 6         10 local $Contextual::Return::uplevel = 2;
1336 6         9 my @rv = eval { $handler->(@{$attrs->{args}}) };
  6         4  
  6         14  
1337              
1338 6 50       36 if (my $recover = $attrs->{RECOVER}) {
    50          
1339 0 0       0 if (!$Contextual::Return::__RESULT__) {
1340 0         0 $Contextual::Return::__RESULT__ = [@rv];
1341             }
1342 0         0 () = $recover->(@{$attrs->{args}});
  0         0  
1343             }
1344             elsif ($@) {
1345 0         0 die $@;
1346             }
1347              
1348 6 50       14 if ($Contextual::Return::__RESULT__) {
1349 0         0 @rv = @{$Contextual::Return::__RESULT__->[0]};
  0         0  
1350             }
1351              
1352 6 100       16 if ( $attrs->{FIXED} ) {
    50          
1353 1         2 $_[0] = \@rv;
1354             }
1355             elsif ( !$attrs->{ACTIVE} ) {
1356 5     0   17 $attrs->{$context} = sub { @rv };
  0         0  
1357             }
1358 6         49 return \@rv;
1359             }
1360              
1361 1 50       2 if ($attrs->{STRICT}) {
1362 1         5 $@ = _in_context "Call to $attrs->{sub} didn't return an array reference, as required ";
1363 1 50       4 if (my $recover = $attrs->{RECOVER}) {
1364 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1365             }
1366             else {
1367 1         6 die $@;
1368             }
1369             }
1370              
1371 0         0 return [ $self ];
1372             },
1373             '%{}' => sub {
1374 16     16   283 my ($self) = @_;
1375 16         25 local $Contextual::Return::__RETOBJ__ = $self;
1376 31     31   130 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         49  
  31         8425  
  16         32  
1377 16         47 my $attrs = $attrs_of{refaddr $self};
1378             handler:
1379 16         30 for my $context (qw(HASHREF REF NONVOID DEFAULT)) {
1380             my $handler = $attrs->{$context}
1381             or $attrs->{STRICT} and last handler
1382 16 0 50     64 or next handler;
      66        
1383              
1384 15         15 local $Contextual::Return::__RESULT__;
1385 15         19 local $Contextual::Return::uplevel = 2;
1386 15         22 my $rv = eval { $handler->(@{$attrs->{args}}) };
  15         15  
  15         41  
1387              
1388 15 100       96 if (my $recover = $attrs->{RECOVER}) {
    50          
1389 1 50       6 if (!$Contextual::Return::__RESULT__) {
1390 1         2 $Contextual::Return::__RESULT__ = [$rv];
1391             }
1392 1         1 scalar $recover->(@{$attrs->{args}});
  1         2  
1393             }
1394             elsif ($@) {
1395 0         0 die $@;
1396             }
1397              
1398 15 100       293 if ($Contextual::Return::__RESULT__) {
1399 5         8 $rv = $Contextual::Return::__RESULT__->[0];
1400             }
1401              
1402             # Catch bad behaviour...
1403 15 50 33     60 die _in_context "$context block did not return ",
1404             "a suitable reference to the hash dereference"
1405             if ref($rv) ne 'HASH' && ref($rv) ne 'OBJ';
1406              
1407 15 100       52 if ( $attrs->{FIXED} ) {
    50          
1408 1         2 $_[0] = $rv;
1409             }
1410             elsif ( !$attrs->{ACTIVE} ) {
1411 14     1   51 $attrs->{$context} = sub { $rv };
  1         3  
1412             }
1413 15         108 return $rv;
1414             }
1415 1         5 $@ = _in_context "Call to $attrs->{sub} didn't return a hash reference, as required ";
1416 1 50       3 if (my $recover = $attrs->{RECOVER}) {
1417 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1418             }
1419             else {
1420 1         5 die $@;
1421             }
1422             },
1423             '&{}' => sub {
1424 7     7   288 my ($self) = @_;
1425 7         11 local $Contextual::Return::__RETOBJ__ = $self;
1426 31     31   123 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         46  
  31         8970  
  7         14  
1427 7         24 my $attrs = $attrs_of{refaddr $self};
1428             handler:
1429 7         15 for my $context (qw(CODEREF REF NONVOID DEFAULT)) {
1430             my $handler = $attrs->{$context}
1431             or $attrs->{STRICT} and last handler
1432 7 0 0     30 or next handler;
      33        
1433              
1434 7         11 local $Contextual::Return::__RESULT__;
1435 7         50 local $Contextual::Return::uplevel = 2;
1436 7         11 my $rv = eval { $handler->(@{$attrs->{args}}) };
  7         9  
  7         84  
1437              
1438 7 100       47 if (my $recover = $attrs->{RECOVER}) {
    50          
1439 1 50       2 if (!$Contextual::Return::__RESULT__) {
1440 1         2 $Contextual::Return::__RESULT__ = [$rv];
1441             }
1442 1         1 scalar $recover->(@{$attrs->{args}});
  1         3  
1443             }
1444             elsif ($@) {
1445 0         0 die $@;
1446             }
1447              
1448 7 100       299 if ($Contextual::Return::__RESULT__) {
1449 2         4 $rv = $Contextual::Return::__RESULT__->[0];
1450             }
1451              
1452             # Catch bad behaviour...
1453 7 50 33     31 die _in_context "$context block did not return ",
1454             "a suitable reference to the subroutine dereference"
1455             if ref($rv) ne 'CODE' && ref($rv) ne 'OBJ';
1456              
1457 7 100       46 if ( $attrs->{FIXED} ) {
    50          
1458 1         2 $_[0] = $rv;
1459             }
1460             elsif ( !$attrs->{ACTIVE} ) {
1461 6     0   23 $attrs->{$context} = sub { $rv };
  0         0  
1462             }
1463 7         30 return $rv;
1464             }
1465 0         0 $@ = _in_context "Call to $attrs->{sub} didn't return a subroutine reference, as required ";
1466 0 0       0 if (my $recover = $attrs->{RECOVER}) {
1467 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1468             }
1469             else {
1470 0         0 die $@;
1471             }
1472             },
1473             '*{}' => sub {
1474 7     7   269 my ($self) = @_;
1475 7         12 local $Contextual::Return::__RETOBJ__ = $self;
1476 31     31   134 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         42  
  31         7752  
  7         15  
1477 7         21 my $attrs = $attrs_of{refaddr $self};
1478             handler:
1479 7         19 for my $context (qw(GLOBREF REF NONVOID DEFAULT)) {
1480             my $handler = $attrs->{$context}
1481             or $attrs->{STRICT} and last handler
1482 7 0 0     24 or next handler;
      33        
1483              
1484 7         14 local $Contextual::Return::__RESULT__;
1485 7         11 local $Contextual::Return::uplevel = 2;
1486 7         12 my $rv = eval { $handler->(@{$attrs->{args}}) };
  7         7  
  7         23  
1487              
1488 7 100       41 if (my $recover = $attrs->{RECOVER}) {
    50          
1489 1 50       2 if (!$Contextual::Return::__RESULT__) {
1490 1         2 $Contextual::Return::__RESULT__ = [$rv];
1491             }
1492 1         1 scalar $recover->(@{$attrs->{args}});
  1         2  
1493             }
1494             elsif ($@) {
1495 0         0 die $@;
1496             }
1497              
1498 7 100       283 if ($Contextual::Return::__RESULT__) {
1499 2         4 $rv = $Contextual::Return::__RESULT__->[0];
1500             }
1501              
1502             # Catch bad behaviour...
1503 7 50 33     45 die _in_context "$context block did not return ",
1504             "a suitable reference to the typeglob dereference"
1505             if ref($rv) ne 'GLOB' && ref($rv) ne 'OBJ';
1506              
1507 7 100       39 if ( $attrs->{FIXED} ) {
    50          
1508 1         1 $_[0] = $rv;
1509             }
1510             elsif ( !$attrs->{ACTIVE} ) {
1511 6     0   23 $attrs->{$context} = sub { $rv };
  0         0  
1512             }
1513 7         44 return $rv;
1514             }
1515 0         0 $@ = _in_context "Call to $attrs->{sub} didn't return a typeglob reference, as required ";
1516 0 0       0 if (my $recover = $attrs->{RECOVER}) {
1517 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1518             }
1519             else {
1520 0         0 die $@;
1521             }
1522             },
1523 31     31   1559 );
1524             }
1525              
1526 31     31   30938 use overload %operator_impl, fallback => 1;
  31         25963  
  31         192  
1527              
1528             sub DESTROY {
1529 247     247   15414 my ($id) = refaddr shift;
1530 247         322 my $attrs = $attrs_of{$id};
1531 31     31   3569 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         41  
  31         9879  
  247         388  
1532 247 100       484 if (my $handler = $attrs->{CLEANUP}) {
1533 13         11 $handler->(@{ $attrs->{args} });
  13         27  
1534             }
1535 247         3094 delete $attrs_of{$id};
1536 247         2435 return;
1537             }
1538              
1539             my $NO_SUCH_METHOD = qr/\ACan't (?:locate|call)(?: class| object)? method/ms;
1540              
1541             # Forward metainformation requests to actual class...
1542             sub can {
1543 7     7   21 my ($invocant) = @_;
1544             # Only forward requests on actual C::R::V objects...
1545 7 100       14 if (ref $invocant) {
1546 6         6 our $AUTOLOAD = 'can';
1547 6         18 goto &AUTOLOAD;
1548             }
1549              
1550             # Refer requests on classes to actual class hierarchy...
1551 1         10 return $invocant->SUPER::can(@_[1..$#_]);
1552             }
1553              
1554             sub isa {
1555             # Only forward requests on actual C::R::V objects...
1556 2     2   11 my ($invocant) = @_;
1557 2 100       5 if (ref $invocant) {
1558 1         1 our $AUTOLOAD = 'isa';
1559 1         3 goto &AUTOLOAD;
1560             }
1561              
1562             # Refer requests on classes to actual class hierarchy...
1563 1         13 return $invocant->SUPER::isa(@_[1..$#_]);
1564             }
1565              
1566              
1567             sub AUTOLOAD {
1568 22     22   678 my ($self) = @_;
1569 22         17 our $AUTOLOAD;
1570              
1571 22 100       113 my ($requested_method) = $AUTOLOAD =~ m{ .* :: (.*) }xms ? $1 : $AUTOLOAD;
1572              
1573 22   50     78 my $attrs = $attrs_of{refaddr $self} || {};
1574 22         24 local $Contextual::Return::__RETOBJ__ = $self;
1575 31     31   140 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         34  
  31         22486  
  22         31  
1576              
1577             # First, see if there is a method call handler...
1578 22 100       40 if (my $context_handler = $attrs->{METHOD}) {
1579 8         11 local $Contextual::Return::__RESULT__;
1580 8         8 local $Contextual::Return::uplevel = 2;
1581 8         8 my @method_handlers = eval { $context_handler->(@{$attrs->{args}}) };
  8         3  
  8         21  
1582              
1583 8 50       102 if (my $recover = $attrs->{RECOVER}) {
    50          
1584 0 0       0 if (!$Contextual::Return::__RESULT__) {
1585 0         0 $Contextual::Return::__RESULT__ = [\@method_handlers];
1586             }
1587 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1588             }
1589             elsif ($@) {
1590 0         0 die $@;
1591             }
1592              
1593 8 50       14 if ($Contextual::Return::__RESULT__) {
1594 0         0 @method_handlers = @{$Contextual::Return::__RESULT__};
  0         0  
1595             }
1596              
1597             # Locate the correct method handler (if any)...
1598             MATCHER:
1599 8         21 while (my ($matcher, $method_handler) = splice @method_handlers, 0, 2) {
1600              
1601 16 100       107 if (ref($matcher) eq 'ARRAY') {
    100          
1602             next MATCHER
1603 3 100       1 if !grep { $requested_method =~ $_ } @{$matcher};
  6         39  
  3         5  
1604             }
1605             elsif ($requested_method !~ $matcher) {
1606 8         27 next MATCHER;
1607             }
1608              
1609 7         7 shift;
1610 7 50       17 if (wantarray) {
1611 0         0 my @result = eval {
1612 0         0 local $_ = $requested_method;
1613 0         0 $method_handler->($self,@_);
1614             };
1615 0 0       0 die _in_context $@ if $@;
1616 0         0 return @result;
1617             }
1618             else {
1619 7         6 my $result = eval {
1620 7         8 local $_ = $requested_method;
1621 7         14 $method_handler->($self,@_);
1622             };
1623 7 50       28 die _in_context $@ if $@;
1624 7         58 return $result;
1625             }
1626             }
1627             }
1628              
1629             # Next, try to create an object on which to call the method...
1630             handler:
1631 15         32 for my $context (qw(OBJREF STR SCALAR LAZY VALUE NONVOID DEFAULT)) {
1632             my $handler = $attrs->{$context}
1633             or $attrs->{STRICT} and last handler
1634 61 50 50     152 or next handler;
      66        
1635              
1636 10         8 local $Contextual::Return::__RESULT__;
1637 10         9 local $Contextual::Return::uplevel = 2;
1638 10         12 my $object = eval { $handler->(@{$attrs->{args}}) };
  10         5  
  10         24  
1639              
1640 10 50       48 if (my $recover = $attrs->{RECOVER}) {
    50          
1641 0 0       0 if (!$Contextual::Return::__RESULT__) {
1642 0         0 $Contextual::Return::__RESULT__ = [$object];
1643             }
1644 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1645             }
1646             elsif ($@) {
1647 0         0 die $@;
1648             }
1649              
1650 10 50       15 if ($Contextual::Return::__RESULT__) {
1651 0         0 $object = $Contextual::Return::__RESULT__->[0];
1652             }
1653              
1654 10 100       22 if ( $attrs->{FIXED} ) {
    50          
1655 1         2 $_[0] = $object;
1656             }
1657             elsif ( !$attrs->{ACTIVE} ) {
1658 9     0   23 $attrs->{$context} = sub { $object };
  0         0  
1659             }
1660 10         10 shift;
1661              
1662 10 50       16 if (wantarray) {
1663 0         0 my @result = eval { $object->$requested_method(@_) };
  0         0  
1664 0         0 my $exception = $@;
1665 0 0       0 return @result if !$exception;
1666 0 0       0 die _in_context $exception if $exception !~ $NO_SUCH_METHOD;
1667             }
1668             else {
1669 10         9 my $result = eval { $object->$requested_method(@_) };
  10         59  
1670 10         24 my $exception = $@;
1671 10 100       36 return $result if !$exception;
1672 4 100       25 die _in_context $exception if $exception !~ $NO_SUCH_METHOD;
1673             }
1674 3         13 $@ = _in_context "Can't call method '$requested_method' on $context value returned by $attrs->{sub}";
1675 3 50       6 if (my $recover = $attrs->{RECOVER}) {
1676 0         0 scalar $recover->(@{$attrs->{args}});
  0         0  
1677             }
1678             else {
1679 3         19 die $@;
1680             }
1681             }
1682              
1683             # Otherwise, the method cannot be called, so react accordingly...
1684 5         15 $@ = _in_context "Can't call method '$requested_method' on value returned by $attrs->{sub}";
1685 5 50       10 if (my $recover = $attrs->{RECOVER}) {
1686 0         0 return scalar $recover->(@{$attrs->{args}});
  0         0  
1687             }
1688             else {
1689 5         108 die $@;
1690             }
1691             }
1692              
1693             package Contextual::Return::Lvalue;
1694              
1695             sub TIESCALAR {
1696 10     10   18 my ($package, @handler) = @_;
1697 10         32 return bless {@handler}, $package;
1698             }
1699              
1700             # Handle calls that are lvalues...
1701             sub STORE {
1702 3     3   7 local *CALLER::_ = \$_;
1703 3         5 local *_ = \$_[1];
1704 3         4 local $Contextual::Return::uplevel = 1;
1705 31     31   147 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         34  
  31         3199  
  3         3  
1706 3         3 local $Contextual::Return::__RESULT__;
1707              
1708 3         2 my $rv = $_[0]{LVALUE}( @{$_[0]{args}} );
  3         9  
1709              
1710 3 50       660 return $rv if !$Contextual::Return::__RESULT__;
1711 0         0 return $Contextual::Return::__RESULT__->[0];
1712             }
1713              
1714             # Handle calls that are rvalues...
1715             sub FETCH {
1716 21     21   22 local $Contextual::Return::uplevel = 1;
1717 31     31   139 no warnings 'redefine'; local *CORE::GLOBAL::caller = $smart_caller;
  31         36  
  31         3673  
  21         26  
1718 21         18 local $Contextual::Return::__RESULT__;
1719              
1720 21 50       34 my $rv = $_[0]{RVALUE} ? $_[0]{RVALUE}( @{$_[0]{args}} ) : undef;
  21         46  
1721              
1722 21 50       245 return $rv if !$Contextual::Return::__RESULT__;
1723 0           return $Contextual::Return::__RESULT__->[0];
1724             }
1725              
1726       0     sub DESTROY {};
1727              
1728             1; # Magic true value required at end of module
1729              
1730             __END__