File Coverage

blib/lib/subs/auto.pm
Criterion Covered Total %
statement 112 115 97.3
branch 29 34 85.2
condition 14 20 70.0
subroutine 26 26 100.0
pod n/a
total 181 195 92.8


line stmt bran cond sub pod time code
1             package subs::auto;
2              
3 5     5   75660 use 5.010;
  5         19  
  5         234  
4              
5 5     5   31 use strict;
  5         12  
  5         192  
6 5     5   26 use warnings;
  5         16  
  5         357  
7              
8             =head1 NAME
9              
10             subs::auto - Read barewords as subroutine names.
11              
12             =head1 VERSION
13              
14             Version 0.08
15              
16             =cut
17              
18             our $VERSION;
19             BEGIN {
20 5     5   169 $VERSION = '0.08';
21             }
22              
23             =head1 SYNOPSIS
24              
25             {
26             use subs::auto;
27             foo; # Compile to "foo()" instead of "'foo'"
28             # or croaking on strict subs
29             foo $x; # Compile to "foo($x)" instead of "$x->foo"
30             foo 1; # Compile to "foo(1)" instead of croaking
31             foo 1, 2; # Compile to "foo(1, 2)" instead of croaking
32             foo(@a); # Still ok
33             foo->meth; # "'foo'->meth" if you have use'd foo somewhere,
34             # or "foo()->meth" otherwise
35             print foo 'wut'; # print to the filehandle foo if it's actually one,
36             # or "print(foo('wut'))" otherwise
37             } # ... but function calls will fail at run-time if you don't
38             # actually define foo somewhere
39              
40             foo; # BANG
41              
42             =head1 DESCRIPTION
43              
44             This pragma lexically enables the parsing of any bareword as a subroutine name, except those which corresponds to an entry in C<%INC> (expected to be class names) or whose symbol table entry has an IO slot (expected to be filehandles).
45              
46             You can pass options to C<import> as key / value pairs :
47              
48             =over 4
49              
50             =item *
51              
52             C<< in => $pkg >>
53              
54             Specifies on which package the pragma should act.
55             Setting C<$pkg> to C<Some::Package> allows you to resolve all functions name of the type C<Some::Package::func ...> in the current scope.
56             You can use the pragma several times with different package names to allow resolution of all the corresponding barewords.
57              
58             Defaults to the current package.
59              
60             =back
61              
62             This module is B<not> a source filter.
63              
64             =cut
65              
66 5     5   28 use B;
  5         9  
  5         271  
67              
68 5     5   5498 use B::Keywords;
  5         6575  
  5         325  
69              
70 5     5   5678 use Variable::Magic 0.31 qw<wizard cast dispell getdata>;
  5         7917  
  5         642  
71              
72             BEGIN {
73 5     5   12 unless (Variable::Magic::VMG_UVAR) {
74             require Carp;
75             Carp::croak('uvar magic not available');
76             }
77 5         33 require XSLoader;
78 5         2889 XSLoader::load(__PACKAGE__, $VERSION);
79             }
80              
81             my %core;
82             @core{
83             @B::Keywords::Barewords,
84             @B::Keywords::Functions,
85             'DATA',
86             } = ();
87             delete @core{qw<my local>};
88              
89             BEGIN {
90 5 50   5   382 *_REFCNT_PLACEHOLDERS = eval 'sub () { ' . ("$]" < 5.011_002 ? 0 : 1) . '}'
91             }
92              
93             my $tag = wizard data => sub { \(my $data = _REFCNT_PLACEHOLDERS ? 2 : 1) };
94              
95             sub _reset {
96 525     525   866 my $fqn = join '::', @_;
97              
98 525         508 my $cb = do {
99 5     5   30 no strict 'refs';
  5         10  
  5         168  
100 5     5   45 no warnings 'once';
  5         13  
  5         1508  
101 2     2   902 *$fqn{CODE};
  2         7  
  2         13  
  525         1446  
102             };
103              
104 525 100 100     2380 if ($cb and defined(my $data = getdata(&$cb, $tag))) {
105 35         41 $$data--;
106 35 100       83 return if $$data > 0;
107              
108 10         42 _delete_sub($fqn);
109             }
110             }
111              
112             sub _fetch {
113 582     582   2137 (undef, my $data, my $name) = @_;
114              
115 582 100       4122 return if $data->{guard};
116 305         537 local $data->{guard} = 1;
117              
118 305 100 100     9377 return if $name =~ /::/
119             or exists $core{$name};
120              
121 229   100     734 my $op_name = $_[-1] || '';
122 229 100       506 return if $op_name =~ /method/;
123              
124 220         284 my $pkg = $data->{pkg};
125              
126 220         1081 my $hints = (caller 0)[10];
127 220 100 100     990 if ($hints and $hints->{+(__PACKAGE__)}) {
128 122         210 my $pm = $name . '.pm';
129 122 100       268 return if exists $INC{$pm};
130              
131 121         175 my $fqn = $pkg . '::' . $name;
132 5     5   30 my $cb = do { no strict 'refs'; *$fqn{CODE} };
  5         11  
  5         405  
  121         116  
  121         373  
133 121 100       276 if ($cb) {
134 91 100       265 if (_REFCNT_PLACEHOLDERS and defined(my $data = getdata(&$cb, $tag))) {
135 13         22 ++$$data;
136             }
137 91         650 return;
138             }
139 5 100   5   29 return if do { no strict 'refs'; *$fqn{IO} };
  5         9  
  5         647  
  30         31  
  30         98  
140              
141             $cb = sub {
142 2     2   14141 my ($file, $line) = (caller 0)[1, 2];
143 2 50 33     24 ($file, $line) = ('(eval 0)', 0) unless $file && $line;
144 2         22 die "Undefined subroutine &$fqn called at $file line $line\n";
145 14         148 };
146 14         46 cast &$cb, $tag;
147              
148 5     5   31 no strict 'refs';
  5         18  
  5         2295  
149 14         68 *$fqn = $cb;
150             } else {
151 98         167 _reset($pkg, $name);
152             }
153              
154 112         3724 return;
155             }
156              
157             sub _store {
158 1833     1833   4724 (undef, my $data, my $name) = @_;
159              
160 1833 100       8783 return if $data->{guard};
161 427         758 local $data->{guard} = 1;
162              
163 427         833 _reset($data->{pkg}, $name);
164              
165 427         287549 return;
166             }
167              
168             my $wiz = wizard data => sub { +{ pkg => $_[1], guard => 0 } },
169             fetch => \&_fetch,
170             store => \&_store,
171             op_info => Variable::Magic::VMG_OP_INFO_NAME;
172              
173             my %pkgs;
174              
175             my $pkg_rx = qr/
176             ^(?:
177             ::
178             |
179             (?:::)?
180             [A-Za-z_][A-Za-z0-9_]*
181             (?:::[A-Za-z_][A-Za-z0-9_]*)*
182             (?:::)?
183             )$
184             /x;
185              
186             sub _validate_pkg {
187 12     12   27 my ($pkg, $cur) = @_;
188              
189 12 100       41 return $cur unless defined $pkg;
190              
191 7 50 66     67 if (ref $pkg or $pkg !~ $pkg_rx) {
192 7         35 require Carp;
193 7         985 Carp::croak('Invalid package name');
194             }
195              
196 0         0 $pkg =~ s/::$//;
197 0 0 0     0 $pkg = $cur . $pkg if $pkg eq '' or $pkg =~ /^::/;
198 0         0 $pkg;
199             }
200              
201             sub import {
202 13     13   3256 shift;
203 13 100       50 if (@_ % 2) {
204 1         5 require Carp;
205 1         187 Carp::croak('Optional arguments must be passed as keys/values pairs');
206             }
207 12         26 my %args = @_;
208              
209 12         27 my $cur = caller;
210 12         49 my $in = _validate_pkg $args{in}, $cur;
211 5         17 ++$pkgs{$in};
212             {
213 5     5   44 no strict 'refs';
  5         9  
  5         585  
  5         6  
214 5         9 cast %{$in . '::'}, $wiz, $in;
  5         69  
215             }
216              
217 5         24 $^H{+(__PACKAGE__)} = 1;
218 5         12 $^H |= 0x020000;
219              
220 5         119 return;
221             }
222              
223             sub unimport {
224 4     4   47415 $^H{+(__PACKAGE__)} = 0;
225             }
226              
227             {
228 5     5   26 no warnings 'void';
  5         9  
  5         280  
229             CHECK {
230 5     5   25 no strict 'refs';
  5         8  
  5         561  
231 3     3   20 dispell %{$_ . '::'}, $wiz for keys %pkgs;
  3         19  
232             }
233             }
234              
235             =head1 EXPORT
236              
237             None.
238              
239             =head1 CAVEATS
240              
241             C<*{'::foo'}{CODE}> will appear as defined in a scope where the pragma is enabled, C<foo> is used as a bareword, but is never actually defined afterwards.
242             This may or may not be considered as Doing The Right Thing.
243             However, C<*{'::foo'}{CODE}> will always return the right value if you fetch it outside the pragma's scope.
244             Actually, you can make it return the right value even in the pragma's scope by reading C<*{'::foo'}{CODE}> outside (or by actually defining C<foo>, which is ultimately why you use this pragma, right ?).
245              
246             You have to open global filehandles outside of the scope of this pragma if you want them not to be treated as function calls.
247             Or just use lexical filehandles and default ones as you should be.
248              
249             This pragma doesn't propagate into C<eval STRING>.
250              
251             =head1 DEPENDENCIES
252              
253             L<perl> 5.10.0.
254              
255             A C compiler.
256             This module may happen to build with a C++ compiler as well, but don't rely on it, as no guarantee is made in this regard.
257              
258             L<Variable::Magic> with C<uvar> magic enabled (this should be assured by the required perl version).
259              
260             L<B::Keywords>.
261              
262             L<Carp> (standard since perl 5), L<XSLoader> (since 5.6.0).
263              
264             =head1 AUTHOR
265              
266             Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
267              
268             You can contact me by mail or on C<irc.perl.org> (vincent).
269              
270             =head1 BUGS
271              
272             Please report any bugs or feature requests to C<bug-subs-auto at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=subs-auto>.
273             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
274              
275             =head1 SUPPORT
276              
277             You can find documentation for this module with the perldoc command.
278              
279             perldoc subs::auto
280              
281             Tests code coverage report is available at L<http://www.profvince.com/perl/cover/subs-auto>.
282              
283             =head1 ACKNOWLEDGEMENTS
284              
285             Thanks to Sebastien Aperghis-Tramoni for helping to name this pragma.
286              
287             =head1 COPYRIGHT & LICENSE
288              
289             Copyright 2008,2009,2010,2011,2013 Vincent Pit, all rights reserved.
290              
291             This program is free software; you can redistribute it and/or modify it
292             under the same terms as Perl itself.
293              
294             =cut
295              
296             1; # End of subs::auto