File Coverage

blib/lib/Fixed.pm
Criterion Covered Total %
statement 47 51 92.1
branch 19 22 86.3
condition 2 3 66.6
subroutine 13 14 92.8
pod 1 1 100.0
total 82 91 90.1


line stmt bran cond sub pod time code
1             package Fixed;
2              
3 2     2   22881 use 5.012;
  2         7  
  2         65  
4 2     2   10 use strict;
  2         2  
  2         68  
5 2     2   9 use warnings;
  2         7  
  2         94  
6              
7             BEGIN {
8 2     2   5 $Fixed::AUTHORITY = 'cpan:TOBYINK';
9 2         45 $Fixed::VERSION = '0.001';
10             }
11              
12 2     2   1760 use Readonly;
  2         5679  
  2         97  
13 2     2   2071 use Text::Balanced;
  2         43913  
  2         306  
14              
15 2     2   1281 BEGIN {
16             package Fixed::Scalar;
17             sub TIESCALAR {
18 10     10   11 my $class = shift;
19 10         39 bless \@_, $class;
20             }
21             sub FETCH {
22 12     12   1104 $_[0][0];
23             }
24             sub STORE {
25 30     30   3597 my $self = shift;
26 30 100       92 Readonly::croak $Readonly::MODIFY if @$self;
27 10         33 push @$self, $_[0];
28             }
29             };
30              
31             my $KEYWORD = 'fix';
32             my $CLASS = __PACKAGE__;
33              
34             my $PERLSVAR = qr{\$[^\W0-9]\w*};
35             my $SPACE = qr{(?:\s|\#.*?\n)*}s;
36              
37             sub import
38             {
39 5     5   4510 require Keyword::Simple;
40             Keyword::Simple::define($KEYWORD, sub
41             {
42 15     15   267 my $ref = shift;
43 15         159 $$ref =~ s/^$SPACE//;
44              
45             # set $foo = 1;
46 15 100       592 if (my ($vname, $assignment, $rest) = ($$ref =~ /^($PERLSVAR)($SPACE=)(.*)$/s))
    100          
    100          
    100          
    100          
47             {
48 1         73 $$ref = "$CLASS\::Scalar my $vname => $rest";
49             }
50              
51             # set ($foo) = 1;
52             elsif (my ($vname4, $assignment4, $rest4) = ($$ref =~ /^\($SPACE($PERLSVAR)$SPACE\)($SPACE=)(.*)$/s))
53             {
54 2         115 $$ref = "$CLASS\::Scalar my $vname4 => $rest4";
55             }
56              
57             # set $foo;
58             elsif (my ($vname2, $rest2) = ($$ref =~ /^($PERLSVAR)$SPACE;(.*)$/s))
59             {
60 4         228 $$ref = "$CLASS\::Scalar my $vname2; $rest2";
61             }
62            
63             # set ($foo, $bar)
64             # set ($foo, $bar) = (1, 2);
65             elsif ($$ref =~ /^$SPACE\(/s)
66             {
67 4 50       23 my $extracted = Text::Balanced::extract_bracketed($$ref)
68             or Readonly::croak "usage: $KEYWORD (\$scalar, ...);";
69 4         599 $extracted =~ s/(^\(|\)$)//gs;
70 4         52 my @E = split /$SPACE,$SPACE/, $extracted;
71 4         22 for (@E)
72             {
73 6 50       59 Readonly::croak "$KEYWORD used for non scalar variable '$_'"
74             unless /^$PERLSVAR$/;
75             }
76             # If declaration includes an assignent, then ensure we have something to assign to!
77 4 100       6 my $extra = ''; $extra = "($extracted)" if $$ref =~ /^$SPACE=/;
  4         44  
78 4         410 $$ref = "$CLASS\::Scalar(\$_) for my ($extracted); $extra $$ref";
79             }
80            
81             elsif (
82             my ($vname3) = ($$ref =~ /^$SPACE([\@\%\*][^\W0-9]\w*)/s)
83             ) {
84 3         19 Readonly::croak "$KEYWORD used with non scalar variable '$vname3'";
85             }
86            
87             else {
88 1         6 Readonly::croak "usage: $KEYWORD \$variable = \$value;";
89             }
90 5         48022 });
91             }
92              
93             sub unimport
94             {
95 0     0   0 require Keyword::Simple;
96 0         0 Keyword::Simple::undefine($KEYWORD);
97             }
98              
99             sub Scalar
100             {
101 13 100 66 13 1 5448 if (@_ > 1 and $Readonly::XSokay) {
    50          
102 3         6 $_[0] = $_[1];
103 3         15 Readonly::make_sv_readonly($_[0]);
104 3         15 return;
105             }
106             elsif (@_ > 1) {
107 0         0 my $value = $_[1];
108 0         0 tie $_[0], "$CLASS\::Scalar", $value;
109             }
110             else {
111 10         49 tie $_[0], "$CLASS\::Scalar";
112             }
113             }
114              
115             1;
116              
117             __END__