| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Fukurama::Class::Implements; |
|
2
|
5
|
|
|
5
|
|
29653
|
use Fukurama::Class::Version(0.02); |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
41
|
|
|
3
|
5
|
|
|
5
|
|
31
|
use Fukurama::Class::Rigid; |
|
|
5
|
|
|
|
|
556
|
|
|
|
5
|
|
|
|
|
38
|
|
|
4
|
5
|
|
|
5
|
|
31
|
use Fukurama::Class::Carp; |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
42
|
|
|
5
|
5
|
|
|
5
|
|
654
|
use Fukurama::Class::Tree(); |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
2523
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $LEVEL_DISABLE = 0; |
|
8
|
|
|
|
|
|
|
our $LEVEL_CHECK_NONE = 1; |
|
9
|
|
|
|
|
|
|
our $LEVEL_CHECK_ALL = 2; |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $CHECK_LEVEL = $LEVEL_CHECK_ALL; |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
my $ERRORS = {}; |
|
14
|
|
|
|
|
|
|
my $ISA_ALREADY_DECORATED; |
|
15
|
|
|
|
|
|
|
my $REGISTER = {}; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Fukurama::Class::Implements - Pragma to provide interfaces |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 VERSION |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
Version 0.02 (beta) |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
package MyClass; |
|
28
|
|
|
|
|
|
|
use Fukurama::Class::Implements('MyParent'); |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
This pragma-like module enables te possibility to use interfaces (like in java). The implementation |
|
33
|
|
|
|
|
|
|
of all subroutines (except perls speacials) will be checked at compiletime. Your package won't inherit |
|
34
|
|
|
|
|
|
|
from this interface but every isa() will say that it is. Use Fukurama::Class instead, to get all the |
|
35
|
|
|
|
|
|
|
features for OO. |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 CONFIG |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
You can define the check-level which describes how the module will check implementations. |
|
40
|
|
|
|
|
|
|
The following levels are allowed: |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=over 4 |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=item DISABLE (0) |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
There is no check and no change in UNIVERSAL. If you use this level, it's like you remove this module. |
|
47
|
|
|
|
|
|
|
There are no side effects. You should only use this, if you never use the isa() method to check for interfaces. |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=item CHECK_NONE (1) |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
All Registration-Processes are executed and UNIVERSAL::isa would be decorated, but there would be no check. |
|
52
|
|
|
|
|
|
|
This level is recommended for production. |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=item CHECK_ALL (2) |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
All Classes would checked for implementation. This is the default behavior when you does'n change the |
|
57
|
|
|
|
|
|
|
check-level. |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=back |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head1 EXPORT |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=over 4 |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=item UNIVERSAL::isa |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
would be decorated |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=back |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head1 METHODS |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=over 4 |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item implements( child_class:STRING, interface_class:STRING ) return:VOID |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
Helper-method, which would executed by every pragma usage. |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=item run_check() return:VOID |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Helper method for static perl (see Fukurama::Class > BUGS) |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=item register_class_tree() return:VOID |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
Helper method to register needed handler in Fukurama::Class::Tree |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=back |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=head1 AUTHOR, BUGS, SUPPORT, ACKNOWLEDGEMENTS, COPYRIGHT & LICENSE |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
see perldoc of L |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=cut |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# void |
|
96
|
|
|
|
|
|
|
my $BUILD_HANDLER = sub { |
|
97
|
|
|
|
|
|
|
my $classname = $_[0]; |
|
98
|
|
|
|
|
|
|
my $classdef = $_[1]; |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
my $interface_def = $REGISTER->{$classname}; |
|
101
|
|
|
|
|
|
|
return if(!$interface_def); |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
my $inheritation_paths = []; |
|
104
|
|
|
|
|
|
|
foreach my $interface (keys(%$interface_def)) { |
|
105
|
|
|
|
|
|
|
my $interface_inheritation_paths = Fukurama::Class::Tree->get_inheritation_path($interface); |
|
106
|
|
|
|
|
|
|
foreach my $path (@$interface_inheritation_paths) { |
|
107
|
|
|
|
|
|
|
unshift(@$path, $interface); |
|
108
|
|
|
|
|
|
|
push(@$inheritation_paths, $path); |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
push(@$inheritation_paths, [$interface]) if(!scalar(@$interface_inheritation_paths)); |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
$classdef->{'implements'} = $inheritation_paths if(scalar(@$inheritation_paths)); |
|
113
|
|
|
|
|
|
|
return; |
|
114
|
|
|
|
|
|
|
}; |
|
115
|
|
|
|
|
|
|
# void |
|
116
|
|
|
|
|
|
|
my $CHECK_HANDLER = sub { |
|
117
|
|
|
|
|
|
|
my $classname = $_[0]; |
|
118
|
|
|
|
|
|
|
my $classdef = $_[1]; |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
return if($CHECK_LEVEL <= $LEVEL_CHECK_NONE); |
|
121
|
|
|
|
|
|
|
my $paths = $classdef->{'implements'}; |
|
122
|
|
|
|
|
|
|
return if(ref($paths) ne 'ARRAY'); |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
my $interface_list = {}; |
|
125
|
|
|
|
|
|
|
foreach my $path (@$paths) { |
|
126
|
|
|
|
|
|
|
my $level = 0; |
|
127
|
|
|
|
|
|
|
foreach my $class (@$path) { |
|
128
|
|
|
|
|
|
|
++$level; |
|
129
|
|
|
|
|
|
|
$interface_list->{$class} ||= ($level == 1 ? 1 : 0); |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
__PACKAGE__->_check_implementations($classname, $interface_list); |
|
133
|
|
|
|
|
|
|
return; |
|
134
|
|
|
|
|
|
|
}; |
|
135
|
|
|
|
|
|
|
# AUTOMAGIC void |
|
136
|
|
|
|
|
|
|
sub import { |
|
137
|
9
|
|
|
9
|
|
2181
|
my $class = $_[0]; |
|
138
|
9
|
|
|
|
|
18
|
my $interface = $_[1]; |
|
139
|
9
|
|
|
|
|
15
|
my $import_depth = $_[2]; |
|
140
|
|
|
|
|
|
|
|
|
141
|
9
|
|
50
|
|
|
45
|
$import_depth ||= 0; |
|
142
|
9
|
|
|
|
|
68
|
my $child = [caller($import_depth)]->[0]; |
|
143
|
9
|
|
|
|
|
44
|
$class->implements($child, $interface); |
|
144
|
8
|
|
|
|
|
496
|
return undef; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
# void |
|
147
|
|
|
|
|
|
|
sub implements { |
|
148
|
13
|
|
|
13
|
1
|
21
|
my $class = $_[0]; |
|
149
|
13
|
|
|
|
|
21
|
my $child = $_[1]; |
|
150
|
13
|
|
|
|
|
20
|
my $interface = $_[2]; |
|
151
|
|
|
|
|
|
|
|
|
152
|
13
|
50
|
|
|
|
39
|
return if($CHECK_LEVEL == $LEVEL_DISABLE); |
|
153
|
|
|
|
|
|
|
|
|
154
|
5
|
|
|
5
|
|
34
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
7
|
|
|
|
5
|
|
|
|
|
4844
|
|
|
155
|
|
|
|
|
|
|
|
|
156
|
13
|
|
|
|
|
43
|
$class->_decorate_isa(); |
|
157
|
13
|
50
|
66
|
1
|
|
16
|
if(!%{"$interface\::"} && !eval("use $interface();return 1")) { |
|
|
13
|
|
|
|
|
151
|
|
|
|
1
|
|
|
|
|
440
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
158
|
1
|
|
|
|
|
7
|
_croak($@); |
|
159
|
|
|
|
|
|
|
} |
|
160
|
12
|
|
100
|
|
|
60
|
$REGISTER->{$child} ||= {}; |
|
161
|
12
|
|
|
|
|
39
|
$REGISTER->{$child}->{$interface} = undef; |
|
162
|
12
|
|
|
|
|
43
|
$class->register_class_tree(); |
|
163
|
12
|
|
|
|
|
29
|
return; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
# void |
|
166
|
|
|
|
|
|
|
sub register_class_tree { |
|
167
|
15
|
|
|
15
|
1
|
27
|
my $class = $_[0]; |
|
168
|
|
|
|
|
|
|
|
|
169
|
15
|
|
|
|
|
78
|
Fukurama::Class::Tree->register_build_handler($BUILD_HANDLER); |
|
170
|
15
|
|
|
|
|
55
|
Fukurama::Class::Tree->register_check_handler($CHECK_HANDLER); |
|
171
|
15
|
|
|
|
|
26
|
return; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
# void |
|
174
|
|
|
|
|
|
|
sub run_check { |
|
175
|
15
|
|
|
15
|
1
|
7162
|
my $class = $_[0]; |
|
176
|
15
|
|
|
|
|
30
|
my $type = $_[1]; |
|
177
|
|
|
|
|
|
|
|
|
178
|
15
|
50
|
|
|
|
64
|
return if($CHECK_LEVEL <= $LEVEL_CHECK_NONE); |
|
179
|
15
|
100
|
|
|
|
51
|
$type = 'MANUAL' if(!defined($type)); |
|
180
|
|
|
|
|
|
|
|
|
181
|
15
|
50
|
|
|
|
59
|
if($CHECK_LEVEL == $LEVEL_CHECK_ALL) { |
|
182
|
15
|
|
|
|
|
89
|
Fukurama::Class::Tree->run_check($type); |
|
183
|
|
|
|
|
|
|
} |
|
184
|
11
|
|
|
|
|
127
|
return; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
# void |
|
187
|
|
|
|
|
|
|
sub _check_implementations { |
|
188
|
21
|
|
|
21
|
|
37
|
my $class = $_[0]; |
|
189
|
21
|
|
|
|
|
36
|
my $checked_class = $_[1]; |
|
190
|
21
|
|
|
|
|
35
|
my $checked_class_interfaces = $_[2]; |
|
191
|
|
|
|
|
|
|
|
|
192
|
21
|
|
|
|
|
37
|
my $error_list = []; |
|
193
|
21
|
|
|
|
|
40
|
my $interface_defs = []; |
|
194
|
21
|
|
|
|
|
361
|
my @interfaces = keys(%$checked_class_interfaces); |
|
195
|
21
|
|
|
|
|
46
|
foreach my $interface (@interfaces) { |
|
196
|
47
|
|
|
|
|
250
|
push(@$interface_defs, { |
|
197
|
|
|
|
|
|
|
class => $interface, |
|
198
|
|
|
|
|
|
|
subs => [Fukurama::Class::Tree->get_class_subs($interface)], |
|
199
|
|
|
|
|
|
|
}); |
|
200
|
|
|
|
|
|
|
} |
|
201
|
21
|
|
|
|
|
47
|
my $class_def = {}; |
|
202
|
21
|
|
|
|
|
83
|
foreach my $sub (Fukurama::Class::Tree->get_class_subs($checked_class)) { |
|
203
|
32
|
|
|
|
|
89
|
$class_def->{$sub} = undef; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
21
|
|
|
|
|
93
|
$class->_check_class_def($checked_class, $class_def, $interface_defs, $error_list); |
|
206
|
|
|
|
|
|
|
|
|
207
|
21
|
100
|
|
|
|
54
|
if(@$error_list) { |
|
208
|
5
|
|
|
|
|
10
|
my $errors = ''; |
|
209
|
5
|
|
|
|
|
12
|
foreach my $e (@$error_list) { |
|
210
|
11
|
|
|
|
|
29
|
my $key = $e->{'class'} . '-' . $e->{'method'}; |
|
211
|
11
|
100
|
|
|
|
33
|
next if($ERRORS->{$key}); |
|
212
|
4
|
|
|
|
|
17
|
$errors .= "\n > You doesn't implement method '$e->{method}' in class '$e->{class}' which is defined in interface(es): " . |
|
213
|
4
|
|
|
|
|
15
|
join(', ', @{$e->{interfaces}}); |
|
214
|
4
|
|
|
|
|
17
|
$ERRORS->{$key} = 1; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
5
|
100
|
|
|
|
34
|
_croak(scalar(@$error_list) . " Interface-Error(s):$errors\n", 1) if($errors); |
|
217
|
|
|
|
|
|
|
} |
|
218
|
19
|
|
|
|
|
93
|
return; |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
# void |
|
221
|
|
|
|
|
|
|
sub _check_class_def { |
|
222
|
21
|
|
|
21
|
|
40
|
my $class = $_[0]; |
|
223
|
21
|
|
|
|
|
41
|
my $obj_class = $_[1]; |
|
224
|
21
|
|
|
|
|
37
|
my $class_def = $_[2]; |
|
225
|
21
|
|
|
|
|
30
|
my $interface_defs = $_[3]; |
|
226
|
21
|
|
|
|
|
32
|
my $errorlist = $_[4]; |
|
227
|
|
|
|
|
|
|
|
|
228
|
21
|
|
|
|
|
69
|
my $interface_methods = $class->_merge_interface_methods($interface_defs); |
|
229
|
21
|
|
|
|
|
97
|
foreach my $method (keys %$interface_methods) { |
|
230
|
36
|
|
|
|
|
126
|
$class->_check_method_implementation($obj_class, $method, exists($class_def->{$method}), $interface_methods->{$method}, $errorlist); |
|
231
|
|
|
|
|
|
|
} |
|
232
|
21
|
|
|
|
|
71
|
return; |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
# void |
|
235
|
|
|
|
|
|
|
sub _check_method_implementation { |
|
236
|
36
|
|
|
36
|
|
69
|
my $class = $_[0]; |
|
237
|
36
|
|
|
|
|
49
|
my $obj_class = $_[1]; |
|
238
|
36
|
|
|
|
|
42
|
my $method = $_[2]; |
|
239
|
36
|
|
|
|
|
56
|
my $class_method_exist = $_[3]; |
|
240
|
36
|
|
|
|
|
48
|
my $interface_method_list = $_[4]; |
|
241
|
36
|
|
|
|
|
46
|
my $error_list = $_[5]; |
|
242
|
|
|
|
|
|
|
|
|
243
|
36
|
100
|
|
|
|
83
|
if(!$class_method_exist) { |
|
244
|
11
|
|
|
|
|
20
|
my $definitions = []; |
|
245
|
11
|
|
|
|
|
20
|
foreach my $interface (@$interface_method_list) { |
|
246
|
17
|
|
|
|
|
42
|
push(@$definitions, $interface); |
|
247
|
|
|
|
|
|
|
} |
|
248
|
11
|
|
|
|
|
140
|
push(@$error_list, { |
|
249
|
|
|
|
|
|
|
class => $obj_class, |
|
250
|
|
|
|
|
|
|
method => $method, |
|
251
|
|
|
|
|
|
|
interfaces => $definitions, |
|
252
|
|
|
|
|
|
|
}); |
|
253
|
|
|
|
|
|
|
} |
|
254
|
36
|
|
|
|
|
101
|
return; |
|
255
|
|
|
|
|
|
|
} |
|
256
|
|
|
|
|
|
|
# hash[] |
|
257
|
|
|
|
|
|
|
sub _merge_interface_methods { |
|
258
|
21
|
|
|
21
|
|
33
|
my $class = $_[0]; |
|
259
|
21
|
|
|
|
|
30
|
my $interface_defs = $_[1]; |
|
260
|
|
|
|
|
|
|
|
|
261
|
21
|
|
|
|
|
37
|
my $methodnames = {}; |
|
262
|
21
|
|
|
|
|
151
|
foreach my $def (@$interface_defs) { |
|
263
|
47
|
|
|
|
|
68
|
foreach my $method (@{$def->{'subs'}}) { |
|
|
47
|
|
|
|
|
104
|
|
|
264
|
59
|
|
100
|
|
|
314
|
$methodnames->{$method} ||= []; |
|
265
|
59
|
|
|
|
|
68
|
push(@{$methodnames->{$method}}, $def->{'class'}); |
|
|
59
|
|
|
|
|
203
|
|
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
} |
|
268
|
21
|
|
|
|
|
55
|
return $methodnames; |
|
269
|
|
|
|
|
|
|
} |
|
270
|
|
|
|
|
|
|
# string{} |
|
271
|
|
|
|
|
|
|
sub _has_interface { |
|
272
|
41539
|
|
|
41539
|
|
49125
|
my $class = $_[0]; |
|
273
|
41539
|
|
|
|
|
50002
|
my $obj_class = $_[1]; |
|
274
|
41539
|
|
|
|
|
44859
|
my $interface_class = $_[2]; |
|
275
|
|
|
|
|
|
|
|
|
276
|
41539
|
50
|
|
|
|
93709
|
return 0 if(!defined($obj_class)); |
|
277
|
41539
|
|
|
|
|
58079
|
my $interfaces = $REGISTER->{$obj_class}; |
|
278
|
41539
|
100
|
66
|
|
|
156659
|
return 0 if(!$interfaces || !exists($interfaces->{$interface_class})); |
|
279
|
9
|
|
|
|
|
59
|
return 1; |
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
# void |
|
282
|
|
|
|
|
|
|
sub _decorate_isa { |
|
283
|
13
|
|
|
13
|
|
21
|
my $class = $_[0]; |
|
284
|
|
|
|
|
|
|
|
|
285
|
5
|
|
|
5
|
|
37
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
163
|
|
|
286
|
5
|
|
|
5
|
|
27
|
no warnings 'redefine'; |
|
|
5
|
|
|
|
|
14
|
|
|
|
5
|
|
|
|
|
847
|
|
|
287
|
|
|
|
|
|
|
|
|
288
|
13
|
100
|
|
|
|
52
|
return if($ISA_ALREADY_DECORATED); |
|
289
|
|
|
|
|
|
|
|
|
290
|
3
|
|
|
|
|
7
|
my $identifier = 'UNIVERSAL::isa'; |
|
291
|
3
|
|
|
|
|
6
|
my $old = *{$identifier}{'CODE'}; |
|
|
3
|
|
|
|
|
11
|
|
|
292
|
3
|
50
|
|
|
|
17
|
die("Unable to decorate non existing sub $identifier") if(!$old); |
|
293
|
|
|
|
|
|
|
|
|
294
|
3
|
|
|
|
|
12
|
*{$identifier} = sub { |
|
295
|
41539
|
|
|
41539
|
|
374255
|
my $obj_class = $_[0]; |
|
296
|
41539
|
|
|
|
|
47100
|
my $type = $_[1]; |
|
297
|
|
|
|
|
|
|
|
|
298
|
41539
|
100
|
|
|
|
91190
|
return 1 if($class->_has_interface($obj_class, $type)); |
|
299
|
|
|
|
|
|
|
|
|
300
|
41530
|
|
|
|
|
333036
|
goto &$old; |
|
301
|
3
|
|
|
|
|
17
|
}; |
|
302
|
3
|
|
|
|
|
8
|
$ISA_ALREADY_DECORATED = 1; |
|
303
|
3
|
|
|
|
|
7
|
return; |
|
304
|
|
|
|
|
|
|
} |
|
305
|
|
|
|
|
|
|
|
|
306
|
5
|
|
|
5
|
|
28
|
no warnings 'void'; # avoid 'Too late to run CHECK/INIT block' |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
471
|
|
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# AUTOMAGIC void |
|
309
|
|
|
|
|
|
|
sub CHECK { |
|
310
|
5
|
|
|
5
|
|
29
|
__PACKAGE__->run_check('CHECK'); |
|
311
|
|
|
|
|
|
|
} |
|
312
|
|
|
|
|
|
|
# AUTOMAGIC void |
|
313
|
|
|
|
|
|
|
sub END { |
|
314
|
5
|
|
|
5
|
|
2121
|
__PACKAGE__->run_check('END'); |
|
315
|
|
|
|
|
|
|
} |
|
316
|
|
|
|
|
|
|
1; |