]> git.vpit.fr Git - perl/modules/Lexical-Types.git/blob - lib/Lexical/Types.pm
This is 0.07
[perl/modules/Lexical-Types.git] / lib / Lexical / Types.pm
1 package Lexical::Types;
2
3 use 5.008;
4
5 use strict;
6 use warnings;
7
8 use Carp qw/croak/;
9
10 =head1 NAME
11
12 Lexical::Types - Extend the semantics of typed lexicals.
13
14 =head1 VERSION
15
16 Version 0.07
17
18 =cut
19
20 our $VERSION;
21 BEGIN {
22  $VERSION = '0.07';
23 }
24
25 =head1 SYNOPSIS
26
27     { package Str; }
28
29     {
30      package My::Types::Str;
31
32      sub new { bless { }, shift }
33     }
34
35     use Lexical::Types as => sub { 'My::Types::' . $_[0] => 'new' };
36
37     my Str $x; # $x is now a My::Types::Str object
38
39     {
40      package My::Types::Int;
41
42      sub TYPEDSCALAR { bless { }, shift }
43     }
44
45     use Lexical::Types;
46
47     use constant Int => 'My::Types::Int';
48
49     my Int $y; # $y is now a My::Types::Int object
50
51 =head1 DESCRIPTION
52
53 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.
54 In particular, it can be used to automatically tie or bless typed lexicals whenever they are initialized.
55
56 Remind that for C<perl> to be able to parse C<my Str $x>, you need :
57
58 =over 4
59
60 =item *
61
62 either the C<Str> package to be defined ;
63
64 =item *
65
66 or for C<Str> to be a constant sub returning a valid defined package.
67
68 =back
69
70 so make sure you follow one of those two strategies to define your types.
71
72 This pragma is B<not> implemented with a source filter.
73
74 =cut
75
76 BEGIN {
77  require XSLoader;
78  XSLoader::load(__PACKAGE__, $VERSION);
79 }
80
81 =head1 FUNCTIONS
82
83 =head2 C<< import [ as => [ $prefix | $mangler ] ] >>
84
85 Magically called when writing C<use Lexical::Types>.
86 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.
87 The method and package are determined by the parameter C<'as'> :
88
89 =over 4
90
91 =item *
92
93 If it's left unspecified, the C<TYPEDSCALAR> method in the C<Str> package will be called.
94
95     use Lexical::Types;
96     my Str $x; # calls Str->TYPEDSCALAR
97
98 =item *
99
100 If a plain scalar C<$prefix> is passed as the value, the C<TYPEDSCALAR> method in the C<${prefix}::Str> package will be used.
101
102     use Lexical::Types as => 'My::'; # or "as => 'My'"
103     my Str $x; # calls My::Str->TYPEDSCALAR
104
105 =item *
106
107 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 :
108
109 =over 4
110
111 =item *
112
113 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) ;
114
115     use Lexical::Types as => sub { return $_[0] =~ /Str/ ? @_ : () };
116     my Str $y; # calls Str->TYPEDSCALAR
117     my Int $x; # nothing special
118
119 =item *
120
121 or the desired package and method name, in that order (if any of those is C<undef>, the default value will be used instead).
122
123     use Lexical::Types as => sub { 'My', 'new_' . lc($_[0]) };
124     my Str $x; # the coderef indicates to call My->new_str
125
126 =back
127
128 Note that if the type is a constant, C<$_[0]> will be set to the I<value> of constant and not to its name.
129
130     use Lexical::Types as => sub { $_[0] => 'new' };
131     use constant Str => 'MyStr';
132     my Str $x; # calls MyStr->new
133
134 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]>.
135
136 =back
137
138 =cut
139
140 sub import {
141  shift;
142  my %args = @_;
143
144  my $hint;
145
146  my $as = delete $args{'as'};
147  if ($as) {
148   my $r = ref $as;
149   if ($r eq 'CODE') {
150    $hint = _tag($as);
151   } elsif (!$r) {
152    $as .= '::' if $as !~ /::$/;
153    $hint = _tag(sub { $as . $_[0] });
154   } else {
155    croak "Invalid $r reference for 'as'";
156   }
157  } else {
158   $hint = _tag(sub { @_ });
159  }
160
161  $^H |= 0x020000;
162  # Yes, we store a coderef inside the hints hash, but that's just for compile
163  # time.
164  $^H{+(__PACKAGE__)} = $hint;
165 }
166
167 =head2 C<unimport>
168
169 Magically called when writing C<no Lexical::Types>.
170 Turns the pragma off.
171
172 =cut
173
174 sub unimport {
175  $^H{+(__PACKAGE__)} = undef;
176 }
177
178 =head1 RUN-TIME INITIALIZER METHOD
179
180 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]>.
181 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.
182
183     use Lexical::Types as => 'My';
184
185     my Str $x;
186
187     ...
188
189     sub My::Str::TYPEDSCALAR {
190      # $_[1] is an alias to $x, and $_[2] is 'Str'
191      ...
192     }
193
194 =head1 INTEGRATION
195
196 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.
197
198     package MyTypes;
199
200     BEGIN { require Lexical::Types; }
201
202     sub import {
203      eval 'package Str; package Int'; # The types you want to support
204      Lexical::Types->import(
205       as => sub { __PACKAGE__, 'new_' . lc($_[0]) }
206      );
207     }
208
209     sub unimport {
210      Lexical::Types->unimport;
211     }
212
213     sub new_str { ... }
214
215     sub new_int { ... }
216
217 If you prefer to use constants rather than creating empty packages, you can replace the previous example with something like this :
218
219     package MyTypes;
220
221     BEGIN { require Lexical::Types; }
222
223     sub import {
224      my $pkg = caller;
225      for (qw/Str Int/) {
226       my $type = __PACKAGE__ . '::' . $_;
227       no strict 'refs';
228       no warnings 'redefine';
229       *{$pkg.'::'.$_} = eval "sub () { '$type' }";
230      }
231      Lexical::Types->import(
232       as => sub { $_[0] => 'new' }
233      );
234     }
235
236     sub unimport {
237      Lexical::Types->unimport;
238     }
239
240     package MyTypes::Str;
241
242     sub new { ... }
243
244     package MyTypes::Int;
245
246     sub new { ... }
247
248 =head1 CONSTANTS
249
250 =head2 C<LT_THREADSAFE>
251
252 True iff the module could have been built with thread-safety features enabled.
253
254 =head1 CAVEATS
255
256 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.
257
258 Only one mangler or prefix can be in use at the same time in a given scope.
259
260 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.
261
262 With 5.8 perls, the pragma does not propagate into C<eval STRING>.
263 This is due to a shortcoming in the way perl handles the hints hash, which is addressed in perl 5.10.
264
265 =head1 DEPENDENCIES
266
267 L<perl> 5.8, L<XSLoader>.
268
269 =head1 SEE ALSO
270
271 L<fields>.
272
273 L<Attribute::Handlers>.
274
275 =head1 AUTHOR
276
277 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
278
279 You can contact me by mail or on C<irc.perl.org> (vincent).
280
281 =head1 BUGS
282
283 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>.  I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
284
285 =head1 SUPPORT
286
287 You can find documentation for this module with the perldoc command.
288
289     perldoc Lexical::Types
290
291 Tests code coverage report is available at L<http://www.profvince.com/perl/cover/Lexical-Types>.
292
293 =head1 ACKNOWLEDGEMENTS
294
295 Inspired by Ricardo Signes.
296
297 Thanks Florian Ragwitz for suggesting the use of constants for types.
298
299 =head1 COPYRIGHT & LICENSE
300
301 Copyright 2009 Vincent Pit, all rights reserved.
302
303 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
304
305 =cut
306
307 1; # End of Lexical::Types