]> git.vpit.fr Git - perl/modules/Lexical-Types.git/blob - lib/Lexical/Types.pm
cf49dd5a90c3573c354cfe3af47d2fb608fd8c34
[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.15
15
16 =cut
17
18 our $VERSION;
19 BEGIN {
20  $VERSION = '0.15';
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  return;
170 }
171
172 =head2 C<unimport>
173
174     no Lexical::Types;
175
176 Magically called when C<no Lexical::Types> is encountered.
177 Turns the pragma off.
178
179 =cut
180
181 sub unimport {
182  $^H |= 0x020000;
183  $^H{+(__PACKAGE__)} = undef;
184
185  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<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.
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<Str Int>) {
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<LT_THREADSAFE>
261
262 True iff the module could have been built with thread-safety features enabled.
263
264 =head2 C<LT_FORKSAFE>
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<use Lexical::Types> - which may become noticeable if you rely heavily on numerous calls to C<eval STRING>.
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<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.
278
279 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.
280
281 With 5.8 perls, the pragma does not propagate into C<eval STRING>.
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<perl> 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<XSLoader> (standard since perl 5.6.0).
292
293 =head1 SEE ALSO
294
295 L<fields>.
296
297 L<Attribute::Handlers>.
298
299 =head1 AUTHOR
300
301 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
302
303 You can contact me by mail or on C<irc.perl.org> (vincent).
304
305 =head1 BUGS
306
307 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>.
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