just a simple XSLoader for now
[gitmo/Mouse.git] / lib / Mouse.pm
CommitLineData
9baf5d6b 1#!/usr/bin/env perl
c3398f5b 2package Mouse;
3use strict;
4use warnings;
eaad7dab 5use base 'Exporter';
c3398f5b 6
5f46c4bd 7our $VERSION = '0.12';
126765f0 8use 5.006;
c3398f5b 9
11ac534b 10if ($ENV{SHIKA_DEBUG}) {
11 *DEBUG = sub (){ 1 };
12} else {
13 *DEBUG = sub (){ 0 };
14}
15
16our $PurePerl;
17$PurePerl = $ENV{SHIKA_PUREPERL} unless defined $PurePerl;
18
19
20if (! $PurePerl) {
21 local $@;
22 local $^W = 0;
23 require XSLoader;
24 $PurePerl = !eval{ XSLoader::load(__PACKAGE__, $VERSION); 1 };
25 warn "Failed to load XS mode: $@" if $@ && Mouse::DEBUG();
26}
27
28
c3398f5b 29use Carp 'confess';
01db075b 30use Mouse::Util 'blessed';
c3398f5b 31
306290e8 32use Mouse::Meta::Attribute;
33use Mouse::Meta::Class;
c3398f5b 34use Mouse::Object;
d60c78b9 35use Mouse::TypeRegistry;
c3398f5b 36
eaad7dab 37our @EXPORT = qw(extends has before after around blessed confess with);
38
39sub extends { Mouse::Meta::Class->initialize(caller)->superclasses(@_) }
c3398f5b 40
eaad7dab 41sub has {
42 my $meta = Mouse::Meta::Class->initialize(caller);
c3398f5b 43
eaad7dab 44 my $names = shift;
45 $names = [$names] if !ref($names);
46
47 for my $name (@$names) {
48 if ($name =~ s/^\+//) {
49 Mouse::Meta::Attribute->clone_parent($meta, $name, @_);
50 }
51 else {
52 Mouse::Meta::Attribute->create($meta, $name, @_);
c3398f5b 53 }
54 }
eaad7dab 55}
56
57sub before {
58 my $meta = Mouse::Meta::Class->initialize(caller);
59
60 my $code = pop;
61
62 for (@_) {
63 $meta->add_before_method_modifier($_ => $code);
64 }
65}
66
67sub after {
68 my $meta = Mouse::Meta::Class->initialize(caller);
69
70 my $code = pop;
71
72 for (@_) {
73 $meta->add_after_method_modifier($_ => $code);
74 }
75}
76
77sub around {
78 my $meta = Mouse::Meta::Class->initialize(caller);
79
80 my $code = pop;
81
82 for (@_) {
83 $meta->add_around_method_modifier($_ => $code);
84 }
85}
86
87sub with {
88 my $meta = Mouse::Meta::Class->initialize(caller);
89
90 my $role = shift;
4aaa2ed6 91 my $args = shift || {};
eaad7dab 92
4aaa2ed6 93 confess "Mouse::Role only supports 'with' on individual roles at a time" if @_ || !ref $args;
eaad7dab 94
95 Mouse::load_class($role);
4aaa2ed6 96 $role->meta->apply($meta, %$args);
eaad7dab 97}
98
99sub import {
100 strict->import;
101 warnings->import;
102
103 my $caller = caller;
104
105 my $meta = Mouse::Meta::Class->initialize($caller);
106 $meta->superclasses('Mouse::Object')
107 unless $meta->superclasses;
108
109 no strict 'refs';
110 no warnings 'redefine';
111 *{$caller.'::meta'} = sub { $meta };
112
113 Mouse->export_to_level(1, @_);
114}
115
116sub unimport {
117 my $caller = caller;
118
119 no strict 'refs';
120 for my $keyword (@EXPORT) {
121 delete ${ $caller . '::' }{$keyword};
122 }
123}
c3398f5b 124
125sub load_class {
126 my $class = shift;
262801ef 127
9694b71b 128 if (ref($class) || !defined($class) || !length($class)) {
129 my $display = defined($class) ? $class : 'undef';
130 confess "Invalid class name ($display)";
131 }
c3398f5b 132
2a674d23 133 return 1 if is_class_loaded($class);
134
c3398f5b 135 (my $file = "$class.pm") =~ s{::}{/}g;
136
137 eval { CORE::require($file) };
2a674d23 138 confess "Could not load class ($class) because : $@" if $@;
c3398f5b 139
140 return 1;
141}
142
2a674d23 143sub is_class_loaded {
144 my $class = shift;
145
7ecc2123 146 return 0 if ref($class) || !defined($class) || !length($class);
147
bf134049 148 # walk the symbol table tree to avoid autovififying
149 # \*{${main::}{"Foo::"}} == \*main::Foo::
150
151 my $pack = \*::;
152 foreach my $part (split('::', $class)) {
153 return 0 unless exists ${$$pack}{"${part}::"};
154 $pack = \*{${$$pack}{"${part}::"}};
2a674d23 155 }
bf134049 156
157 # check for $VERSION or @ISA
158 return 1 if exists ${$$pack}{VERSION}
159 && defined *{${$$pack}{VERSION}}{SCALAR};
160 return 1 if exists ${$$pack}{ISA}
161 && defined *{${$$pack}{ISA}}{ARRAY};
162
163 # check for any method
164 foreach ( keys %{$$pack} ) {
165 next if substr($_, -2, 2) eq '::';
166 return 1 if defined *{${$$pack}{$_}}{CODE};
167 }
168
169 # fail
2a674d23 170 return 0;
171}
172
c3398f5b 1731;
174
175__END__
176
177=head1 NAME
178
0fff36e6 179Mouse - Moose minus the antlers
c3398f5b 180
c3398f5b 181=head1 SYNOPSIS
182
183 package Point;
6caea456 184 use Mouse; # automatically turns on strict and warnings
185
186 has 'x' => (is => 'rw', isa => 'Int');
187 has 'y' => (is => 'rw', isa => 'Int');
188
189 sub clear {
190 my $self = shift;
191 $self->x(0);
192 $self->y(0);
193 }
194
195 package Point3D;
c3398f5b 196 use Mouse;
197
6caea456 198 extends 'Point';
c3398f5b 199
6caea456 200 has 'z' => (is => 'rw', isa => 'Int');
201
8517d2ff 202 after 'clear' => sub {
203 my $self = shift;
204 $self->z(0);
205 };
c3398f5b 206
207=head1 DESCRIPTION
208
0fff36e6 209L<Moose> is wonderful.
c3398f5b 210
0fff36e6 211Unfortunately, it's a little slow. Though significant progress has been made
212over the years, the compile time penalty is a non-starter for some
213applications.
214
215Mouse aims to alleviate this by providing a subset of Moose's
216functionality, faster. In particular, L<Moose/has> is missing only a few
217expert-level features.
218
d1c1b994 219We're also going as light on dependencies as possible. Most functions we use
220from L<Scalar::Util> are copied into this dist. L<Scalar::Util> is required if
221you'd like weak references; there's simply no way to do it from pure Perl.
222L<Class::Method::Modifiers> is required if you want support for L</before>,
223L</after>, and L</around>.
224
0fff36e6 225=head2 MOOSE COMPAT
226
227Compatibility with Moose has been the utmost concern. Fewer than 1% of the
228tests fail when run against Moose instead of Mouse. Mouse code coverage is also
7e3ed32e 229over 96%. Even the error messages are taken from Moose. The Mouse code just
230runs the test suite 4x faster.
0fff36e6 231
232The idea is that, if you need the extra power, you should be able to run
8e1a28a8 233C<s/Mouse/Moose/g> on your codebase and have nothing break. To that end,
234nothingmuch has written L<Squirrel> (part of this distribution) which will act
235as Mouse unless Moose is loaded, in which case it will act as Moose.
0fff36e6 236
237Mouse also has the blessings of Moose's author, stevan.
238
239=head2 MISSING FEATURES
240
0fff36e6 241=head3 Roles
242
faa5cb70 243We're working on fixing this one! stevan has suggested an implementation
244strategy. Mouse currently ignores methods, so that needs to be fixed next.
245Roles that consist entirely of attributes may be usable in this very version.
0fff36e6 246
247=head3 Complex types
248
249User-defined type constraints and parameterized types may be implemented. Type
250coercions probably not (patches welcome).
251
252=head3 Bootstrapped meta world
253
254Very handy for extensions to the MOP. Not pressing, but would be nice to have.
255
256=head3 Modification of attribute metaclass
257
258When you declare an attribute with L</has>, you get the inlined accessors
259installed immediately. Modifying the attribute metaclass, even if possible,
260does nothing.
261
262=head3 Lots more..
263
264MouseX?
265
266=head1 KEYWORDS
c3398f5b 267
306290e8 268=head2 meta -> Mouse::Meta::Class
c3398f5b 269
270Returns this class' metaclass instance.
271
272=head2 extends superclasses
273
274Sets this class' superclasses.
275
b7a74822 276=head2 before (method|methods) => Code
277
278Installs a "before" method modifier. See L<Moose/before> or
279L<Class::Method::Modifiers/before>.
280
6beb7db6 281Use of this feature requires L<Class::Method::Modifiers>!
282
b7a74822 283=head2 after (method|methods) => Code
284
285Installs an "after" method modifier. See L<Moose/after> or
286L<Class::Method::Modifiers/after>.
287
6beb7db6 288Use of this feature requires L<Class::Method::Modifiers>!
289
b7a74822 290=head2 around (method|methods) => Code
291
292Installs an "around" method modifier. See L<Moose/around> or
293L<Class::Method::Modifiers/around>.
294
6beb7db6 295Use of this feature requires L<Class::Method::Modifiers>!
296
c3398f5b 297=head2 has (name|names) => parameters
298
299Adds an attribute (or if passed an arrayref of names, multiple attributes) to
0fff36e6 300this class. Options:
301
302=over 4
303
304=item is => ro|rw
305
306If specified, inlines a read-only/read-write accessor with the same name as
307the attribute.
308
309=item isa => TypeConstraint
310
311Provides basic type checking in the constructor and accessor. Basic types such
312as C<Int>, C<ArrayRef>, C<Defined> are supported. Any unknown type is taken to
313be a class check (e.g. isa => 'DateTime' would accept only L<DateTime>
314objects).
315
316=item required => 0|1
317
318Whether this attribute is required to have a value. If the attribute is lazy or
319has a builder, then providing a value for the attribute in the constructor is
320optional.
321
ca63d17a 322=item init_arg => Str | Undef
0fff36e6 323
ca63d17a 324Allows you to use a different key name in the constructor. If undef, the
325attribue can't be passed to the constructor.
0fff36e6 326
327=item default => Value | CodeRef
328
329Sets the default value of the attribute. If the default is a coderef, it will
330be invoked to get the default value. Due to quirks of Perl, any bare reference
331is forbidden, you must wrap the reference in a coderef. Otherwise, all
332instances will share the same reference.
333
334=item lazy => 0|1
335
336If specified, the default is calculated on demand instead of in the
337constructor.
338
339=item predicate => Str
340
341Lets you specify a method name for installing a predicate method, which checks
342that the attribute has a value. It will not invoke a lazy default or builder
343method.
344
345=item clearer => Str
346
347Lets you specify a method name for installing a clearer method, which clears
348the attribute's value from the instance. On the next read, lazy or builder will
349be invoked.
350
351=item handles => HashRef|ArrayRef
352
353Lets you specify methods to delegate to the attribute. ArrayRef forwards the
354given method names to method calls on the attribute. HashRef maps local method
355names to remote method names called on the attribute. Other forms of
356L</handles>, such as regular expression and coderef, are not yet supported.
357
358=item weak_ref => 0|1
359
360Lets you automatically weaken any reference stored in the attribute.
361
6beb7db6 362Use of this feature requires L<Scalar::Util>!
363
844fa049 364=item trigger => CodeRef
365
366Any time the attribute's value is set (either through the accessor or the constructor), the trigger is called on it. The trigger receives as arguments the instance, the new value, and the attribute instance.
367
6beb7db6 368Mouse 0.05 supported more complex triggers, but this behavior is now removed.
0fff36e6 369
370=item builder => Str
371
372Defines a method name to be called to provide the default value of the
373attribute. C<< builder => 'build_foo' >> is mostly equivalent to
374C<< default => sub { $_[0]->build_foo } >>.
375
376=item auto_deref => 0|1
377
378Allows you to automatically dereference ArrayRef and HashRef attributes in list
379context. In scalar context, the reference is returned (NOT the list length or
380bucket status). You must specify an appropriate type constraint to use
381auto_deref.
382
5253d13d 383=item lazy_build => 0|1
384
385Automatically define lazy => 1 as well as builder => "_build_$attr", clearer =>
386"clear_$attr', predicate => 'has_$attr' unless they are already defined.
387
0fff36e6 388=back
c3398f5b 389
390=head2 confess error -> BOOM
391
392L<Carp/confess> for your convenience.
393
394=head2 blessed value -> ClassName | undef
395
396L<Scalar::Util/blessed> for your convenience.
397
398=head1 MISC
399
400=head2 import
401
6caea456 402Importing Mouse will default your class' superclass list to L<Mouse::Object>.
c3398f5b 403You may use L</extends> to replace the superclass list.
404
405=head2 unimport
406
0fff36e6 407Please unimport Mouse (C<no Mouse>) so that if someone calls one of the
408keywords (such as L</extends>) it will break loudly instead breaking subtly.
c3398f5b 409
410=head1 FUNCTIONS
411
412=head2 load_class Class::Name
413
6caea456 414This will load a given C<Class::Name> (or die if it's not loadable).
c3398f5b 415This function can be used in place of tricks like
416C<eval "use $module"> or using C<require>.
417
262801ef 418=head2 is_class_loaded Class::Name -> Bool
419
420Returns whether this class is actually loaded or not. It uses a heuristic which
421involves checking for the existence of C<$VERSION>, C<@ISA>, and any
422locally-defined method.
423
c3398f5b 424=head1 AUTHOR
425
426Shawn M Moore, C<< <sartak at gmail.com> >>
427
fc9f8988 428Yuval Kogman, C<< <nothingmuch at woobling.org> >>
429
0fff36e6 430with plenty of code borrowed from L<Class::MOP> and L<Moose>
431
c3398f5b 432=head1 BUGS
433
434No known bugs.
435
436Please report any bugs through RT: email
437C<bug-mouse at rt.cpan.org>, or browse
438L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Mouse>.
439
440=head1 COPYRIGHT AND LICENSE
441
442Copyright 2008 Shawn M Moore.
443
444This program is free software; you can redistribute it and/or modify it
445under the same terms as Perl itself.
446
447=cut
448