Upgrade to version-0.52
[p5sagit/p5-mst-13.2.git] / lib / assertions / compat.pm
CommitLineData
aefc56c5 1package assertions::compat;
2
3require assertions;
4our @ISA = qw(assertions);
5
6sub _on () { 1 }
7sub _off () { 0 }
8
9sub import {
10 my $class = shift;
11 my $name = @_ ? shift : 'asserting';
12 my $pkg = caller;
13 $name =~ /::/ or $name = "${pkg}::${name}";
14 @_ = $pkg unless @_;
15 $class->SUPER::import(@_);
16 my $enabled = assertions::enabled();
17 {
18 no strict 'vars';
19 no warnings;
20 undef &{$name};
21 *{$name} = $enabled ? \&_on : \&_off;
22 }
23}
24
25sub _compat_assertion_handler {
26 shift; shift;
27 grep $_ ne 'assertion', @_
28}
29
30sub _do_nothing_handler {}
31
32# test if 'assertion' attribute is natively supported
33my $assertion_ok=eval q{
34 sub _my_asserting_test : assertion { 1 }
35 _my_asserting_test()
36};
37
38*MODIFY_CODE_ATTRIBUTES =
39 defined($assertion_ok)
40 ? \&_do_nothing_handler
41 : \&_compat_assertion_handler;
42
431;
44
45__END__
46
47=head1 NAME
48
49assertions::compat - assertions for pre-5.9 versions of perl
50
51=head1 SYNOPSIS
52
53 # add support for 'assertion' attribute:
54 use base 'assertions::compat';
55 sub assert_foo : assertion { ... };
56
57 # then, maybe in another module:
58 package Foo::Bar;
59
60 # define sub 'asserting' with the assertion status:
61 use assertions::compat;
62 asserting and assert_foo(1,2,3,4);
63
64 # or
65 use assertions::compat ASST => 'Foo::Bar::doz';
66 ASST and assert_foo('dozpera');
67
68=head1 DESCRIPTION
69
70C<assertions::compat> allows to use assertions on perl versions prior
71to 5.9.0 (that is the first one to natively support them). Though,
72it's not magic, do not expect it to allow for conditional executed
73subroutines.
74
75This module provides support for two different functionalities:
76
77=head2 The C<assertion> attribute handler
78
79The subroutine attribute C<assertion> is not recognised on perls
80without assertion support. This module provides a
81C<MODIFY_CODE_ATTRIBUTES> handler for this attribute. It must be used
82via inheritance:
83
84 use base 'assertions::compat';
85
86 sub assert_foo : assertion { ... }
87
88Be aware that the handler just discards the attribute, so subroutines
89declared as assertions will be B<unconditionally> called on perl without
90native support for them.
91
92=head2 Assertion execution status as a constant
93
94C<assertions::compat> also allows to create constant subs which value
95is the assertion execution status. That allows checking explicitly and
96efficiently if assertions have to be executed on perls without native
97assertion support.
98
99For instance...
100
101 use assertions::compat ASST => 'Foo::Bar';
102
103exports constant subroutine C<ASST>. Its value is true when assertions
104tagged as C<Foo::Bar> has been activated via L<assertions::activate>;
105usually done with the -A switch from the command line on perls
106supporting it...
107
108 perl -A=Foo::Bar my_script.pl
109
110or alternatively with...
111
112 perl -Massertions::activate=Foo::Bar my_script.pl
113
114on pre-5.9.0 versions of perl.
115
116The constant sub defined can be used following this idiom:
117
118 use assertions::compat ASST => 'Foo::Bar';
119 ...
120 ASST and assert_foo();
121
122When ASST is false, the perl interpreter optimizes away the rest of
123the C<and> statement at compile time.
124
125
126When no assertion selection tags are passed to C<use
127assertions::compat>, the current module name is used as the selection
128tag, so...
129
130 use assertions::compat 'ASST';
131
132is equivalent to...
133
134 use assertions::compat ASST => __PACKAGE__;
135
136If the name of the constant subroutine is also omitted, C<asserting>
137is used.
138
139This module will not emit a warning when the constant is redefined.
140this is done on purpose to allow for code like that:
141
142 use assertions::compat ASST => 'Foo';
143 ASST and assert_foo();
144
145 use assertions::compat ASST => 'Bar';
146 ASST and assert_bar();
147
148Finally, be aware that while assertion execution status is lexical
149scoped, defined constants are not. You should be careful on that to
150not write inconsistent code. For instance...
151
152 package Foo;
153
154 use MyAssertions qw(assert_foo);
155
156 use assertions::compat ASST => 'Foo::Out'
157 {
158 use assertions::compat ASST => 'Foo::In';
159 ASST and assert_foo(); # ok!
160 }
161
162 ASST and assert_foo() # bad usage!
163 # ASST refers to tag Foo::In while assert_foo() is
164 # called only when Foo::Out has been activated.
165 # This is not what you want!!!
166
167
168=head1 SEE ALSO
169
170L<perlrun>, L<assertions>, L<assertions::activate>, L<attributes>.
171
172=head1 AUTHOR
173
174Salvador FandiE<ntilde>o, E<lt>sfandino@yahoo.comE<gt>
175
176=head1 COPYRIGHT AND LICENSE
177
178Copyright 2005 by Salvador FandiE<ntilde>o
179
180This library is free software; you can redistribute it and/or modify
181it under the same terms as Perl itself.
182
183=cut