File Coverage

blib/lib/Acme/Roman.pm
Criterion Covered Total %
statement 35 73 47.9
branch 2 34 5.8
condition n/a
subroutine 11 21 52.3
pod n/a
total 48 128 37.5


line stmt bran cond sub pod time code
1            
2             package Acme::Roman;
3            
4 3     3   24902 use strict;
  3         6  
  3         146  
5 3     3   14 use warnings;
  3         6  
  3         89  
6            
7 3     3   2516 use version; our $VERSION = qv('0.0.2.12');
  3         7594  
  3         23  
8            
9             require Roman;
10 3     3   275 use Carp qw( croak );
  3         5  
  3         226  
11            
12 3     3   16 use base qw( Class::Accessor );
  3         7  
  3         3134  
13             __PACKAGE__->mk_ro_accessors( qw( roman num ) );
14            
15             use overload
16 0     0   0 '0+' => sub { shift->num },
17 0     0   0 '""' => sub { shift->roman },
18 3         58 '+' => \&plus,
19             '-' => \&minus,
20             '*' => \×,
21             fallback => 1
22 3     3   9210 ;
  3         1213  
23            
24             # aliases to Roman functions, whose names dislike me
25             *to_roman = \&Roman::Roman;
26             *to_number = \&Roman::arabic;
27            
28             sub is_roman {
29 0 0   0   0 return "" if $_[0] =~ /[^IVXLCDM]/; # false: accept nothing but uppercase
30 0         0 return Roman::isroman(shift);
31             }
32            
33             sub new {
34 1     1   731 my $proto = shift;
35 1         2 my $arg = shift;
36 1 50       7 if ( $arg =~ /^\d+$/ ) { # looks like an arabic number
    0          
37 1 50       7 croak __PACKAGE__, " does not like numbers above 3999" if $arg > 3999;
38 1         148 return $proto->SUPER::new( { roman => Roman::Roman($arg), num => $arg } );
39             } elsif ( Roman::isroman($arg) ) {
40 0           return $proto->SUPER::new( { roman => $arg, num => Roman::arabic($arg) } );
41             } else {
42 0           croak "$arg does not look like a (roman or arabic) number";
43             }
44             }
45            
46             sub plus {
47 0     0     my $r1 = shift;
48 0           my $r2 = shift;
49 0 0         my $num1 = ref $r1 ? $r1->num : is_roman($r1) ? to_number($r1) : $r1;
    0          
50 0 0         my $num2 = ref $r2 ? $r2->num : is_roman($r2) ? to_number($r2) : $r2;
    0          
51 0           return __PACKAGE__->new( $num1 + $num2 );
52             }
53            
54             sub minus {
55 0     0     my $r1 = shift;
56 0           my $r2 = shift;
57 0 0         my $num1 = ref $r1 ? $r1->num : is_roman($r1) ? to_number($r1) : $r1;
    0          
58 0 0         my $num2 = ref $r2 ? $r2->num : is_roman($r2) ? to_number($r2) : $r2;
    0          
59 0           return __PACKAGE__->new( $num1 - $num2 );
60             }
61            
62             sub times {
63 0     0     my $r1 = shift;
64 0           my $r2 = shift;
65 0 0         my $num1 = ref $r1 ? $r1->num : is_roman($r1) ? to_number($r1) : $r1;
    0          
66 0 0         my $num2 = ref $r2 ? $r2->num : is_roman($r2) ? to_number($r2) : $r2;
    0          
67 0           return __PACKAGE__->new( $num1 * $num2 );
68             }
69            
70 3     3   1932 use vars qw( $AUTOLOAD );
  3         8  
  3         493  
71            
72             sub make_autoload {
73 0     0     my $package = shift;
74             return sub {
75 0     0     my $sub_name = $AUTOLOAD;
76 0           $sub_name =~ s/^.*:://;
77 0 0         if ( is_roman($sub_name) ) {
78 0           return Acme::Roman->new($sub_name);
79             } else {
80 0           croak "Undefined subroutine $AUTOLOAD called";
81             }
82 0           };
83             }
84            
85 3     3   19 use Scalar::Util qw( set_prototype );
  3         5  
  3         375  
86            
87             sub def_prototypes {
88 0     0     my $package = shift;
89 3     3   15 use strict;
  3         5  
  3         470  
90 0           for ( 1..3999 ) {
91 0           my $roman = to_roman($_);
92             # sets an empty prototype
93 0           set_prototype( \&{ "${package}::${roman}" }, '' );
  0            
94             #eval "sub ${package}::${roman} (); ";
95             }
96             }
97            
98             sub import {
99 0     0     my $package = caller;
100            
101 0           def_prototypes($package);
102            
103 0           my $autoload = make_autoload($package);
104 3     3   44 no strict 'refs';
  3         6  
  3         199  
105 0           *{ "${package}::AUTOLOAD" } = $autoload;
  0            
106             }
107            
108             1;
109            
110             __END__