]> git.vpit.fr Git - perl/modules/Lexical-Types.git/blob - lib/Lexical/Types.pm
74c1150dd04a22067cb87aed49988e5394ffae1d
[perl/modules/Lexical-Types.git] / lib / Lexical / Types.pm
1 package Lexical::Types;
2
3 use 5.008_004;
4
5 use strict;
6 use warnings;
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  $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<my Str $x>) 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<perl> to be able to parse C<my Str $x>, you need :
55
56 =over 4
57
58 =item *
59
60 either the C<Str> package to be defined ;
61
62 =item *
63
64 or for C<Str> 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<not> implemented with a source filter.
71
72 =cut
73
74 BEGIN {
75  require XSLoader;
76  XSLoader::load(__PACKAGE__, $VERSION);
77 }
78
79 =head1 METHODS
80
81 =head2 C<import>
82
83     use Lexical::Types;
84     use Lexical::Types as => $prefix;
85     use Lexical::Types as => sub { ... }; # = $mangler
86
87 Magically called when C<use Lexical::Types> is encountered.
88 All the occurences of C<my Str $x> 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<TYPEDSCALAR> method in the C<Str> 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<TYPEDSCALAR> 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<undef>, 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<value> 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  shift;
146  my %args = @_;
147
148  my $hint;
149
150  my $as = delete $args{'as'};
151  if ($as) {
152   my $r = ref $as;
153   if ($r eq 'CODE') {
154    $hint = _tag($as);
155   } elsif (!$r) {
156    $as .= '::' if $as !~ /::$/;
157    $hint = _tag(sub { $as . $_[0] });
158   } else {
159    require Carp;
160    Carp::croak("Invalid $r reference for 'as'");
161   }
162  } else {
163   $hint = _tag(sub { @_ });
164  }
165
166  $^H |= 0x020000;
167  $^H{+(__PACKAGE__)} = $hint;
168 }
169
170 =head2 C<unimport>
171
172     no Lexical::Types;
173
174 Magically called when C<no Lexical::Types> is encountered.
175 Turns the pragma off.
176
177 =cut
178
179 sub unimport {
180  $^H{+(__PACKAGE__)} = undef;
181 }
182
183 =head1 RUN-TIME INITIALIZER METHOD
184
185 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]>.
186 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.
187
188     use Lexical::Types as => 'My';
189
190     my Str $x;
191
192     ...
193
194     sub My::Str::TYPEDSCALAR {
195      # $_[1] is an alias to $x, and $_[2] is 'Str'
196      ...
197     }
198
199 =head1 INTEGRATION
200
201 You can integrate L<Lexical::Types> in your module so that using it will provide types to your users without asking them to load either L<Lexical::Types> or the type classes manually.
202
203     package MyTypes;
204
205     BEGIN { require Lexical::Types; }
206
207     sub import {
208      eval 'package Str; package Int'; # The types you want to support
209      Lexical::Types->import(
210       as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
211      );
212     }
213
214     sub unimport {
215      Lexical::Types->unimport;
216     }
217
218     sub new_str { ... }
219
220     sub new_int { ... }
221
222 If you prefer to use constants rather than creating empty packages, you can replace the previous example with something like this :
223
224     package MyTypes;
225
226     BEGIN { require Lexical::Types; }
227
228     sub import {
229      my $pkg = caller;
230      for (qw<Str Int>) {
231       my $type = __PACKAGE__ . '::' . $_;
232       no strict 'refs';
233       no warnings 'redefine';
234       *{$pkg.'::'.$_} = eval "sub () { '$type' }";
235      }
236      Lexical::Types->import(
237       as => sub { $_[0] => 'new' }
238      );
239     }
240
241     sub unimport {
242      Lexical::Types->unimport;
243     }
244
245     package MyTypes::Str;
246
247     sub new { ... }
248
249     package MyTypes::Int;
250
251     sub new { ... }
252
253 =head1 CONSTANTS
254
255 =head2 C<LT_THREADSAFE>
256
257 True iff the module could have been built with thread-safety features enabled.
258
259 =head2 C<LT_FORKSAFE>
260
261 True iff this module could have been built with fork-safety features enabled.
262 This will always be true except on Windows where it's false for perl 5.10.0 and below .
263
264 =head1 CAVEATS
265
266 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<use Lexical::Types> - which may become noticeable if you rely heavily on numerous calls to C<eval STRING>.
267
268 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.
269
270 Only one mangler or prefix can be in use at the same time in a given scope.
271
272 Typed lexicals declarations that appear in code C<eval>'d during the global destruction phase of a spawned thread or pseudo-fork (the processes used internally for the C<fork> emulation on Windows) are ignored.
273
274 The implementation was tweaked to work around several limitations of vanilla C<perl> pragmas : it's thread safe, and doesn't suffer from a C<perl 5.8.x-5.10.0> bug that causes all pragmas to propagate into C<require>d scopes.
275
276 With 5.8 perls, the pragma does not propagate into C<eval STRING>.
277 This is due to a shortcoming in the way perl handles the hints hash, which is addressed in perl 5.10.
278
279 =head1 DEPENDENCIES
280
281 L<perl> 5.8.4.
282
283 A C compiler.
284 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.
285
286 L<XSLoader> (standard since perl 5.6.0).
287
288 =head1 SEE ALSO
289
290 L<fields>.
291
292 L<Attribute::Handlers>.
293
294 =head1 AUTHOR
295
296 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
297
298 You can contact me by mail or on C<irc.perl.org> (vincent).
299
300 =head1 BUGS
301
302 Please report any bugs or feature requests to C<bug-lexical-types at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Lexical-Types>.
303 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
304
305 =head1 SUPPORT
306
307 You can find documentation for this module with the perldoc command.
308
309     perldoc Lexical::Types
310
311 =head1 ACKNOWLEDGEMENTS
312
313 Inspired by Ricardo Signes.
314
315 Thanks Florian Ragwitz for suggesting the use of constants for types.
316
317 =head1 COPYRIGHT & LICENSE
318
319 Copyright 2009,2010,2011,2012,2013,2014,2015 Vincent Pit, all rights reserved.
320
321 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
322
323 =cut
324
325 1; # End of Lexical::Types