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