File Coverage

blib/lib/Mu/Tiny.pm
Criterion Covered Total %
statement 65 72 90.2
branch 15 30 50.0
condition 7 14 50.0
subroutine 14 15 93.3
pod 0 1 0.0
total 101 132 76.5


line stmt bran cond sub pod time code
1             package Mu::Tiny;
2              
3             our $VERSION = '0.000001'; # 0.0.1
4              
5             $VERSION = eval $VERSION;
6              
7 1     1   70926 use strict;
  1         2  
  1         31  
8 1     1   4 use warnings;
  1         2  
  1         26  
9 1     1   4 use Carp ();
  1         2  
  1         39  
10              
11             sub import {
12 1     1   8 my $targ = caller;
13 1         5 strict->import;
14 1         13 warnings->import;
15 1     1   5 no strict 'refs';
  1         2  
  1         650  
16 1   50     2 @$_ or @$_ = ('Mu::Tiny::Object') for my $isa = \@{"${targ}::ISA"};
  1         24  
17 1         11 my $attrs;
18 1         5 *{"${targ}::extends"} = sub {
19 0 0   0   0 Carp::croak "Can't call extends after attributes" if $attrs;
20 0 0       0 Carp::croak "No superclass list passed to extends" unless @_;
21 0         0 foreach my $el (@_) {
22 0         0 require join('/', split '::', $el).'.pm';
23             }
24 0         0 @$isa = @_;
25 1         5 };
26 1         4 *{"${targ}::ro"} = sub {
27 2 50   2   11 Carp::croak "No name passed to ro" unless my $name = shift;
28 2 50       6 Carp::croak "Extra args passed to ro" if @_;
29 2   66     6 ($attrs||=_setup_attrs($targ))->{$name} = 1;
30 2     1   6 *{"${targ}::${name}"} = sub { $_[0]->{$name} };
  2         8  
  1         10  
31 1         5 };
32 1         50 *{"${targ}::lazy"} = sub {
33 1 50   1   6 Carp::croak "No name passed to lazy" unless my $name = shift;
34 1 50       3 Carp::croak "No builder passed to lazy" unless my $builder = shift;
35 1 50       3 Carp::croak "Extra args passed to lazy" if @_;
36 1   33     3 ($attrs||=_setup_attrs($targ))->{$name} = 0;
37 1 50       4 if (ref($builder) eq 'CODE') {
    0          
38 1         2 my $method = "_build_${name}";
39 1         2 *{"${targ}::${method}"} = $builder;
  1         14  
40 1         3 $builder = $method;
41             } elsif (ref($builder)) {
42 0         0 Carp::croak "Builder passed to lazy must be name or code, not ${builder}";
43             }
44 1         1544 *{"${targ}::${name}"} = sub {
45             exists($_[0]->{$name})
46             ? $_[0]->{name}
47 1 50   1   8 : ($_[0]->{name} = $_[0]->$builder)
48 1         10 };
49 1         3 };
50             }
51              
52             my $ATTRS = '__Mu__Tiny__attrs';
53              
54             sub _setup_attrs {
55 1     1   3 my ($targ) = @_;
56 1         2 my $attrs = {};
57 1         10 my $orig = $targ->can($ATTRS);
58 1 50       3 Carp::croak "Can't find Mu::Tiny attrs method ${ATTRS} in ${targ}"
59             unless $orig;
60 1     1   8 no strict 'refs';
  1         2  
  1         336  
61 1     1   4 *{"${targ}::${ATTRS}"} = sub { $_[0]->$orig, %$attrs };
  1         4  
  1         4  
62 1         6 $attrs;
63             }
64              
65             package Mu::Tiny::Object;
66              
67 1     1   7 sub __Mu__Tiny__attrs { () }
68              
69             my %spec;
70              
71             sub new {
72 2     2 0 875 my $class = shift;
73 2   66     5 my ($attr, $req) = @{$spec{$class} ||= do {
  2         8  
74 1         3 my %attrs = $class->__Mu__Tiny__attrs;
75 1         15 [[ sort keys %attrs ], [ sort grep $attrs{$_}, keys %attrs ]];
76             }};
77 2 50       10 my %args = @_ ? @_ > 1 ? @_ : %{$_[0]} : ();
  0 100       0  
78 2         9 my @missing = grep !exists($args{$_}), @$req;
79 2 100       196 Carp::croak "Missing required attributes: ".join(', ', @missing) if @missing;
80 1 100       2 my %new = map { exists($args{$_}) ? ($_ => $args{$_}) : () } @$attr;
  3         9  
81 1   33     9 bless(\%new, ref($class) || $class);
82             }
83              
84             $INC{"Mu/Tiny/Object.pm"} = __FILE__;
85              
86             1;
87              
88             =head1 NAME
89              
90             Mu::Tiny - NAE KING! NAE QUIN! NAE CAPTAIN! WE WILLNAE BE FOOLED AGAIN!
91              
92             =head1 SYNOPSIS
93              
94             BEGIN {
95             package Feegle;
96            
97             use Mu::Tiny;
98            
99             ro 'name';
100             lazy plan => sub { 'PLN' };
101             }
102            
103             my $rob = Feegle->new(name => 'Rob Anybody'); # name is required
104            
105             say $rob->plan; # outputs 'PLN'
106              
107             =head1 DESCRIPTION
108              
109             This is the aaaabsoluuuute baaaaare minimumimumimum subset o' L, for
110             those o' ye who value yer independence over yer sanity. It doesnae trouble
111             wi' anythin' but the read-onlies, for tis a terrible thing to make a feegle
112             try t' write.
113              
114             =head1 METHODS
115              
116             =head2 new
117              
118             my $new = Feegle->new(%attrs|\%attrs);
119              
120             The new method be inherited from C like a shiny thing or
121             the duties o' a Kelda.
122              
123             Ye may hand it a hash, or if ye already made yer own hash o' things, a
124             reference to the one so pre-prepared.
125              
126             An ye forget any o' the attrs declared as L, then C will go
127             waily waily waily and C with a list of all that ye missed.
128              
129             =head1 EXPORTS
130              
131             =head2 ro
132              
133             ro 'attr';
134              
135             An C attr be required and read only, and knows nothin' but its own name.
136              
137             =head2 lazy
138              
139             lazy 'attr' => sub { };
140              
141             A attr be read only but not required, an' if ye make us, we'll take a
142             guess at what ye wanted, but only when we must.
143              
144             If'n ye be slightly less lazy than us, then subclass and override yan
145             C<_build_attr> method t' change tha guess.
146              
147             =head1 WHUT
148              
149             Dinnae fash yersel', Hamish, you prob'ly wanted L anyway.
150              
151             =head1 APOLOGIES
152              
153             ... to Terry Pratchett, Mithaldu, and probably everybody else as well.
154              
155             =head1 AUTHOR
156              
157             mst - Matt S. Trout (cpan:MSTROUT)
158              
159             =head1 CONTRIBUTORS
160              
161             None yet - maybe this software is perfect! (ahahahahahahahahaha)
162              
163             =head1 COPYRIGHT
164              
165             Copyright (c) 2020 the Mu::Tiny L and L
166             as listed above.
167              
168             =head1 LICENSE
169              
170             This library is free software and may be distributed under the same terms
171             as perl itself.