line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
### Class::MakeMethods |
2
|
|
|
|
|
|
|
# Copyright 2002, 2003 Matthew Simon Cavalletto |
3
|
|
|
|
|
|
|
# See documentation, license, and other information after _END_. |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
package Class::MakeMethods; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
require 5.00307; # for the UNIVERSAL::isa method. |
8
|
116
|
|
|
116
|
|
16470
|
use strict; |
|
116
|
|
|
|
|
226
|
|
|
116
|
|
|
|
|
5366
|
|
9
|
116
|
|
|
116
|
|
6162
|
use Carp; |
|
116
|
|
|
|
|
213
|
|
|
116
|
|
|
|
|
9836
|
|
10
|
|
|
|
|
|
|
|
11
|
116
|
|
|
116
|
|
798
|
use vars qw( $VERSION ); |
|
116
|
|
|
|
|
237
|
|
|
116
|
|
|
|
|
9571
|
|
12
|
|
|
|
|
|
|
$VERSION = 1.010; |
13
|
|
|
|
|
|
|
|
14
|
116
|
|
|
116
|
|
646
|
use vars qw( %CONTEXT %DIAGNOSTICS ); |
|
116
|
|
|
|
|
508
|
|
|
116
|
|
|
|
|
22640
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
######################################################################## |
17
|
|
|
|
|
|
|
### MODULE IMPORT: import(), _import_version() |
18
|
|
|
|
|
|
|
######################################################################## |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub import { |
21
|
592
|
|
|
592
|
|
3053
|
my $class = shift; |
22
|
|
|
|
|
|
|
|
23
|
592
|
50
|
66
|
|
|
9355
|
if ( scalar @_ and $_[0] =~ m/^\d/ ) { |
24
|
0
|
|
|
|
|
0
|
$class->_import_version( shift ); |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
|
27
|
592
|
100
|
66
|
|
|
4056
|
if ( scalar @_ == 1 and $_[0] eq '-isasubclass' ) { |
28
|
469
|
|
|
|
|
18274
|
shift; |
29
|
469
|
|
|
|
|
2071
|
my $target_class = ( caller )[0]; |
30
|
116
|
|
|
116
|
|
942
|
no strict; |
|
116
|
|
|
|
|
230
|
|
|
116
|
|
|
|
|
15311
|
|
31
|
469
|
|
|
|
|
1059
|
push @{"$target_class\::ISA"}, $class; |
|
469
|
|
|
|
|
8538
|
|
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
592
|
100
|
|
|
|
31848
|
$class->make( @_ ) if ( scalar @_ ); |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub _import_version { |
38
|
0
|
|
|
0
|
|
0
|
my $class = shift; |
39
|
0
|
|
|
|
|
0
|
my $wanted = shift; |
40
|
|
|
|
|
|
|
|
41
|
116
|
|
|
116
|
|
759
|
no strict; |
|
116
|
|
|
|
|
265
|
|
|
116
|
|
|
|
|
211978
|
|
42
|
0
|
|
|
|
|
0
|
my $version = ${ $class.'::VERSION '}; |
|
0
|
|
|
|
|
0
|
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# If passed a version number, ensure that we measure up. |
45
|
|
|
|
|
|
|
# Based on similar functionality in Exporter.pm |
46
|
0
|
0
|
0
|
|
|
0
|
if ( ! $version or $version < $wanted ) { |
47
|
0
|
|
|
|
|
0
|
my $file = "$class.pm"; |
48
|
0
|
|
|
|
|
0
|
$file =~ s!::!/!g; |
49
|
0
|
0
|
|
|
|
0
|
$file = $INC{$file} ? " ($INC{$file})" : ''; |
50
|
0
|
|
0
|
|
|
0
|
_diagnostic('mm_version_fail', $class, $wanted, $version || '(undef)', $file); |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
######################################################################## |
55
|
|
|
|
|
|
|
### METHOD GENERATION: make() |
56
|
|
|
|
|
|
|
######################################################################## |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub make { |
59
|
187
|
|
|
187
|
1
|
730
|
local $CONTEXT{MakerClass} = shift; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# Find the first class in the caller() stack that's not a subclass of us |
62
|
187
|
|
|
|
|
438
|
local $CONTEXT{TargetClass}; |
63
|
187
|
|
|
|
|
334
|
my $i = 0; |
64
|
187
|
|
|
|
|
336
|
do { |
65
|
355
|
|
|
|
|
7471
|
$CONTEXT{TargetClass} = ( caller($i ++) )[0]; |
66
|
|
|
|
|
|
|
} while UNIVERSAL::isa($CONTEXT{TargetClass}, __PACKAGE__ ); |
67
|
|
|
|
|
|
|
|
68
|
187
|
|
|
|
|
347
|
my @methods; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# For compatibility with 5.004, which fails to splice use's constant @_ |
71
|
187
|
|
|
|
|
777
|
my @declarations = @_; |
72
|
|
|
|
|
|
|
|
73
|
187
|
50
|
|
|
|
885
|
if (@_ % 2) { _diagnostic('make_odd_args', $CONTEXT{MakerClass}); } |
|
0
|
|
|
|
|
0
|
|
74
|
187
|
|
|
|
|
690
|
while ( scalar @declarations ) { |
75
|
|
|
|
|
|
|
# The list passed to import should alternate between the names of the |
76
|
|
|
|
|
|
|
# meta-method to call to generate the methods, and arguments to it. |
77
|
436
|
|
|
|
|
1560
|
my ($name, $args) = splice(@declarations, 0, 2); |
78
|
436
|
50
|
|
|
|
1661
|
unless ( defined $name ) { |
79
|
0
|
|
|
|
|
0
|
croak "Undefined name"; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# Leading dash on the first argument of a pair means it's a |
83
|
|
|
|
|
|
|
# global/general option to be stored in CONTEXT. |
84
|
436
|
100
|
|
|
|
1921
|
if ( $name =~ s/^\-// ) { |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# To prevent difficult-to-predict retroactive behaviour, start by |
87
|
|
|
|
|
|
|
# flushing any pending methods before letting settings take effect |
88
|
46
|
50
|
|
|
|
162
|
if ( scalar @methods ) { |
89
|
0
|
|
|
|
|
0
|
_install_methods( $CONTEXT{MakerClass}, @methods ); |
90
|
0
|
|
|
|
|
0
|
@methods = (); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
46
|
100
|
|
|
|
177
|
if ( $name eq 'MakerClass' ) { |
94
|
|
|
|
|
|
|
# Switch base package for remainder of args |
95
|
15
|
|
|
|
|
44
|
$CONTEXT{MakerClass} = _find_subclass($CONTEXT{MakerClass}, $args); |
96
|
|
|
|
|
|
|
} else { |
97
|
31
|
|
|
|
|
70
|
$CONTEXT{$name} = $args; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
46
|
|
|
|
|
133
|
next; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# Argument normalization |
104
|
390
|
100
|
|
|
|
2478
|
my @args = ( |
|
|
100
|
|
|
|
|
|
105
|
|
|
|
|
|
|
! ref($args) ? split(' ', $args) : # If a string, it is split on spaces. |
106
|
|
|
|
|
|
|
ref($args) eq 'ARRAY' ? (@$args) : # If an arrayref, use its contents. |
107
|
|
|
|
|
|
|
( $args ) # If a hashref, it is used directly |
108
|
|
|
|
|
|
|
); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# If the type argument contains an array of method types, do the first |
111
|
|
|
|
|
|
|
# now, and put the others back in the queue to be processed subsequently. |
112
|
390
|
100
|
|
|
|
1338
|
if ( ref($name) eq 'ARRAY' ) { |
113
|
3
|
|
|
|
|
11
|
($name, my @name) = @$name; |
114
|
3
|
|
|
|
|
7
|
unshift @declarations, map { $_=>[@args] } @name; |
|
6
|
|
|
|
|
21
|
|
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# If the type argument contains space characters, use the first word |
118
|
|
|
|
|
|
|
# as the type, and prepend the remaining items to the argument list. |
119
|
390
|
100
|
|
|
|
1737
|
if ( $name =~ /\s/ ) { |
120
|
64
|
|
|
|
|
333
|
my @items = split ' ', $name; |
121
|
64
|
|
|
|
|
140
|
$name = shift( @items ); |
122
|
64
|
|
|
|
|
453
|
unshift @args, @items; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# If name contains a colon or double colon, treat the preceeding part |
126
|
|
|
|
|
|
|
# as the subclass name but only for this one set of methods. |
127
|
390
|
100
|
|
|
|
3372
|
local $CONTEXT{MakerClass} = _find_subclass($CONTEXT{MakerClass}, $1) |
128
|
|
|
|
|
|
|
if ($name =~ s/^(.*?)\:{1,2}(\w+)$/$2/); |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# Meta-method invocation via named_method or direct method call |
131
|
390
|
50
|
|
|
|
7927
|
my @results = ( |
|
|
100
|
|
|
|
|
|
132
|
|
|
|
|
|
|
$CONTEXT{MakerClass}->can('named_method') ? |
133
|
|
|
|
|
|
|
$CONTEXT{MakerClass}->named_method( $name, @args ) : |
134
|
|
|
|
|
|
|
$CONTEXT{MakerClass}->can($name) ? |
135
|
|
|
|
|
|
|
$CONTEXT{MakerClass}->$name( @args ) : |
136
|
|
|
|
|
|
|
croak "Can't generate $CONTEXT{MakerClass}->$name() methods" |
137
|
|
|
|
|
|
|
); |
138
|
|
|
|
|
|
|
# warn "$CONTEXT{MakerClass} $name - ", join(', ', @results) . "\n"; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
### A method-generator may be implemented in any of the following ways: |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# SELF-CONTAINED: It may return nothing, if there are no methods |
143
|
|
|
|
|
|
|
# to install, or if it has installed the methods itself. |
144
|
|
|
|
|
|
|
# (We also accept a single false value, for backward compatibility |
145
|
|
|
|
|
|
|
# with generators that are written as foreach loops, which return ''!) |
146
|
390
|
100
|
66
|
|
|
6993
|
if ( ! scalar @results or scalar @results == 1 and ! $results[0] ) { } |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
50
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# ALIAS: It may return a string containing a meta-method type to run |
149
|
|
|
|
|
|
|
# instead. Put the arguments back in the queue and go through again. |
150
|
514
|
|
|
|
|
4618
|
elsif ( scalar @results == 1 and ! ref $results[0]) { |
151
|
34
|
|
|
|
|
179
|
unshift @declarations, $results[0], \@args; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# REWRITER: It may return one or more array reference containing a meta- |
155
|
|
|
|
|
|
|
# method type and arguments which should be created to complete this |
156
|
|
|
|
|
|
|
# request. Put the arguments back in the queue and go through again. |
157
|
|
|
|
|
|
|
elsif ( ! grep { ref $_ ne 'ARRAY' } @results ) { |
158
|
46
|
|
|
|
|
102
|
unshift @declarations, ( map { shift(@$_), $_ } @results ); |
|
47
|
|
|
|
|
303
|
|
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# CODE REFS: It may provide a list of name, code pairs to install |
162
|
|
|
|
|
|
|
elsif ( ! scalar @results % 2 and ! ref $results[0] ) { |
163
|
96
|
|
|
|
|
440
|
push @methods, @results; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# GENERATOR OBJECT: It may return an object reference which will construct |
167
|
|
|
|
|
|
|
# the relevant methods. |
168
|
|
|
|
|
|
|
elsif ( UNIVERSAL::can( $results[0], 'make_methods' ) ) { |
169
|
211
|
|
|
|
|
1204
|
push @methods, ( shift @results )->make_methods(@results, @args); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
else { |
173
|
0
|
|
|
|
|
0
|
_diagnostic('make_bad_meta', $name, join(', ', map "'$_'", @results)); |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
187
|
|
|
|
|
1030
|
_install_methods( $CONTEXT{MakerClass}, @methods ); |
178
|
|
|
|
|
|
|
|
179
|
187
|
|
|
|
|
248842
|
return; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
######################################################################## |
183
|
|
|
|
|
|
|
### DECLARATION PARSING: _get_declarations() |
184
|
|
|
|
|
|
|
######################################################################## |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub _get_declarations { |
187
|
89
|
|
|
89
|
|
129
|
my $class = shift; |
188
|
|
|
|
|
|
|
|
189
|
89
|
|
|
|
|
110
|
my @results; |
190
|
|
|
|
|
|
|
my %defaults; |
191
|
|
|
|
|
|
|
|
192
|
89
|
|
|
|
|
281
|
while (scalar @_) { |
193
|
118
|
|
|
|
|
165
|
my $m_name = shift @_; |
194
|
118
|
50
|
33
|
|
|
858
|
if ( ! defined $m_name or ! length $m_name ) { |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
195
|
0
|
|
|
|
|
0
|
_diagnostic('make_empty') |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# Various forms of default parameters |
199
|
|
|
|
|
|
|
elsif ( substr($m_name, 0, 1) eq '-' ) { |
200
|
0
|
0
|
|
|
|
0
|
if ( substr($m_name, 1, 1) ne '-' ) { |
|
|
0
|
|
|
|
|
|
201
|
|
|
|
|
|
|
# Parse default values in the format "-param => value" |
202
|
0
|
|
|
|
|
0
|
$defaults{ substr($m_name, 1) } = shift @_; |
203
|
|
|
|
|
|
|
} elsif ( length($m_name) == 2 ) { |
204
|
|
|
|
|
|
|
# Parse hash of default values in the format "-- => { ... }" |
205
|
0
|
0
|
|
|
|
0
|
ref($_[0]) eq 'HASH' or _diagnostic('make_unsupported', $m_name.$_[0]); |
206
|
0
|
|
|
|
|
0
|
%defaults = ( %defaults, %{ shift @_ } ); |
|
0
|
|
|
|
|
0
|
|
207
|
|
|
|
|
|
|
} else { |
208
|
|
|
|
|
|
|
# Parse "special" arguments in the format "--foobar" |
209
|
0
|
|
|
|
|
0
|
$defaults{ '--' } .= $m_name; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
# Parse string and string-then-hash declarations |
214
|
|
|
|
|
|
|
elsif ( ! ref $m_name ) { |
215
|
96
|
100
|
100
|
|
|
822
|
if ( scalar @_ and ref $_[0] eq 'HASH' and ! exists $_[0]->{'name'} ) { |
|
|
|
66
|
|
|
|
|
216
|
24
|
|
|
|
|
39
|
push @results, { %defaults, 'name' => $m_name, %{ shift @_ } }; |
|
24
|
|
|
|
|
150
|
|
217
|
|
|
|
|
|
|
} else { |
218
|
72
|
|
|
|
|
387
|
push @results, { %defaults, 'name' => $m_name }; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# Parse hash-only declarations |
223
|
|
|
|
|
|
|
elsif ( ref $m_name eq 'HASH' ) { |
224
|
22
|
50
|
|
|
|
62
|
if ( length $m_name->{'name'} ) { |
225
|
22
|
|
|
|
|
151
|
push @results, { %defaults, %$m_name }; |
226
|
|
|
|
|
|
|
} else { |
227
|
0
|
|
|
|
|
0
|
_diagnostic('make_noname'); |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# Normalize: If we've got an array of names, replace it with those names |
232
|
|
|
|
|
|
|
elsif ( ref $m_name eq 'ARRAY' ) { |
233
|
0
|
|
|
|
|
0
|
my @items = @{ $m_name }; |
|
0
|
|
|
|
|
0
|
|
234
|
|
|
|
|
|
|
# If array is followed by an params hash, each one gets the same params |
235
|
0
|
0
|
0
|
|
|
0
|
if ( scalar @_ and ref $_[0] eq 'HASH' and ! exists $_[0]->{'name'} ) { |
|
|
|
0
|
|
|
|
|
236
|
0
|
|
|
|
|
0
|
my $params = shift; |
237
|
0
|
|
|
|
|
0
|
@items = map { $_, $params } @items |
|
0
|
|
|
|
|
0
|
|
238
|
|
|
|
|
|
|
} |
239
|
0
|
|
|
|
|
0
|
unshift @_, @items; |
240
|
0
|
|
|
|
|
0
|
next; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
else { |
244
|
0
|
|
|
|
|
0
|
_diagnostic('make_unsupported', $m_name); |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
89
|
|
|
|
|
330
|
return @results; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
######################################################################## |
253
|
|
|
|
|
|
|
### FUNCTION INSTALLATION: _install_methods() |
254
|
|
|
|
|
|
|
######################################################################## |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub _install_methods { |
257
|
187
|
|
|
187
|
|
9514
|
my ($class, %methods) = @_; |
258
|
|
|
|
|
|
|
|
259
|
116
|
|
|
116
|
|
1392
|
no strict 'refs'; |
|
116
|
|
|
|
|
489
|
|
|
116
|
|
|
|
|
63618
|
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# print STDERR "CLASS: $class\n"; |
262
|
187
|
|
|
|
|
536
|
my $package = $CONTEXT{TargetClass}; |
263
|
|
|
|
|
|
|
|
264
|
187
|
|
|
|
|
289
|
my ($name, $code); |
265
|
187
|
|
|
|
|
971
|
while (($name, $code) = each %methods) { |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# Skip this if the target package already has a function by the given name. |
268
|
1392
|
|
|
|
|
9210
|
next if ( ! $CONTEXT{ForceInstall} and |
269
|
1403
|
100
|
100
|
|
|
4157
|
defined *{$package. '::'. $name}{CODE} ); |
270
|
|
|
|
|
|
|
|
271
|
1398
|
50
|
|
|
|
16077
|
if ( ! ref $code ) { |
|
|
50
|
|
|
|
|
|
272
|
0
|
|
|
|
|
0
|
local $SIG{__DIE__}; |
273
|
0
|
|
|
|
|
0
|
local $^W; |
274
|
0
|
|
|
|
|
0
|
my $coderef = eval $code; |
275
|
0
|
0
|
|
|
|
0
|
if ( $@ ) { |
|
|
0
|
|
|
|
|
|
276
|
0
|
|
|
|
|
0
|
_diagnostic('inst_eval_syntax', $name, $@, $code); |
277
|
|
|
|
|
|
|
} elsif ( ref $coderef ne 'CODE' ) { |
278
|
0
|
|
|
|
|
0
|
_diagnostic('inst_eval_result', $name, $coderef, $code); |
279
|
|
|
|
|
|
|
} |
280
|
0
|
|
|
|
|
0
|
$code = $coderef; |
281
|
|
|
|
|
|
|
} elsif ( ref $code ne 'CODE' ) { |
282
|
0
|
|
|
|
|
0
|
_diagnostic('inst_result', $name, $code); |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# Add the code refence to the target package |
286
|
|
|
|
|
|
|
# _diagnostic('debug_install', $package, $name, $code); |
287
|
1398
|
100
|
|
|
|
4282
|
local $^W = 0 if ( $CONTEXT{ForceInstall} ); |
288
|
1398
|
|
|
|
|
1843
|
*{$package . '::' . $name} = $code; |
|
1398
|
|
|
|
|
6194
|
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
} |
291
|
187
|
|
|
|
|
789
|
return; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
######################################################################## |
295
|
|
|
|
|
|
|
### SUBCLASS LOADING: _find_subclass() |
296
|
|
|
|
|
|
|
######################################################################## |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# $pckg = _find_subclass( $class, $optional_package_name ); |
299
|
|
|
|
|
|
|
sub _find_subclass { |
300
|
5182
|
|
|
5182
|
|
14794
|
my $class = shift; |
301
|
5182
|
50
|
|
|
|
17394
|
my $package = shift or die "No package for _find_subclass"; |
302
|
|
|
|
|
|
|
|
303
|
5182
|
100
|
|
|
|
23586
|
$package = $package =~ s/^::// ? $package : |
304
|
|
|
|
|
|
|
"Class::MakeMethods::$package"; |
305
|
|
|
|
|
|
|
|
306
|
5182
|
|
|
|
|
23334
|
(my $file = $package . '.pm' ) =~ s|::|/|go; |
307
|
5182
|
100
|
|
|
|
33235
|
return $package if ( $::INC{ $file } ); |
308
|
|
|
|
|
|
|
|
309
|
116
|
|
|
116
|
|
981
|
no strict 'refs'; |
|
116
|
|
|
|
|
333
|
|
|
116
|
|
|
|
|
24447
|
|
310
|
148
|
100
|
|
|
|
274
|
return $package if ( @{$package . '::ISA'} ); |
|
148
|
|
|
|
|
2501
|
|
311
|
|
|
|
|
|
|
|
312
|
147
|
|
|
|
|
1475
|
local $SIG{__DIE__} = ''; |
313
|
147
|
|
|
|
|
327
|
eval { require $file }; |
|
147
|
|
|
|
|
149432
|
|
314
|
147
|
|
|
|
|
862
|
$::INC{ $package } = $::INC{ $file }; |
315
|
147
|
50
|
|
|
|
4731
|
if ( $@ ) { _diagnostic('mm_package_fail', $package, $@) } |
|
0
|
|
|
|
|
0
|
|
316
|
|
|
|
|
|
|
|
317
|
147
|
|
|
|
|
1926
|
return $package |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
######################################################################## |
321
|
|
|
|
|
|
|
### CONTEXT: _context(), %CONTEXT |
322
|
|
|
|
|
|
|
######################################################################## |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
sub _context { |
325
|
221
|
|
|
221
|
|
455
|
my $class = shift; |
326
|
221
|
50
|
|
|
|
875
|
return %CONTEXT if ( ! scalar @_ ); |
327
|
221
|
|
|
|
|
403
|
my $key = shift; |
328
|
221
|
50
|
|
|
|
1709
|
return $CONTEXT{$key} if ( ! scalar @_ ); |
329
|
0
|
|
|
|
|
0
|
$CONTEXT{$key} = shift; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
BEGIN { |
333
|
116
|
|
50
|
116
|
|
52836
|
$CONTEXT{Debug} ||= 0; |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
######################################################################## |
337
|
|
|
|
|
|
|
### DIAGNOSTICS: _diagnostic(), %DIAGNOSTICS |
338
|
|
|
|
|
|
|
######################################################################## |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
sub _diagnostic { |
341
|
2083
|
|
|
2083
|
|
4945
|
my $case = shift; |
342
|
2083
|
|
|
|
|
4067
|
my $message = $DIAGNOSTICS{$case}; |
343
|
2083
|
|
|
|
|
10335
|
$message =~ s/\A\s*\((\w)\)\s*//; |
344
|
2083
|
|
50
|
|
|
7787
|
my $severity = $1 || 'I'; |
345
|
2083
|
50
|
|
|
|
9512
|
if ( $severity eq 'Q' ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
346
|
2083
|
50
|
|
|
|
9417
|
carp( sprintf( $message, @_ ) ) if ( $CONTEXT{Debug} ); |
347
|
|
|
|
|
|
|
} elsif ( $severity eq 'W' ) { |
348
|
0
|
0
|
|
|
|
|
carp( sprintf( $message, @_ ) ) if ( $^W ); |
349
|
|
|
|
|
|
|
} elsif ( $severity eq 'F' ) { |
350
|
0
|
|
|
|
|
|
croak( sprintf( $message, @_ ) ) |
351
|
|
|
|
|
|
|
} else { |
352
|
0
|
|
|
|
|
|
confess( sprintf( $message, @_ ) ) |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
|
357
|
116
|
|
|
116
|
|
54372
|
BEGIN { %DIAGNOSTICS = ( |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
### BASE CLASS DIAGNOSTICS |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
# _diagnostic('debug_install', $package, $name, $code) |
362
|
|
|
|
|
|
|
debug_install => q|(W) Installing function %s::%s (%s)|, |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# _diagnostic('make_odd_args', $CONTEXT{MakerClass}) |
365
|
|
|
|
|
|
|
make_odd_args => q|(F) Odd number of arguments passed to %s method generator|, |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
# _diagnostic('make_bad_meta', $name, join(', ', map "'$_'", @results) |
368
|
|
|
|
|
|
|
make_bad_meta => q|(I) Unexpected return value from method constructor %s: %s|, |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# _diagnostic('inst_eval_syntax', $name, $@, $code) |
371
|
|
|
|
|
|
|
inst_eval_syntax => q|(I) Unable to compile generated method %s(): %s| . |
372
|
|
|
|
|
|
|
qq|\n (There's probably a syntax error in this generated code.)\n%s\n|, |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# _diagnostic('inst_eval_result', $name, $coderef, $code) |
375
|
|
|
|
|
|
|
inst_eval_result => q|(I) Unexpected return value from compilation of %s(): '%s'| . |
376
|
|
|
|
|
|
|
qq|\n (This generated code should have returned a code ref.)\n%s\n|, |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
# _diagnostic('inst_result', $name, $code) |
379
|
|
|
|
|
|
|
inst_result => q|(I) Unable to install code for %s() method: '%s'|, |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# _diagnostic('mm_package_fail', $package, $@) |
382
|
|
|
|
|
|
|
mm_package_fail => q|(F) Unable to dynamically load %s: %s|, |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# _diagnostic('mm_version_fail', $class, $wanted, $version || '(undef) |
385
|
|
|
|
|
|
|
mm_version_fail => q|(F) %s %s required--this is only version %s%s|, |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
### STANDARD SUBCLASS DIAGNOSTICS |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# _diagnostic('make_empty') |
390
|
|
|
|
|
|
|
make_empty => q|(F) Can't parse meta-method declaration: argument is empty or undefined|, |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
# _diagnostic('make_noname') |
393
|
|
|
|
|
|
|
make_noname => q|(F) Can't parse meta-method declaration: missing name attribute.| . |
394
|
|
|
|
|
|
|
qq|\n (Perhaps a trailing attributes hash has become separated from its name?)|, |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
# _diagnostic('make_unsupported', $m_name) |
397
|
|
|
|
|
|
|
make_unsupported => q|(F) Can't parse meta-method declaration: unsupported declaration type '%s'|, |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
### TEMPLATE SUBCLASS DIAGNOSTICS |
400
|
|
|
|
|
|
|
# ToDo: Should be moved to the Class::MakeMethods::Template package |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
debug_declaration => q|(Q) Meta-method declaration parsed: %s|, |
403
|
|
|
|
|
|
|
debug_make_behave => q|(Q) Building meta-method behavior %s: %s(%s)|, |
404
|
|
|
|
|
|
|
mmdef_not_interpretable => qq|(I) Not an interpretable meta-method: '%s'| . |
405
|
|
|
|
|
|
|
qq|\n (Perhaps a meta-method attempted to import from a non-templated meta-method?)|, |
406
|
|
|
|
|
|
|
make_bad_modifier => q|(F) Can't parse meta-method declaration: unknown option for %s: %s|, |
407
|
|
|
|
|
|
|
make_bad_behavior => q|(F) Can't make method %s(): template specifies unknown behavior '%s'|, |
408
|
|
|
|
|
|
|
behavior_mod_unknown => q|(F) Unknown modification to %s behavior: -%s|, |
409
|
|
|
|
|
|
|
debug_template_builder => qq|(Q) Template interpretation for %s:\n%s|. |
410
|
|
|
|
|
|
|
qq|\n---------\n%s\n---------\n|, |
411
|
|
|
|
|
|
|
debug_template => q|(Q) Parsed template '%s': %s|, |
412
|
|
|
|
|
|
|
debug_eval_builder => q|(Q) Compiling behavior builder '%s':| . qq|\n%s|, |
413
|
|
|
|
|
|
|
make_behavior_mod => q|(F) Can't apply modifiers (%s) to code behavior %s|, |
414
|
|
|
|
|
|
|
behavior_eval => q|(I) Class::MakeMethods behavior compilation error: %s| . |
415
|
|
|
|
|
|
|
qq|\n (There's probably a syntax error in the below code.)\n%s|, |
416
|
|
|
|
|
|
|
tmpl_unkown => q|(F) Can't interpret meta-method template: unknown template name '%s'|, |
417
|
|
|
|
|
|
|
tmpl_empty => q|(F) Can't interpret meta-method template: argument is empty or undefined|, |
418
|
|
|
|
|
|
|
tmpl_unsupported => q|(F) Can't interpret meta-method template: unsupported template type '%s'|, |
419
|
|
|
|
|
|
|
) } |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
1; |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
__END__ |