implement 'classmethod' keyword type
[p5sagit/Function-Parameters.git] / lib / Function / Parameters.pm
CommitLineData
7a63380c 1package Function::Parameters;
2
7dd35535 3use v5.14.0;
4
7a63380c 5use strict;
6use warnings;
7
db81d362 8use XSLoader;
9BEGIN {
5d0dba1f 10 our $VERSION = '0.05_03';
db81d362 11 XSLoader::load;
7a63380c 12}
13
db81d362 14use Carp qw(confess);
7a63380c 15
2d5cf47a 16sub _assert_valid_identifier {
17 my ($name, $with_dollar) = @_;
18 my $bonus = $with_dollar ? '\$' : '';
19 $name =~ /^${bonus}[^\W\d]\w*\z/
20 or confess qq{"$name" doesn't look like a valid identifier};
21}
22
b72eb6ee 23sub _assert_valid_attributes {
24 my ($attrs) = @_;
25 $attrs =~ /^\s*:\s*[^\W\d]\w*\s*(?:(?:\s|:\s*)[^\W\d]\w*\s*)*(?:\(|\z)/
26 or confess qq{"$attrs" doesn't look like valid attributes};
27}
28
125c067e 29my @bare_arms = qw(function method);
2d5cf47a 30my %type_map = (
31 function => { name => 'optional' },
7947f7ce 32 method => {
33 name => 'optional',
34 shift => '$self',
35 attrs => ':method',
36 },
a23979e1 37 classmethod => {
38 name => 'optional',
39 shift => '$class',
40 attrs => ':method',
41 },
2d5cf47a 42);
c9a39f6b 43
db81d362 44sub import {
45 my $class = shift;
7a63380c 46
b72eb6ee 47 @_ or @_ = {
48 fun => 'function',
49 method => 'method',
50 };
125c067e 51 if (@_ == 1 && ref($_[0]) eq 'HASH') {
52 @_ = map [$_, $_[0]{$_}], keys %{$_[0]}
53 or return;
54 }
7a63380c 55
125c067e 56 my %spec;
57
58 my $bare = 0;
59 for my $proto (@_) {
60 my $item = ref $proto
61 ? $proto
62 : [$proto, $bare_arms[$bare++] || confess(qq{Don't know what to do with "$proto"})]
63 ;
64 my ($name, $type) = @$item;
2d5cf47a 65 _assert_valid_identifier $name;
66
67 unless (ref $type) {
68 # use '||' instead of 'or' to preserve $type in the error message
69 $type = $type_map{$type}
70 || confess qq["$type" doesn't look like a valid type (one of ${\join ', ', sort keys %type_map})];
71 }
72 $type->{name} ||= 'optional';
73 $type->{name} =~ /^(?:optional|required|prohibited)\z/
74 or confess qq["$type->{name}" doesn't look like a valid name attribute (one of optional, required, prohibited)];
b72eb6ee 75
76 $type->{shift} and _assert_valid_identifier $type->{shift}, 1;
77 $type->{attrs} and _assert_valid_attributes $type->{attrs};
125c067e 78
db81d362 79 $spec{$name} = $type;
125c067e 80 }
81
db81d362 82 for my $kw (keys %spec) {
83 my $type = $spec{$kw};
84
85 $^H{HINTK_SHIFT_ . $kw} = $type->{shift} || '';
b72eb6ee 86 $^H{HINTK_ATTRS_ . $kw} = $type->{attrs} || '';
db81d362 87 $^H{HINTK_NAME_ . $kw} =
88 $type->{name} eq 'prohibited' ? FLAG_NAME_PROHIBITED :
89 $type->{name} eq 'required' ? FLAG_NAME_REQUIRED :
90 FLAG_NAME_OPTIONAL
91 ;
92 $^H{+HINTK_KEYWORDS} .= "$kw ";
125c067e 93 }
eeb7df5f 94}
95
db81d362 96sub unimport {
eeb7df5f 97 my $class = shift;
125c067e 98
db81d362 99 if (!@_) {
100 delete $^H{+HINTK_KEYWORDS};
125c067e 101 return;
102 }
103
db81d362 104 for my $kw (@_) {
105 $^H{+HINTK_KEYWORDS} =~ s/(?<![^ ])\Q$kw\E //g;
125c067e 106 }
107}
108
db81d362 109
125c067e 110'ok'
7a63380c 111
112__END__
113
114=head1 NAME
115
116Function::Parameters - subroutine definitions with parameter lists
117
118=head1 SYNOPSIS
119
120 use Function::Parameters;
121
122 fun foo($bar, $baz) {
123 return $bar + $baz;
124 }
125
126 fun mymap($fun, @args) :(&@) {
127 my @res;
128 for (@args) {
129 push @res, $fun->($_);
130 }
131 @res
132 }
133
134 print "$_\n" for mymap { $_ * 2 } 1 .. 4;
125c067e 135
136 method set_name($name) {
137 $self->{name} = $name;
138 }
7a63380c 139
125c067e 140=cut
141
142=pod
143
63a24d7c 144 use Function::Parameters {
145 proc => 'function',
146 meth => 'method',
147 };
c9a39f6b 148
125c067e 149 my $f = proc ($x) { $x * 2 };
150 meth get_age() {
151 return $self->{age};
152 }
153
7a63380c 154=head1 DESCRIPTION
155
156This module lets you use parameter lists in your subroutines. Thanks to
63a24d7c 157L<PL_keyword_plugin|perlapi/PL_keyword_plugin> it works without source filters.
7a63380c 158
db81d362 159WARNING: This is my first attempt at writing L<XS code|perlxs> and I have
7a63380c 160almost no experience with perl's internals. So while this module might
161appear to work, it could also conceivably make your programs segfault.
162Consider this module alpha quality.
163
164=head2 Basic stuff
165
166To use this new functionality, you have to use C<fun> instead of C<sub> -
167C<sub> continues to work as before. The syntax is almost the same as for
168C<sub>, but after the subroutine name (or directly after C<fun> if you're
125c067e 169writing an anonymous sub) you can write a parameter list in parentheses. This
7a63380c 170list consists of comma-separated variables.
171
172The effect of C<fun foo($bar, $baz) {> is as if you'd written
173C<sub foo { my ($bar, $baz) = @_; >, i.e. the parameter list is simply
174copied into C<my> and initialized from L<@_|perlvar/"@_">.
175
125c067e 176In addition you can use C<method>, which understands the same syntax as C<fun>
177but automatically creates a C<$self> variable for you. So by writing
178C<method foo($bar, $baz) {> you get the same effect as
179C<sub foo { my $self = shift; my ($bar, $baz) = @_; >.
7a63380c 180
125c067e 181=head2 Customizing the generated keywords
c9a39f6b 182
63a24d7c 183You can customize the names of the keywords injected into your scope. To do
184that you pass a hash reference in the import list:
7a63380c 185
125c067e 186 use Function::Parameters { proc => 'function', meth => 'method' }; # -or-
187 use Function::Parameters { proc => 'function' }; # -or-
a23979e1 188 use Function::Parameters { meth => 'method' }; # etc.
125c067e 189
190The first line creates two keywords, C<proc> and C<meth> (for defining
191functions and methods, respectively). The last two lines only create one
192keyword. Generally the hash keys can be any identifiers you want while the
a23979e1 193values have to be either C<function>, C<method>, C<classmethod> or a hash
194reference (see below). The difference between C<function> and C<method> is that
195C<method>s automatically L<shift|perlfunc/shift> their first argument into
196C<$self> (C<classmethod>s are similar but shift into C<$class>).
125c067e 197
198The following shortcuts are available:
199
200 use Function::Parameters;
201 # is equivalent to #
202 use Function::Parameters { fun => 'function', method => 'method' };
203
204=cut
205
206=pod
207
63a24d7c 208The following shortcuts are deprecated and may be removed from a future version
209of the module:
210
211 # DEPRECATED
125c067e 212 use Function::Parameters 'foo';
213 # is equivalent to #
214 use Function::Parameters { 'foo' => 'function' };
215
216=cut
217
218=pod
219
63a24d7c 220 # DEPRECATED
125c067e 221 use Function::Parameters 'foo', 'bar';
222 # is equivalent to #
223 use Function::Parameters { 'foo' => 'function', 'bar' => 'method' };
224
63a24d7c 225That is, if you want to pass arguments to L<Function::Parameters>, use a
226hashref, not a list of strings.
227
ce052c57 228You can customize things even more by passing a hashref instead of C<function>
229or C<method>. This hash can have the following keys:
230
231=over
232
233=item C<name>
234
235Valid values: C<optional> (default), C<required> (all uses of this keyword must
236specify a function name), and C<prohibited> (all uses of this keyword must not
237specify a function name). This means a C<< name => 'prohibited' >> keyword can
238only be used for defining anonymous functions.
239
240=item C<shift>
241
242Valid values: strings that look like a scalar variable. Any function created by
243this keyword will automatically L<shift|perlfunc/shift> its first argument into
63a24d7c 244a local variable whose name is specified here.
ce052c57 245
273c6544 246=item C<attrs>
247
248Valid values: strings that are valid source code for attributes. Any value
249specified here will be inserted as a subroutine attribute in the generated
250code. Thus:
251
252 use Function::Parameters { sub_l => { attrs => ':lvalue' } };
253 sub_l foo() {
254 ...
255 }
256
257turns into
258
259 sub foo :lvalue {
260 ...
261 }
262
ce052c57 263=back
264
a23979e1 265Plain C<'function'> is equivalent to C<< { name => 'optional' } >>, plain
273c6544 266C<'method'> is equivalent to
a23979e1 267C<< { name => 'optional', shift => '$self', attrs => ':method' } >>, and plain
268C<'classmethod'> is equivalent to
269C<< { name => 'optional', shift => '$class', attrs => ':method' } >>.
ce052c57 270
63a24d7c 271=head2 Syntax and generated code
7a63380c 272
273Normally, Perl subroutines are not in scope in their own body, meaning the
63a24d7c 274parser doesn't know the name C<foo> or its prototype while processing the body
275of C<sub foo ($) { foo $bar[1], $bar[0]; }>, parsing it as
7a63380c 276C<$bar-E<gt>foo([1], $bar[0])>. Yes. You can add parens to change the
277interpretation of this code, but C<foo($bar[1], $bar[0])> will only trigger
278a I<foo() called too early to check prototype> warning. This module attempts
279to fix all of this by adding a subroutine declaration before the definition,
280so the parser knows the name (and possibly prototype) while it processes the
281body. Thus C<fun foo($x) :($) { $x }> really turns into
282C<sub foo ($); sub foo ($) { my ($x) = @_; $x }>.
283
125c067e 284If you need L<subroutine attributes|perlsub/"Subroutine Attributes">, you can
285put them after the parameter list with their usual syntax.
286
287Syntactically, these new parameter lists live in the spot normally occupied
288by L<prototypes|perlsub/"Prototypes">. However, you can include a prototype by
289specifying it as the first attribute (this is syntactically unambiguous
63a24d7c 290because normal attributes have to start with a letter while a prototype starts
291with C<(>).
292
293As an example, the following declaration uses every feature available
294(subroutine name, parameter list, prototype, attributes, and implicit
295C<$self>):
296
297 method foo($x, $y, @z) :($;$@) :lvalue :Banana(2 + 2) {
298 ...
299 }
300
301And here's what it turns into:
302
303 sub foo ($;$@); sub foo ($;$@) :lvalue :Banana(2 + 2) { my $self = shift; my ($x, $y, @z) = @_;
304 ...
305 }
306
307Another example:
308
309 my $coderef = fun ($p, $q) :(;$$)
310 :lvalue
311 :Gazebo((>:O)) {
312 ...
313 };
314
315And the generated code:
316
317 my $coderef = sub (;$$) :lvalue :Gazebo((>:O)) { my ($p, $q) = @_;
318 ...
319 };
320
321=head2 Wrapping Function::Parameters
125c067e 322
db81d362 323If you want to wrap L<Function::Parameters>, you just have to call its
324C<import> method. It always applies to the file that is currently being parsed
63a24d7c 325and its effects are lexical (i.e. it works like L<warnings> or L<strict>):
326
327 package Some::Wrapper;
328 use Function::Parameters ();
329 sub import {
330 Function::Parameters->import;
331 # or Function::Parameters->import(@other_import_args);
332 }
eeb7df5f 333
7a63380c 334=head1 AUTHOR
335
336Lukas Mai, C<< <l.mai at web.de> >>
337
338=head1 COPYRIGHT & LICENSE
339
db81d362 340Copyright 2010, 2011, 2012 Lukas Mai.
7a63380c 341
342This program is free software; you can redistribute it and/or modify it
343under the terms of either: the GNU General Public License as published
344by the Free Software Foundation; or the Artistic License.
345
346See http://dev.perl.org/licenses/ for more information.
347
348=cut