]> git.vpit.fr Git - perl/modules/Lexical-Types.git/blob - lib/Lexical/Types.pm
531e0e82cf5c219e914564ca6c03d88b470ea9bf
[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 |= 0x020000;
181  $^H{+(__PACKAGE__)} = undef;
182 }
183
184 =head1 RUN-TIME INITIALIZER METHOD
185
186 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]>.
187 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.
188
189     use Lexical::Types as => 'My';
190
191     my Str $x;
192
193     ...
194
195     sub My::Str::TYPEDSCALAR {
196      # $_[1] is an alias to $x, and $_[2] is 'Str'
197      ...
198     }
199
200 =head1 INTEGRATION
201
202 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.
203
204     package MyTypes;
205
206     BEGIN { require Lexical::Types; }
207
208     sub import {
209      eval 'package Str; package Int'; # The types you want to support
210      Lexical::Types->import(
211       as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
212      );
213     }
214
215     sub unimport {
216      Lexical::Types->unimport;
217     }
218
219     sub new_str { ... }
220
221     sub new_int { ... }
222
223 If you prefer to use constants rather than creating empty packages, you can replace the previous example with something like this :
224
225     package MyTypes;
226
227     BEGIN { require Lexical::Types; }
228
229     sub import {
230      my $pkg = caller;
231      for (qw<Str Int>) {
232       my $type = __PACKAGE__ . '::' . $_;
233       no strict 'refs';
234       no warnings 'redefine';
235       *{$pkg.'::'.$_} = eval "sub () { '$type' }";
236      }
237      Lexical::Types->import(
238       as => sub { $_[0] => 'new' }
239      );
240     }
241
242     sub unimport {
243      Lexical::Types->unimport;
244     }
245
246     package MyTypes::Str;
247
248     sub new { ... }
249
250     package MyTypes::Int;
251
252     sub new { ... }
253
254 =head1 CONSTANTS
255
256 =head2 C<LT_THREADSAFE>
257
258 True iff the module could have been built with thread-safety features enabled.
259
260 =head2 C<LT_FORKSAFE>
261
262 True iff this module could have been built with fork-safety features enabled.
263 This will always be true except on Windows where it's false for perl 5.10.0 and below .
264
265 =head1 CAVEATS
266
267 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>.
268
269 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.
270
271 Only one mangler or prefix can be in use at the same time in a given scope.
272
273 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.
274
275 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.
276
277 With 5.8 perls, the pragma does not propagate into C<eval STRING>.
278 This is due to a shortcoming in the way perl handles the hints hash, which is addressed in perl 5.10.
279
280 =head1 DEPENDENCIES
281
282 L<perl> 5.8.4.
283
284 A C compiler.
285 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.
286
287 L<XSLoader> (standard since perl 5.6.0).
288
289 =head1 SEE ALSO
290
291 L<fields>.
292
293 L<Attribute::Handlers>.
294
295 =head1 AUTHOR
296
297 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
298
299 You can contact me by mail or on C<irc.perl.org> (vincent).
300
301 =head1 BUGS
302
303 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>.
304 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
305
306 =head1 SUPPORT
307
308 You can find documentation for this module with the perldoc command.
309
310     perldoc Lexical::Types
311
312 =head1 ACKNOWLEDGEMENTS
313
314 Inspired by Ricardo Signes.
315
316 Thanks Florian Ragwitz for suggesting the use of constants for types.
317
318 =head1 COPYRIGHT & LICENSE
319
320 Copyright 2009,2010,2011,2012,2013,2014,2015 Vincent Pit, all rights reserved.
321
322 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
323
324 =cut
325
326 1; # End of Lexical::Types