File Coverage

blib/lib/Lexical/Types.pm
Criterion Covered Total %
statement 30 30 100.0
branch 8 8 100.0
condition n/a
subroutine 9 9 100.0
pod n/a
total 47 47 100.0


line stmt bran cond sub pod time code
1             package Lexical::Types;
2              
3 17     17   175858 use 5.008_004;
  17         53  
  17         620  
4              
5 17     17   74 use strict;
  17         34  
  17         543  
6 17     17   78 use warnings;
  17         25  
  17         968  
7              
8             =head1 NAME
9              
10             Lexical::Types - Extend the semantics of typed lexicals.
11              
12             =head1 VERSION
13              
14             Version 0.14
15              
16             =cut
17              
18             our $VERSION;
19             BEGIN {
20 17     17   638 $VERSION = '0.14';
21             }
22              
23             =head1 SYNOPSIS
24              
25             { package Str; }
26              
27             {
28             package My::Types::Str;
29              
30             sub new { bless { }, shift }
31             }
32              
33             use Lexical::Types as => sub { 'My::Types::' . $_[0] => 'new' };
34              
35             my Str $x; # $x is now a My::Types::Str object
36              
37             {
38             package My::Types::Int;
39              
40             sub TYPEDSCALAR { bless { }, shift }
41             }
42              
43             use Lexical::Types;
44              
45             use constant Int => 'My::Types::Int';
46              
47             my Int $y; # $y is now a My::Types::Int object
48              
49             =head1 DESCRIPTION
50              
51             This pragma allows you to hook the execution of typed lexicals declarations (C) by calling a configurable method in a configurable package at each run.
52             In particular, it can be used to automatically tie or bless typed lexicals whenever they are initialized.
53              
54             Remind that for C to be able to parse C, you need :
55              
56             =over 4
57              
58             =item *
59              
60             either the C package to be defined ;
61              
62             =item *
63              
64             or for C to be a constant sub returning a valid defined package.
65              
66             =back
67              
68             so make sure you follow one of those two strategies to define your types.
69              
70             This pragma is B implemented with a source filter.
71              
72             =cut
73              
74             BEGIN {
75 17     17   76 require XSLoader;
76 17         12678 XSLoader::load(__PACKAGE__, $VERSION);
77             }
78              
79             =head1 METHODS
80              
81             =head2 C
82              
83             use Lexical::Types;
84             use Lexical::Types as => $prefix;
85             use Lexical::Types as => sub { ... }; # = $mangler
86              
87             Magically called when C is encountered.
88             All the occurences of C in the current lexical scope will be changed to call at each run a given method in a given package.
89             The method and package are determined by the parameter C<'as'> :
90              
91             =over 4
92              
93             =item *
94              
95             If it's left unspecified, the C method in the C package will be called.
96              
97             use Lexical::Types;
98             my Str $x; # calls Str->TYPEDSCALAR
99              
100             =item *
101              
102             If a plain scalar C<$prefix> is passed as the value, the C method in the C<${prefix}::Str> package will be used.
103              
104             use Lexical::Types as => 'My::'; # or "as => 'My'"
105             my Str $x; # calls My::Str->TYPEDSCALAR
106              
107             =item *
108              
109             If the value given is a code reference C<$mangler>, it will be called at compile-time with arguments C<'Str'> and C<'TYPEDSCALAR'> and is expected to return :
110              
111             =over 4
112              
113             =item *
114              
115             either an empty list, in which case the current typed lexical definition will be skipped (thus it won't be altered to trigger a run-time hook) ;
116              
117             use Lexical::Types as => sub {
118             return $_[0] =~ /Str/ ? @_ : ()
119             };
120             my Str $y; # calls Str->TYPEDSCALAR
121             my Int $x; # nothing special
122              
123             =item *
124              
125             or the desired package and method name, in that order (if any of those is C, the default value will be used instead).
126              
127             use Lexical::Types as => sub { 'My', 'new_' . lc($_[0]) };
128             my Str $x; # the coderef indicates to call My->new_str
129              
130             =back
131              
132             Note that if the type is a constant, C<$_[0]> will be set to the I of constant and not to its name.
133              
134             use Lexical::Types as => sub { $_[0] => 'new' };
135             use constant Str => 'MyStr';
136             my Str $x; # calls MyStr->new
137              
138             This means in particular that you can't both use constant types and redirect several types to different methods of the same package, because then you can't distinguish between the original types with C<$_[0]>.
139              
140             =back
141              
142             =cut
143              
144             sub import {
145 1040     1040   496537 shift;
146 1040         1915 my %args = @_;
147              
148 1040         959 my $hint;
149              
150 1040         1276 my $as = delete $args{'as'};
151 1040 100       1766 if ($as) {
152 23         41 my $r = ref $as;
153 23 100       55 if ($r eq 'CODE') {
    100          
154 17         48 $hint = _tag($as);
155             } elsif (!$r) {
156 5 100       27 $as .= '::' if $as !~ /::$/;
157 5     8   25 $hint = _tag(sub { $as . $_[0] });
  8         3987  
158             } else {
159 1         36 require Carp;
160 1         257 Carp::croak("Invalid $r reference for 'as'");
161             }
162             } else {
163 1017     1071   4634 $hint = _tag(sub { @_ });
  1071         62530  
164             }
165              
166 1039         1802 $^H |= 0x020000;
167             # Yes, we store a coderef inside the hints hash, but that's just for compile
168             # time.
169 1039         13026 $^H{+(__PACKAGE__)} = $hint;
170             }
171              
172             =head2 C
173              
174             no Lexical::Types;
175              
176             Magically called when C is encountered.
177             Turns the pragma off.
178              
179             =cut
180              
181             sub unimport {
182 2     2   126 $^H{+(__PACKAGE__)} = undef;
183             }
184              
185             =head1 RUN-TIME INITIALIZER METHOD
186              
187             The initializer method receives an alias to the pad slot of the initialized lexical in C<$_[1]> and the original type name in C<$_[2]>.
188             You can either edit C<$_[1]> in place, in which case you should return an empty list, or return a new scalar that will be copied into the pad slot.
189              
190             use Lexical::Types as => 'My';
191              
192             my Str $x;
193              
194             ...
195              
196             sub My::Str::TYPEDSCALAR {
197             # $_[1] is an alias to $x, and $_[2] is 'Str'
198             ...
199             }
200              
201             =head1 INTEGRATION
202              
203             You can integrate L in your module so that using it will provide types to your users without asking them to load either L or the type classes manually.
204              
205             package MyTypes;
206              
207             BEGIN { require Lexical::Types; }
208              
209             sub import {
210             eval 'package Str; package Int'; # The types you want to support
211             Lexical::Types->import(
212             as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
213             );
214             }
215              
216             sub unimport {
217             Lexical::Types->unimport;
218             }
219              
220             sub new_str { ... }
221              
222             sub new_int { ... }
223              
224             If you prefer to use constants rather than creating empty packages, you can replace the previous example with something like this :
225              
226             package MyTypes;
227              
228             BEGIN { require Lexical::Types; }
229              
230             sub import {
231             my $pkg = caller;
232             for (qw) {
233             my $type = __PACKAGE__ . '::' . $_;
234             no strict 'refs';
235             no warnings 'redefine';
236             *{$pkg.'::'.$_} = eval "sub () { '$type' }";
237             }
238             Lexical::Types->import(
239             as => sub { $_[0] => 'new' }
240             );
241             }
242              
243             sub unimport {
244             Lexical::Types->unimport;
245             }
246              
247             package MyTypes::Str;
248              
249             sub new { ... }
250              
251             package MyTypes::Int;
252              
253             sub new { ... }
254              
255             =head1 CONSTANTS
256              
257             =head2 C
258              
259             True iff the module could have been built with thread-safety features enabled.
260              
261             =head2 C
262              
263             True iff this module could have been built with fork-safety features enabled.
264             This will always be true except on Windows where it's false for perl 5.10.0 and below .
265              
266             =head1 CAVEATS
267              
268             Using this pragma will cause a slight global slowdown of any subsequent compilation phase that happens anywere in your code - even outside of the scope of use of C - which may become noticeable if you rely heavily on numerous calls to C.
269              
270             The restrictions on the type (being either a defined package name or a constant) apply even if you use the C<'as'> option to redirect to another package, and are unlikely to find a workaround as this happens deep inside the lexer - far from the reach of an extension.
271              
272             Only one mangler or prefix can be in use at the same time in a given scope.
273              
274             Typed lexicals declarations that appear in code C'd during the global destruction phase of a spawned thread or pseudo-fork (the processes used internally for the C emulation on Windows) are ignored.
275              
276             The implementation was tweaked to work around several limitations of vanilla C pragmas : it's thread safe, and doesn't suffer from a C bug that causes all pragmas to propagate into Cd scopes.
277              
278             With 5.8 perls, the pragma does not propagate into C.
279             This is due to a shortcoming in the way perl handles the hints hash, which is addressed in perl 5.10.
280              
281             =head1 DEPENDENCIES
282              
283             L 5.8.4.
284              
285             A C compiler.
286             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.
287              
288             L (standard since perl 5.6.0).
289              
290             =head1 SEE ALSO
291              
292             L.
293              
294             L.
295              
296             =head1 AUTHOR
297              
298             Vincent Pit, C<< >>, L.
299              
300             You can contact me by mail or on C (vincent).
301              
302             =head1 BUGS
303              
304             Please report any bugs or feature requests to C, or through the web interface at L.
305             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
306              
307             =head1 SUPPORT
308              
309             You can find documentation for this module with the perldoc command.
310              
311             perldoc Lexical::Types
312              
313             Tests code coverage report is available at L.
314              
315             =head1 ACKNOWLEDGEMENTS
316              
317             Inspired by Ricardo Signes.
318              
319             Thanks Florian Ragwitz for suggesting the use of constants for types.
320              
321             =head1 COPYRIGHT & LICENSE
322              
323             Copyright 2009,2010,2011,2012,2013,2014,2015 Vincent Pit, all rights reserved.
324              
325             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
326              
327             =cut
328              
329             1; # End of Lexical::Types