rewrite attribute validation regex to check everything
[p5sagit/Function-Parameters.git] / lib / Function / Parameters / Info.pm
CommitLineData
53c979f0 1package Function::Parameters::Info;
2
3use v5.14.0;
4
5use warnings;
6
47ba782a 7our $VERSION = '0.03';
53c979f0 8
8c4ca548 9# If Moo isn't loaded yet but Moose is, avoid pulling in Moo and fall back to Moose
47ba782a 10my $Moo;
8c4ca548 11BEGIN {
12 if ($INC{'Moose.pm'} && !$INC{'Moo.pm'}) {
13 $Moo = 'Moose';
8c4ca548 14 } else {
15 require Moo;
16 $Moo = 'Moo';
8c4ca548 17 }
18 $Moo->import;
19}
20
51a483f8 21{
22 package Function::Parameters::Param;
23
8c4ca548 24 BEGIN { $Moo->import; }
51a483f8 25 use overload
26 fallback => 1,
27 '""' => sub { $_[0]->name },
28 ;
29
30 has $_ => (is => 'ro') for qw(name type);
8c4ca548 31
47ba782a 32 __PACKAGE__->meta->make_immutable;
51a483f8 33}
34
53c979f0 35my @pn_ro = glob '{positional,named}_{required,optional}';
36
37for my $attr (qw[keyword invocant slurpy], map "_$_", @pn_ro) {
38 has $attr => (
39 is => 'ro',
40 );
41}
42
43for my $gen (join "\n", map "sub $_ { \@{\$_[0]->_$_} }", @pn_ro) {
44 eval "$gen\n1" or die $@;
45}
46
ebdc721b 47sub args_min {
48 my $self = shift;
49 my $r = 0;
50 $r++ if defined $self->invocant;
51 $r += $self->positional_required;
52 $r += $self->named_required * 2;
53 $r
54}
55
56sub args_max {
57 my $self = shift;
58 return 0 + 'Inf' if defined $self->slurpy || $self->named_required || $self->named_optional;
59 my $r = 0;
60 $r++ if defined $self->invocant;
61 $r += $self->positional_required;
62 $r += $self->positional_optional;
63 $r
64}
65
47ba782a 66__PACKAGE__->meta->make_immutable;
8c4ca548 67
53c979f0 68'ok'
69
70__END__
ebdc721b 71
72=encoding UTF-8
73
74=head1 NAME
75
76Function::Parameters::Info - Information about parameter lists
77
78=head1 SYNOPSIS
79
80 use Function::Parameters;
81
82 fun foo($x, $y, :$hello, :$world = undef) {}
83
84 my $info = Function::Parameters::info \&foo;
85 my $p0 = $info->invocant; # undef
86 my @p1 = $info->positional_required; # ('$x', '$y')
87 my @p2 = $info->positional_optional; # ()
88 my @p3 = $info->named_required; # ('$hello')
89 my @p4 = $info->named_optional; # ('$world')
90 my $p5 = $info->slurpy; # undef
91 my $min = $info->args_min; # 4
92 my $max = $info->args_max; # inf
93
94 my $invocant = Function::Parameters::info(method () { 42 })->invocant; # '$self'
95
96 my $slurpy = Function::Parameters::info(fun {})->slurpy; # '@_'
97
98=head1 DESCRIPTION
99
100L<C<Function::Parameters::info>|Function::Parameters/Introspection> returns
101objects of this class to describe parameter lists of functions. The following
102methods are available:
103
0d87c016 104=head2 $info->invocant
ebdc721b 105
106Returns the name of the variable into which the first argument is
420e3b82 107L<C<shift>|perlfunc/shift>ed automatically, or C<undef> if no such thing
ebdc721b 108exists. This will usually return C<'$self'> for methods.
109
0d87c016 110=head2 $info->positional_required
ebdc721b 111
112Returns a list of the names of the required positional parameters (or a count
113in scalar context).
114
0d87c016 115=head2 $info->positional_optional
ebdc721b 116
117Returns a list of the names of the optional positional parameters (or a count
118in scalar context).
119
0d87c016 120=head2 $info->named_required
ebdc721b 121
122Returns a list of the names of the required named parameters (or a count
123in scalar context).
124
0d87c016 125=head2 $info->named_optional
ebdc721b 126
127Returns a list of the names of the optional named parameters (or a count
128in scalar context).
129
0d87c016 130=head2 $info->slurpy
ebdc721b 131
132Returns the name of the final array or hash that gobbles up all remaining
133arguments, or C<undef> if no such thing exists.
134
135As a special case, functions defined without an explicit parameter list (i.e.
136without C<( )>) will return C<'@_'> here because they accept any number of
137arguments.
138
0d87c016 139=head2 $info->args_min
ebdc721b 140
141Returns the minimum number of arguments this function requires. This is
142computed as follows: Invocant and required positional parameters count 1 each.
143Optional parameters don't count. Required named parameters count 2 each (key +
144value). Slurpy parameters don't count either because they accept empty lists.
145
0d87c016 146=head2 $info->args_max
ebdc721b 147
148Returns the maximum number of arguments this function accepts. This is computed
149as follows: If there is any named or slurpy parameter, the result is C<Inf>.
150Otherwise the result is the sum of all invocant and positional parameters.
151
0175ff9a 152=head2 Experimental feature: Types
153
154All the methods described above actually return parameter objects wherever the
155description says "name". These objects have two methods: C<name>, which
156returns the name of the parameter (as a plain string), and C<type>, which
157returns the corresponding type constraint object (or undef if there was no type
158specified).
159
160This should be invisible if you don't use types because the objects also
161L<overload|overload> stringification to call C<name>. That is, if you treat
162parameter objects like strings, they behave like strings (i.e. their names).
163
ebdc721b 164=head1 SEE ALSO
165
166L<Function::Parameters>
167
168=head1 AUTHOR
169
170Lukas Mai, C<< <l.mai at web.de> >>
171
172=head1 COPYRIGHT & LICENSE
173
ea89928a 174Copyright 2013 Lukas Mai.
ebdc721b 175
176This program is free software; you can redistribute it and/or modify it
177under the terms of either: the GNU General Public License as published
178by the Free Software Foundation; or the Artistic License.
179
180See http://dev.perl.org/licenses/ for more information.
181
182=cut