File Coverage

blib/lib/Acme/Lvalue.pm
Criterion Covered Total %
statement 40 45 88.8
branch 3 6 50.0
condition n/a
subroutine 12 14 85.7
pod n/a
total 55 65 84.6


line stmt bran cond sub pod time code
1             package Acme::Lvalue;
2              
3 4     4   136770 use warnings;
  4         9  
  4         117  
4 4     4   20 use strict;
  4         9  
  4         123  
5              
6 4     4   73 use v5.16.0; # earliest release with #51408 fixed
  4         16  
  4         909  
7              
8             *VERSION = \'0.03';
9              
10             {
11             package Acme::Lvalue::Proxy;
12              
13             sub TIESCALAR {
14 21     21   46 my ($class, $ref, $func, $cnuf) = @_;
15 21         87 bless [$ref, $func, $cnuf], $class
16             }
17              
18             sub FETCH {
19 8     8   87 my ($self) = @_;
20 8         11 $self->[1]->(${$self->[0]})
  8         200  
21             }
22              
23             sub STORE {
24 17     17   40 my ($self, $val) = @_;
25 17         35 my $ref = $self->[0];
26 17         76 $$ref = $self->[2]->($val, $$ref);
27             }
28              
29 0     0   0 sub UNTIE {}
30 0     0   0 sub DESTROY {}
31             }
32              
33 4     4   157592 use Math::Trig;
  4         116137  
  4         904  
34 4     4   49 use Carp qw(croak);
  4         10  
  4         692  
35              
36             sub _export {
37 42     42   50 my ($where, $what, $how, $woh) = @_;
38             my $fun = sub ($) :lvalue {
39 21     21   6135 tie my $proxy, 'Acme::Lvalue::Proxy', \$_[0], $how, $woh;
40 21         109 $proxy
41 42         102 };
42 4     4   25 no strict 'refs';
  4         8  
  4         2850  
43 42         43 *{$where . '::' . $what} = $fun;
  42         5958  
44             }
45              
46             our %builtins = map +($_->[0] => [eval "sub {scalar $_->[0] \$_[0]}", $_->[1]]),
47             [chr => sub { ord $_[0] }],
48             [cos => sub { acos $_[0] }],
49             [defined =>
50             sub {
51             $_[0]
52             ? defined $_[1]
53             ? $_[1]
54             : 1
55             : undef
56             }
57             ],
58             [exp => sub { log $_[0] }],
59             [hex => sub { sprintf '%x', $_[0] }],
60             [length =>
61             sub {
62             my ($n, $x) = @_;
63             my $l = length $x;
64             $n <= $l
65             ? substr $x, 0, $n
66             : $x . "\0" x ($n - $l)
67             }
68             ],
69             [log => sub { exp $_[0] }],
70             [oct => sub { sprintf '%o', $_[0] }],
71             [ord => sub { chr $_[0] }],
72             [quotemeta => sub { $_[0] =~ s/\\(.)/$1/sgr }],
73             [reverse => sub { scalar reverse $_[0] }],
74             [sin => sub { asin $_[0] }],
75             [sqrt => sub { my $x = shift; $x * $x }],
76             ;
77              
78             sub import {
79 4     4   49 my $class = shift;
80 4         9 my $caller = caller;
81              
82 4         19 for my $item (@_) {
83 6 100       23 if (ref $item) {
    50          
    0          
84 3         7 _export $caller, @$item;
85             } elsif ($item eq ':builtins') {
86 3         13 for my $f (keys %builtins) {
87 39         43 _export $caller, $f, @{$builtins{$f}};
  39         76  
88             }
89             } elsif ($builtins{$item}) {
90 0           _export $caller, $item, @{$builtins{$item}};
  0            
91             } else {
92 0           croak qq{"$item" is not exported by the $class module};
93             }
94             }
95             }
96              
97             'ok'
98             __END__