]> git.vpit.fr Git - perl/modules/Lexical-Types.git/blob - lib/Lexical/Types.pm
725204bedc6bf68d048317b0e2542b99a248512d
[perl/modules/Lexical-Types.git] / lib / Lexical / Types.pm
1 package Lexical::Types;
2
3 use 5.008003;
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.11
15
16 =cut
17
18 our $VERSION;
19 BEGIN {
20  $VERSION = '0.11';
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 FUNCTIONS
80
81 =head2 C<< import [ as => [ $prefix | $mangler ] ] >>
82
83 Magically called when writing C<use Lexical::Types>.
84 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.
85 The method and package are determined by the parameter C<'as'> :
86
87 =over 4
88
89 =item *
90
91 If it's left unspecified, the C<TYPEDSCALAR> method in the C<Str> package will be called.
92
93     use Lexical::Types;
94     my Str $x; # calls Str->TYPEDSCALAR
95
96 =item *
97
98 If a plain scalar C<$prefix> is passed as the value, the C<TYPEDSCALAR> method in the C<${prefix}::Str> package will be used.
99
100     use Lexical::Types as => 'My::'; # or "as => 'My'"
101     my Str $x; # calls My::Str->TYPEDSCALAR
102
103 =item *
104
105 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 :
106
107 =over 4
108
109 =item *
110
111 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) ;
112
113     use Lexical::Types as => sub { return $_[0] =~ /Str/ ? @_ : () };
114     my Str $y; # calls Str->TYPEDSCALAR
115     my Int $x; # nothing special
116
117 =item *
118
119 or the desired package and method name, in that order (if any of those is C<undef>, the default value will be used instead).
120
121     use Lexical::Types as => sub { 'My', 'new_' . lc($_[0]) };
122     my Str $x; # the coderef indicates to call My->new_str
123
124 =back
125
126 Note that if the type is a constant, C<$_[0]> will be set to the I<value> of constant and not to its name.
127
128     use Lexical::Types as => sub { $_[0] => 'new' };
129     use constant Str => 'MyStr';
130     my Str $x; # calls MyStr->new
131
132 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]>.
133
134 =back
135
136 =cut
137
138 sub import {
139  shift;
140  my %args = @_;
141
142  my $hint;
143
144  my $as = delete $args{'as'};
145  if ($as) {
146   my $r = ref $as;
147   if ($r eq 'CODE') {
148    $hint = _tag($as);
149   } elsif (!$r) {
150    $as .= '::' if $as !~ /::$/;
151    $hint = _tag(sub { $as . $_[0] });
152   } else {
153    require Carp;
154    Carp::croak("Invalid $r reference for 'as'");
155   }
156  } else {
157   $hint = _tag(sub { @_ });
158  }
159
160  $^H |= 0x020000;
161  # Yes, we store a coderef inside the hints hash, but that's just for compile
162  # time.
163  $^H{+(__PACKAGE__)} = $hint;
164 }
165
166 =head2 C<unimport>
167
168 Magically called when writing C<no Lexical::Types>.
169 Turns the pragma off.
170
171 =cut
172
173 sub unimport {
174  $^H{+(__PACKAGE__)} = undef;
175 }
176
177 =head1 RUN-TIME INITIALIZER METHOD
178
179 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]>.
180 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.
181
182     use Lexical::Types as => 'My';
183
184     my Str $x;
185
186     ...
187
188     sub My::Str::TYPEDSCALAR {
189      # $_[1] is an alias to $x, and $_[2] is 'Str'
190      ...
191     }
192
193 =head1 INTEGRATION
194
195 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.
196
197     package MyTypes;
198
199     BEGIN { require Lexical::Types; }
200
201     sub import {
202      eval 'package Str; package Int'; # The types you want to support
203      Lexical::Types->import(
204       as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
205      );
206     }
207
208     sub unimport {
209      Lexical::Types->unimport;
210     }
211
212     sub new_str { ... }
213
214     sub new_int { ... }
215
216 If you prefer to use constants rather than creating empty packages, you can replace the previous example with something like this :
217
218     package MyTypes;
219
220     BEGIN { require Lexical::Types; }
221
222     sub import {
223      my $pkg = caller;
224      for (qw<Str Int>) {
225       my $type = __PACKAGE__ . '::' . $_;
226       no strict 'refs';
227       no warnings 'redefine';
228       *{$pkg.'::'.$_} = eval "sub () { '$type' }";
229      }
230      Lexical::Types->import(
231       as => sub { $_[0] => 'new' }
232      );
233     }
234
235     sub unimport {
236      Lexical::Types->unimport;
237     }
238
239     package MyTypes::Str;
240
241     sub new { ... }
242
243     package MyTypes::Int;
244
245     sub new { ... }
246
247 =head1 CONSTANTS
248
249 =head2 C<LT_THREADSAFE>
250
251 True iff the module could have been built with thread-safety features enabled.
252
253 =head2 C<LT_FORKSAFE>
254
255 True iff this module could have been built with fork-safety features enabled.
256 This will always be true except on Windows where it's false for perl 5.10.0 and below .
257
258 =head1 CAVEATS
259
260 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.
261
262 Only one mangler or prefix can be in use at the same time in a given scope.
263
264 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.
265
266 With 5.8 perls, the pragma does not propagate into C<eval STRING>.
267 This is due to a shortcoming in the way perl handles the hints hash, which is addressed in perl 5.10.
268
269 =head1 DEPENDENCIES
270
271 L<perl> 5.8.3.
272
273 A C compiler.
274 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.
275
276 L<XSLoader> (standard since perl 5.006).
277
278 =head1 SEE ALSO
279
280 L<fields>.
281
282 L<Attribute::Handlers>.
283
284 =head1 AUTHOR
285
286 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
287
288 You can contact me by mail or on C<irc.perl.org> (vincent).
289
290 =head1 BUGS
291
292 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>.
293 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
294
295 =head1 SUPPORT
296
297 You can find documentation for this module with the perldoc command.
298
299     perldoc Lexical::Types
300
301 Tests code coverage report is available at L<http://www.profvince.com/perl/cover/Lexical-Types>.
302
303 =head1 ACKNOWLEDGEMENTS
304
305 Inspired by Ricardo Signes.
306
307 Thanks Florian Ragwitz for suggesting the use of constants for types.
308
309 =head1 COPYRIGHT & LICENSE
310
311 Copyright 2009,2010,2011 Vincent Pit, all rights reserved.
312
313 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
314
315 =cut
316
317 1; # End of Lexical::Types