File Coverage

blib/lib/Try/Lite.pm
Criterion Covered Total %
statement 48 48 100.0
branch 18 20 90.0
condition 6 9 66.6
subroutine 7 7 100.0
pod 1 1 100.0
total 80 85 94.1


line stmt bran cond sub pod time code
1             package Try::Lite;
2 8     8   167382 use strict;
  8         21  
  8         247  
3 8     8   38 use warnings;
  8         14  
  8         230  
4 8     8   6333 use parent 'Exporter';
  8         2604  
  8         42  
5 8     8   555 use 5.008005;
  8         28  
  8         466  
6             our $VERSION = '0.0.3';
7              
8             our @EXPORT = 'try';
9              
10 8     8   44 use Scalar::Util;
  8         12  
  8         597  
11 8     8   40 use Carp;
  8         20  
  8         3420  
12             $Carp::Internal{+__PACKAGE__}++;
13              
14             sub try (&;%) {
15 29     29 1 32089 my($try, @catches) = @_;
16              
17 29 50       84 confess 'Unknown @catches values. Check your usage & try again'
18             unless @catches;
19              
20             # check @catches
21 29         96 for (my $i = 0; $i < @catches; $i += 2) {
22 31 50 33     264 confess q{illegal @catches values. try {} 'ClassName' => sub {}, ...;}
23             unless $catches[$i] && ref($catches[$i + 1]) eq 'CODE';
24             }
25              
26             # we need to save this here, the eval block will be in scalar context due
27             # to $failed
28 29         42 my $wantarray = wantarray;
29              
30             # save the value of $@ so we can set $@ back to it in the beginning of the eval
31             # and restore $@ after the eval finishes
32 29         39 my $prev_error = $@;
33              
34 29         57 my @ret;
35              
36             # failed will be true if the eval dies, because 1 will not be returned
37             # from the eval body
38 29         40 my $failed = not eval {
39 29         37 $@ = $prev_error;
40              
41             # evaluate the try block in the correct context
42 29 100       91 if ( $wantarray ) {
    100          
43 7         20 @ret = $try->();
44             } elsif ( defined $wantarray ) {
45 7         19 $ret[0] = $try->();
46             } else {
47 15         41 $try->();
48             };
49              
50 7         31 return 1; # properly set $fail to false
51             };
52              
53             # preserve the current error and reset the original value of $@
54 29         249 my $error = $@;
55 29         42 $@ = $prev_error;
56              
57 29 100       65 if ($failed) {
58 22         63 for (my $i = 0;$i < @catches;$i += 2) {
59 24         82 my($class, $code) = ($catches[$i], $catches[$i + 1]);
60 24 100 100     152 next unless $class eq '*' || (Scalar::Util::blessed($error) && UNIVERSAL::isa($error, $class));
      66        
61              
62             # evaluate the catch block in the correct context
63 19         25 $@ = $error;
64 19         25 my @ret;
65 19 100       55 if ( $wantarray ) {
    100          
66 4         11 @ret = $code->();
67             } elsif ( defined $wantarray ) {
68 4         11 $ret[0] = $code->();
69             } else {
70 11         49 $code->();
71             };
72              
73 16         54 $@ = $prev_error;
74 16 100       81 return $wantarray ? @ret : $ret[0];
75             }
76              
77             # rethrow
78 3         11 die $error;
79             }
80              
81             # no failure, $@ is back to what it was, everything is fine
82 7 100       28 return $wantarray ? @ret : $ret[0];
83             }
84              
85              
86             1;
87             __END__