File Coverage

blib/lib/Specio/Constraint/Parameterizable.pm
Criterion Covered Total %
statement 47 49 95.9
branch 12 20 60.0
condition n/a
subroutine 13 13 100.0
pod 1 2 50.0
total 73 84 86.9


line stmt bran cond sub pod time code
1              
2             use strict;
3 30     30   159 use warnings;
  30         52  
  30         686  
4 30     30   120  
  30         51  
  30         1019  
5             our $VERSION = '0.48';
6              
7             use Carp qw( confess );
8 30     30   146 use Role::Tiny::With;
  30         55  
  30         1167  
9 30     30   5943 use Specio::Constraint::Parameterized;
  30         72138  
  30         1300  
10 30     30   10914 use Specio::DeclaredAt;
  30         86  
  30         944  
11 30     30   6113 use Specio::OO;
  30         65  
  30         679  
12 30     30   159 use Specio::TypeChecks qw( does_role isa_class );
  30         54  
  30         1241  
13 30     30   145  
  30         50  
  30         1062  
14             use Specio::Constraint::Role::Interface;
15 30     30   156 with 'Specio::Constraint::Role::Interface';
  30         50  
  30         9843  
16              
17             {
18             ## no critic (Subroutines::ProtectPrivateSubs)
19             my $role_attrs = Specio::Constraint::Role::Interface::_attrs();
20             ## use critic
21              
22             my $attrs = {
23             %{$role_attrs},
24             _parameterized_constraint_generator => {
25             isa => 'CodeRef',
26             init_arg => 'parameterized_constraint_generator',
27             predicate => '_has_parameterized_constraint_generator',
28             },
29             _parameterized_inline_generator => {
30             isa => 'CodeRef',
31             init_arg => 'parameterized_inline_generator',
32             predicate => '_has_parameterized_inline_generator',
33             },
34             };
35              
36             ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
37             return $attrs;
38             }
39 493     493   866 }
40              
41             my $self = shift;
42              
43             if ( $self->_has_constraint ) {
44 120     120 0 1914 die
45             'A parameterizable constraint with a constraint parameter must also have a parameterized_constraint_generator'
46 120 50       298 unless $self->_has_parameterized_constraint_generator;
47 0 0       0 }
48              
49             if ( $self->_has_inline_generator ) {
50             die
51             'A parameterizable constraint with an inline_generator parameter must also have a parameterized_inline_generator'
52 120 50       599 unless $self->_has_parameterized_inline_generator;
53 120 50       628 }
54              
55             return;
56             }
57              
58 120         505 my $self = shift;
59             my %args = @_;
60              
61             my ( $parameter, $declared_at ) = @args{qw( of declared_at )};
62 15     15 1 154 does_role( $parameter, 'Specio::Constraint::Role::Interface' )
63 15         52 or confess
64             'The "of" parameter passed to ->parameterize must be an object which does the Specio::Constraint::Role::Interface role';
65 15         43  
66 15 50       43 if ($declared_at) {
67             isa_class( $declared_at, 'Specio::DeclaredAt' )
68             or confess
69             'The "declared_at" parameter passed to ->parameterize must be a Specio::DeclaredAt object';
70 15 100       252 }
71 14 50       43  
72             $declared_at = Specio::DeclaredAt->new_from_caller(1)
73             unless defined $declared_at;
74              
75             my %p = (
76 15 100       46 parent => $self,
77             parameter => $parameter,
78             declared_at => $declared_at,
79 15         60 );
80              
81             if ( $self->_has_parameterized_constraint_generator ) {
82             $p{constraint}
83             = $self->_parameterized_constraint_generator->($parameter);
84             }
85 15 50       60 else {
86             confess
87 0         0 'The "of" parameter passed to ->parameterize must be an inlinable constraint if the parameterizable type has an inline_generator'
88             unless $parameter->can_be_inlined;
89              
90 15 100       152 my $ig = $self->_parameterized_inline_generator;
91             $p{inline_generator} = sub { $ig->( shift, $parameter, @_ ) };
92             }
93              
94 14         137 return Specio::Constraint::Parameterized->new(%p);
95 14     13   108 }
  13         74  
96              
97             __PACKAGE__->_ooify;
98 14         94  
99             1;
100              
101             # ABSTRACT: A class which represents parameterizable constraints
102              
103              
104             =pod
105              
106             =encoding UTF-8
107              
108             =head1 NAME
109              
110             Specio::Constraint::Parameterizable - A class which represents parameterizable constraints
111              
112             =head1 VERSION
113              
114             version 0.48
115              
116             =head1 SYNOPSIS
117              
118             my $arrayref = t('ArrayRef');
119              
120             my $arrayref_of_int = $arrayref->parameterize( of => t('Int') );
121              
122             =head1 DESCRIPTION
123              
124             This class implements the API for parameterizable types like C<ArrayRef> and
125             C<Maybe>.
126              
127             =for Pod::Coverage BUILD
128              
129             =head1 API
130              
131             This class implements the same API as L<Specio::Constraint::Simple>, with a few
132             additions.
133              
134             =head2 Specio::Constraint::Parameterizable->new(...)
135              
136             This class's constructor accepts two additional parameters:
137              
138             =over 4
139              
140             =item * parameterized_constraint_generator
141              
142             This is a subroutine that generates a new constraint subroutine when the type
143             is parameterized.
144              
145             It will be called as a method on the type and will be passed a single argument,
146             the type object for the type parameter.
147              
148             This parameter is mutually exclusive with the C<parameterized_inline_generator>
149             parameter.
150              
151             =item * parameterized_inline_generator
152              
153             This is a subroutine that generates a new inline generator subroutine when the
154             type is parameterized.
155              
156             It will be called as a method on the L<Specio::Constraint::Parameterized>
157             object when that object needs to generate an inline constraint. It will receive
158             the type parameter as the first argument and the variable name as a string as
159             the second.
160              
161             This probably seems fairly confusing, so looking at the examples in the
162             L<Specio::Library::Builtins> code may be helpful.
163              
164             This parameter is mutually exclusive with the
165             C<parameterized_constraint_generator> parameter.
166              
167             =back
168              
169             =head2 $type->parameterize(...)
170              
171             This method takes two arguments. The C<of> argument should be an object which
172             does the L<Specio::Constraint::Role::Interface> role, and is required.
173              
174             The other argument, C<declared_at>, is optional. If it is not given, then a new
175             L<Specio::DeclaredAt> object is creating using a call stack depth of 1.
176              
177             This method returns a new L<Specio::Constraint::Parameterized> object.
178              
179             =head1 SUPPORT
180              
181             Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
182              
183             =head1 SOURCE
184              
185             The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
186              
187             =head1 AUTHOR
188              
189             Dave Rolsky <autarch@urth.org>
190              
191             =head1 COPYRIGHT AND LICENSE
192              
193             This software is Copyright (c) 2012 - 2022 by Dave Rolsky.
194              
195             This is free software, licensed under:
196              
197             The Artistic License 2.0 (GPL Compatible)
198              
199             The full text of the license can be found in the
200             F<LICENSE> file included with this distribution.
201              
202             =cut