File Coverage

blib/lib/Try/Catch.pm
Criterion Covered Total %
statement 62 62 100.0
branch 34 34 100.0
condition 4 6 66.6
subroutine 8 8 100.0
pod 3 3 100.0
total 111 113 98.2


line stmt bran cond sub pod time code
1             package Try::Catch;
2 13     13   191780 use strict;
  13         17  
  13         326  
3 13     13   44 use warnings;
  13         15  
  13         315  
4 13     13   45 use Carp;
  13         20  
  13         1045  
5             $Carp::Internal{+__PACKAGE__}++;
6 13     13   48 use base 'Exporter';
  13         15  
  13         6804  
7             our @EXPORT = our @EXPORT_OK = qw(try catch finally);
8             our $VERSION = '1.1.0';
9            
10             sub _default_catch {
11 4     4   506 croak $_[0];
12             }
13            
14             sub try(&;@) {
15 67     67 1 334 my $wantarray = wantarray;
16 67         62 my $try = shift;
17 67         63 my $caller = pop;
18 67         54 my $finally = pop;
19 67         62 my $catch = pop;
20            
21 67 100 66     313 if (!$caller || $caller ne __PACKAGE__){
22 1         76 croak "syntax error after try block \n" .
23             "usage : \n" .
24             "try { ... } catch { ... }; \n" .
25             "try { ... } finally { ... }; \n" .
26             "try { ... } catch { ... } finally { ... }; ";
27             }
28            
29             #sane behaviour is to throw an error
30             #if there is no catch block
31 66 100       110 if (!$catch){
32 12         26 $catch = \&_default_catch;
33             }
34            
35 66         60 my @ret;
36 66         80 my $prev_error = $@;
37 66         76 my $fail = not eval {
38 66         60 $@ = $prev_error;
39 66 100       111 if (!defined $wantarray) {
    100          
40 55         97 $try->();
41             } elsif (!$wantarray) {
42 7         14 $ret[0] = $try->();
43             } else {
44 4         9 @ret = $try->();
45             }
46 23         705153 return 1;
47             };
48            
49 62         1710 my $error = $@;
50            
51 62 100       148 if ($fail) {
52 39         34 my $ret = not eval {
53 39         36 $@ = $prev_error;
54 39         48 for ($error) {
55 39 100       59 if (!defined $wantarray) {
    100          
56 33         53 $catch->($error);
57             } elsif (!$wantarray) {
58 4         6 $ret[0] = $catch->($error);
59             } else {
60 2         5 @ret = $catch->($error);
61             }
62 27         4005 last; ## seems to boost speed by 7%
63             }
64 28         541 return 1;
65             };
66            
67 39 100       432 if ($ret){
68 11         26 my $catch_error = $@;
69 11 100       19 if ($finally) {
70 9         8 $@ = $prev_error;
71 9         15 $finally->($error);
72             }
73 11         3293 croak $catch_error;
74             }
75             }
76            
77 51 100       102 if ($finally) {
78 20         35 $@ = $prev_error;
79 20 100       108 $finally->( $fail ? $error : () );
80             }
81            
82 50         3140 $@ = $prev_error;
83 50 100       188 return $wantarray ? @ret : $ret[0];
84             }
85            
86             sub catch(&;@) {
87 60 100   60 1 5533 croak 'Useless bare catch()' unless wantarray;
88 57 100       167 if (@_ > 1){
89 20 100 66     155 croak "syntax error after catch block - maybe a missing semicolon"
90             if !$_[2] || $_[2] ne __PACKAGE__;
91             } else {
92 37         155 return ( shift, undef, __PACKAGE__);
93             }
94 19         46 return (@_);
95             }
96            
97             sub finally(&;@) {
98 36 100   36 1 4784 croak 'Useless bare finally()' unless wantarray;
99 33 100       89 if (@_ > 1) {
100 1         76 croak "syntax error after finally block - maybe a missing semicolon";
101             }
102 32         153 return ( shift, __PACKAGE__ );
103             }
104            
105             1;
106            
107             __END__