File Coverage

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


line stmt bran cond sub pod time code
1             package Lexical::Types;
2              
3 15     15   777182 use 5.008_004;
  15         188  
4              
5 15     15   110 use strict;
  15         41  
  15         457  
6 15     15   98 use warnings;
  15         37  
  15         1122  
7              
8             =head1 NAME
9              
10             Lexical::Types - Extend the semantics of typed lexicals.
11              
12             =head1 VERSION
13              
14             Version 0.16
15              
16             =cut
17              
18             our $VERSION;
19             BEGIN {
20 15     15   882 $VERSION = '0.16';
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 15     15   113 require XSLoader;
76 15         13199 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   789426 shift;
146 1040         2742 my %args = @_;
147              
148 1040         1707 my $hint;
149              
150 1040         2122 my $as = delete $args{'as'};
151 1040 100       2525 if ($as) {
152 23         68 my $r = ref $as;
153 23 100       85 if ($r eq 'CODE') {
    100          
154 17         71 $hint = _tag($as);
155             } elsif (!$r) {
156 5 100       32 $as .= '::' if $as !~ /::$/;
157 5     8   32 $hint = _tag(sub { $as . $_[0] });
  8         4880  
158             } else {
159 1         12 require Carp;
160 1         243 Carp::croak("Invalid $r reference for 'as'");
161             }
162             } else {
163 1017     1071   6143 $hint = _tag(sub { @_ });
  1071         74862  
164             }
165              
166 1039         3364 $^H |= 0x020000;
167 1039         5056 $^H{+(__PACKAGE__)} = $hint;
168              
169 1039         12951 return;
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   78 $^H |= 0x020000;
183 2         7 $^H{+(__PACKAGE__)} = undef;
184              
185 2         101 return;
186             }
187              
188             =head1 RUN-TIME INITIALIZER METHOD
189              
190             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]>.
191             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.
192              
193             use Lexical::Types as => 'My';
194              
195             my Str $x;
196              
197             ...
198              
199             sub My::Str::TYPEDSCALAR {
200             # $_[1] is an alias to $x, and $_[2] is 'Str'
201             ...
202             }
203              
204             =head1 INTEGRATION
205              
206             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.
207              
208             package MyTypes;
209              
210             BEGIN { require Lexical::Types; }
211              
212             sub import {
213             eval 'package Str; package Int'; # The types you want to support
214             Lexical::Types->import(
215             as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
216             );
217             }
218              
219             sub unimport {
220             Lexical::Types->unimport;
221             }
222              
223             sub new_str { ... }
224              
225             sub new_int { ... }
226              
227             If you prefer to use constants rather than creating empty packages, you can replace the previous example with something like this :
228              
229             package MyTypes;
230              
231             BEGIN { require Lexical::Types; }
232              
233             sub import {
234             my $pkg = caller;
235             for (qw) {
236             my $type = __PACKAGE__ . '::' . $_;
237             no strict 'refs';
238             no warnings 'redefine';
239             *{$pkg.'::'.$_} = eval "sub () { '$type' }";
240             }
241             Lexical::Types->import(
242             as => sub { $_[0] => 'new' }
243             );
244             }
245              
246             sub unimport {
247             Lexical::Types->unimport;
248             }
249              
250             package MyTypes::Str;
251              
252             sub new { ... }
253              
254             package MyTypes::Int;
255              
256             sub new { ... }
257              
258             =head1 CONSTANTS
259              
260             =head2 C
261              
262             True iff the module could have been built with thread-safety features enabled.
263              
264             =head2 C
265              
266             True iff this module could have been built with fork-safety features enabled.
267             This will always be true except on Windows where it's false for perl 5.10.0 and below .
268              
269             =head1 CAVEATS
270              
271             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.
272              
273             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.
274              
275             Only one mangler or prefix can be in use at the same time in a given scope.
276              
277             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.
278              
279             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.
280              
281             With 5.8 perls, the pragma does not propagate into C.
282             This is due to a shortcoming in the way perl handles the hints hash, which is addressed in perl 5.10.
283              
284             =head1 DEPENDENCIES
285              
286             L 5.8.4.
287              
288             A C compiler.
289             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.
290              
291             L (standard since perl 5.6.0).
292              
293             =head1 SEE ALSO
294              
295             L.
296              
297             L.
298              
299             =head1 AUTHOR
300              
301             Vincent Pit, C<< >>, L.
302              
303             You can contact me by mail or on C (vincent).
304              
305             =head1 BUGS
306              
307             Please report any bugs or feature requests to C, or through the web interface at L.
308             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
309              
310             =head1 SUPPORT
311              
312             You can find documentation for this module with the perldoc command.
313              
314             perldoc Lexical::Types
315              
316             =head1 ACKNOWLEDGEMENTS
317              
318             Inspired by Ricardo Signes.
319              
320             Thanks Florian Ragwitz for suggesting the use of constants for types.
321              
322             =head1 COPYRIGHT & LICENSE
323              
324             Copyright 2009,2010,2011,2012,2013,2014,2015,2017 Vincent Pit, all rights reserved.
325              
326             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
327              
328             =cut
329              
330             1; # End of Lexical::Types