line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::Generate; |
2
|
|
|
|
|
|
|
|
3
|
22
|
|
|
22
|
|
57652
|
use 5.010; |
|
22
|
|
|
|
|
3066
|
|
|
22
|
|
|
|
|
940
|
|
4
|
20
|
|
|
20
|
|
715
|
use strict; |
|
20
|
|
|
|
|
818
|
|
|
20
|
|
|
|
|
793
|
|
5
|
17
|
|
|
17
|
|
91
|
use Carp; |
|
17
|
|
|
|
|
32
|
|
|
17
|
|
|
|
|
966
|
|
6
|
18
|
|
|
18
|
|
80
|
use warnings::register; |
|
18
|
|
|
|
|
28
|
|
|
18
|
|
|
|
|
1918
|
|
7
|
21
|
|
|
21
|
|
6183
|
use Symbol qw(&delete_package); |
|
21
|
|
|
|
|
9171
|
|
|
21
|
|
|
|
|
1898
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
BEGIN { |
10
|
21
|
|
|
21
|
|
100
|
use vars qw(@ISA @EXPORT_OK $VERSION); |
|
21
|
|
|
|
|
32
|
|
|
21
|
|
|
|
|
1521
|
|
11
|
17
|
|
|
17
|
|
80
|
use vars qw($save $accept_refs $strict $allow_redefine $class_var $instance_var $check_params $check_code $check_default $nfi $warnings); |
|
17
|
|
|
|
|
20
|
|
|
17
|
|
|
|
|
2087
|
|
12
|
|
|
|
|
|
|
|
13
|
17
|
|
|
17
|
|
75
|
require Exporter; |
14
|
17
|
|
|
|
|
108
|
@ISA = qw(Exporter); |
15
|
17
|
|
|
|
|
2685
|
@EXPORT_OK = (qw(&class &subclass &delete_class), qw($save $accept_refs $strict $allow_redefine $class_var $instance_var $check_params $check_code $check_default $nfi $warnings)); |
16
|
15
|
|
|
|
|
33
|
$VERSION = '1.15'; |
17
|
|
|
|
|
|
|
|
18
|
15
|
|
|
|
|
22
|
$accept_refs = 1; |
19
|
15
|
|
|
|
|
135
|
$strict = 1; |
20
|
15
|
|
|
|
|
91
|
$allow_redefine = 0; |
21
|
15
|
|
|
|
|
20
|
$class_var = 'class'; |
22
|
15
|
|
|
|
|
430
|
$instance_var = 'self'; |
23
|
15
|
|
|
|
|
27
|
$check_params = 1; |
24
|
15
|
|
|
|
|
17
|
$check_code = 1; |
25
|
15
|
|
|
|
|
1359
|
$check_default = 1; |
26
|
15
|
|
|
|
|
27
|
$nfi = 0; |
27
|
15
|
|
|
|
|
234
|
$warnings = 1; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
15
|
|
|
15
|
|
140
|
use vars qw(@_initial_values); # Holds all initial values passed as references. |
|
15
|
|
|
|
|
30
|
|
|
15
|
|
|
|
|
51451
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
my ($class_name, $class); |
33
|
|
|
|
|
|
|
my ($class_vars, $use_packages, $excluded_methods, $param_style_spec, $default_pss); |
34
|
|
|
|
|
|
|
my %class_options; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
my $cm; # These variables are for error messages. |
37
|
|
|
|
|
|
|
my $sa_needed = 'must be string or array reference'; |
38
|
|
|
|
|
|
|
my $sh_needed = 'must be string or hash reference'; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
my $allow_redefine_for_class; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my ($initialize, # These variables all hold |
43
|
|
|
|
|
|
|
$parse_any_flags, # references to package-local |
44
|
|
|
|
|
|
|
$set_class_type, # subs that other packages |
45
|
|
|
|
|
|
|
$parse_class_specification, # shouldn't call. |
46
|
|
|
|
|
|
|
$parse_method_specification, |
47
|
|
|
|
|
|
|
$parse_member_specification, |
48
|
|
|
|
|
|
|
$set_attributes, |
49
|
|
|
|
|
|
|
$class_defined, |
50
|
|
|
|
|
|
|
$process_class, |
51
|
|
|
|
|
|
|
$store_initial_value_reference, |
52
|
|
|
|
|
|
|
$check_for_invalid_parameter_names, |
53
|
|
|
|
|
|
|
$constructor_parameter_passing_style, |
54
|
|
|
|
|
|
|
$verify_class_type, |
55
|
|
|
|
|
|
|
$croak_if_duplicate_names, |
56
|
|
|
|
|
|
|
$invalid_spec_message); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
my %valid_option = map(substr($_, 0, 1) eq '$' ? (substr($_,1) => 1) : (), @EXPORT_OK); |
59
|
|
|
|
|
|
|
my %class_to_ref_map = ( |
60
|
|
|
|
|
|
|
'Class::Generate::Array_Class' => 'ARRAY', |
61
|
|
|
|
|
|
|
'Class::Generate::Hash_Class' => 'HASH' |
62
|
|
|
|
|
|
|
); |
63
|
|
|
|
|
|
|
my %warnings_keys = map(($_ => 1), qw(use no register)); |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub class(%) { # One of the three interface |
66
|
54
|
|
|
54
|
1
|
2618
|
my %params = @_; # routines to the package. |
67
|
54
|
100
|
|
|
|
310
|
if ( defined $params{-parent} ) { # Defines a class or a |
68
|
7
|
|
|
|
|
52
|
subclass(@_); # subclass. |
69
|
7
|
|
|
|
|
79
|
return; |
70
|
|
|
|
|
|
|
} |
71
|
48
|
|
|
|
|
184
|
&$initialize(); |
72
|
48
|
|
|
|
|
230
|
&$parse_any_flags(\%params); |
73
|
48
|
50
|
|
|
|
192
|
croak "Missing/extra arguments to class()" if scalar(keys %params) != 1; |
74
|
48
|
|
|
|
|
128
|
($class_name, undef) = %params; |
75
|
48
|
|
|
|
|
303
|
$cm = qq|Class "$class_name"|; |
76
|
47
|
|
|
|
|
182
|
&$verify_class_type($params{$class_name}); |
77
|
47
|
50
|
33
|
|
|
255
|
croak "$cm: A package of this name already exists" if ! $allow_redefine_for_class && &$class_defined($class_name); |
78
|
47
|
|
|
|
|
271
|
&$set_class_type($params{$class_name}); |
79
|
47
|
|
|
|
|
233
|
&$process_class($params{$class_name}); |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub subclass(%) { # One of the three interface |
83
|
15
|
|
|
16
|
1
|
239
|
my %params = @_; # routines to the package. |
84
|
15
|
|
|
|
|
49
|
&$initialize(); # Defines a subclass. |
85
|
15
|
|
|
|
|
20
|
my ($p_spec, $parent); |
86
|
15
|
50
|
|
|
|
71
|
if ( defined ($p_spec = $params{-parent}) ) { |
87
|
15
|
|
|
|
|
42
|
delete $params{-parent}; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
else { |
90
|
0
|
|
|
|
|
0
|
croak "Missing subclass parent"; |
91
|
|
|
|
|
|
|
} |
92
|
15
|
|
|
|
|
16
|
eval { $parent = Class::Generate::Array->new($p_spec) }; |
|
15
|
|
|
|
|
71
|
|
93
|
15
|
50
|
33
|
|
|
189
|
croak qq|Invalid parent specification ($sa_needed)| if $@ || scalar($parent->values) == 0; |
94
|
15
|
|
|
|
|
55
|
&$parse_any_flags(\%params); |
95
|
15
|
50
|
|
|
|
54
|
croak "Missing/extra arguments to subclass()" if scalar(keys %params) != 1; |
96
|
15
|
|
|
|
|
41
|
($class_name, undef) = %params; |
97
|
15
|
|
|
|
|
46
|
$cm = qq|Subclass "$class_name"|; |
98
|
15
|
|
|
|
|
61
|
&$verify_class_type($params{$class_name}); |
99
|
15
|
50
|
33
|
|
|
72
|
croak "$cm: A package of this name already exists" if ! $allow_redefine_for_class && &$class_defined($class_name); |
100
|
15
|
100
|
|
|
|
260
|
my $assumed_type = UNIVERSAL::isa($params{$class_name}, 'ARRAY') ? 'ARRAY' : 'HASH'; |
101
|
15
|
|
|
|
|
38
|
my $child_type = lc($assumed_type); |
102
|
15
|
|
|
|
|
45
|
for my $p ( $parent->values ) { |
103
|
15
|
|
|
|
|
49
|
my $c = Class::Generate::Class_Holder::get($p, $assumed_type); |
104
|
15
|
50
|
|
|
|
43
|
croak qq|$cm: Parent package "$p" does not exist| if ! defined $c; |
105
|
15
|
|
|
|
|
50
|
my $parent_type = lc($class_to_ref_map{ref $c}); |
106
|
15
|
50
|
|
|
|
74
|
croak "$cm: $child_type-based class must have $child_type-based parent ($p is $parent_type-based)" |
107
|
|
|
|
|
|
|
if ! UNIVERSAL::isa($params{$class_name}, $class_to_ref_map{ref $c}); |
108
|
15
|
50
|
33
|
|
|
2646
|
warnings::warn(qq{$cm: Parent class "$p" was not defined using class() or subclass(); $child_type reference assumed}) |
109
|
|
|
|
|
|
|
if warnings::enabled() && eval "! exists \$" . $p . '::{_cginfo}'; |
110
|
|
|
|
|
|
|
} |
111
|
15
|
|
|
|
|
67
|
&$set_class_type($params{$class_name}, $parent); |
112
|
15
|
|
|
|
|
45
|
for my $p ( $parent->values ) { |
113
|
15
|
|
|
|
|
43
|
$class->add_parents(Class::Generate::Class_Holder::get($p)); |
114
|
|
|
|
|
|
|
} |
115
|
15
|
|
|
|
|
54
|
&$process_class($params{$class_name}); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub delete_class(@) { # One of the three interface routines |
119
|
0
|
|
|
1
|
1
|
0
|
for my $class ( @_ ) { # to the package. Deletes a class |
120
|
0
|
0
|
|
|
|
0
|
next if ! eval '%' . $class . '::'; # declared using Class::Generate. |
121
|
0
|
0
|
|
|
|
0
|
if ( ! eval '%' . $class . '::_cginfo' ) { |
122
|
0
|
|
|
|
|
0
|
croak $class, ': Class was not declared using ', __PACKAGE__; |
123
|
|
|
|
|
|
|
} |
124
|
0
|
|
|
|
|
0
|
delete_package($class); |
125
|
0
|
|
|
|
|
0
|
Class::Generate::Class_Holder::remove($class); |
126
|
0
|
|
|
|
|
0
|
my $code_checking_package = __PACKAGE__ . '::Code_Checker::check::' . $class . '::'; |
127
|
0
|
0
|
|
|
|
0
|
if ( eval '%' . $code_checking_package ) { |
128
|
0
|
|
|
|
|
0
|
delete_package($code_checking_package); |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
$default_pss = Class::Generate::Array->new('key_value'); |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
$initialize = sub { # Reset certain variables, and set |
136
|
|
|
|
|
|
|
undef $class_vars; # options to their default values. |
137
|
|
|
|
|
|
|
undef $use_packages; |
138
|
|
|
|
|
|
|
undef $excluded_methods; |
139
|
|
|
|
|
|
|
$param_style_spec = $default_pss; |
140
|
|
|
|
|
|
|
%class_options = ( virtual => 0, |
141
|
|
|
|
|
|
|
strict => $strict, |
142
|
|
|
|
|
|
|
save => $save, |
143
|
|
|
|
|
|
|
accept_refs => $accept_refs, |
144
|
|
|
|
|
|
|
class_var => $class_var, |
145
|
|
|
|
|
|
|
instance_var => $instance_var, |
146
|
|
|
|
|
|
|
check_params => $check_params, |
147
|
|
|
|
|
|
|
check_code => $check_code, |
148
|
|
|
|
|
|
|
check_default=> $check_default, |
149
|
|
|
|
|
|
|
nfi => $nfi, |
150
|
|
|
|
|
|
|
warnings => $warnings ); |
151
|
|
|
|
|
|
|
$allow_redefine_for_class = $allow_redefine; |
152
|
|
|
|
|
|
|
}; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
$verify_class_type = sub { # Ensure that the class specification |
155
|
|
|
|
|
|
|
my $spec = $_[0]; # is a hash or array reference. |
156
|
|
|
|
|
|
|
return if UNIVERSAL::isa($spec, 'HASH') || UNIVERSAL::isa($spec, 'ARRAY'); |
157
|
|
|
|
|
|
|
croak qq|$cm: Elements must be in array or hash reference|; |
158
|
|
|
|
|
|
|
}; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
$set_class_type = sub { # Set $class to the type (array or |
161
|
|
|
|
|
|
|
my ($class_spec, $parent) = @_; # hash) appropriate to its declaration. |
162
|
|
|
|
|
|
|
my @params = ($class_name, %class_options); |
163
|
|
|
|
|
|
|
if ( UNIVERSAL::isa($class_spec, 'ARRAY') ) { |
164
|
|
|
|
|
|
|
if ( defined $parent ) { |
165
|
|
|
|
|
|
|
my ($parent_name, @other_array_values) = $parent->values; |
166
|
|
|
|
|
|
|
croak qq|$cm: An array reference based subclass must have exactly one parent| |
167
|
|
|
|
|
|
|
if @other_array_values; |
168
|
|
|
|
|
|
|
$parent = Class::Generate::Class_Holder::get($parent_name, 'ARRAY'); |
169
|
|
|
|
|
|
|
push @params, ( base_index => $parent->last + 1 ); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
$class = Class::Generate::Array_Class->new(@params); |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
else { |
174
|
|
|
|
|
|
|
$class = Class::Generate::Hash_Class->new(@params); |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
}; |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
my $class_name_regexp = '[A-Za-z_]\w*(::[A-Za-z_]\w*)*'; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
$parse_class_specification = sub { # Parse the class' specification, |
181
|
|
|
|
|
|
|
my %specs = @_; # checking for errors and amalgamating |
182
|
|
|
|
|
|
|
my %required; # class data. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
if ( defined $specs{new} ) { |
185
|
|
|
|
|
|
|
croak qq|$cm: Specification for "new" must be hash reference| |
186
|
|
|
|
|
|
|
unless UNIVERSAL::isa($specs{new}, 'HASH'); |
187
|
|
|
|
|
|
|
my %new_spec = %{$specs{new}}; # Modify %new_spec, not parameter passed |
188
|
|
|
|
|
|
|
my $required_items; # to class() or subclass(). |
189
|
|
|
|
|
|
|
if ( defined $new_spec{required} ) { |
190
|
|
|
|
|
|
|
eval { $required_items = Class::Generate::Array->new($new_spec{required}) }; |
191
|
|
|
|
|
|
|
croak qq|$cm: Invalid specification for required constructor parameters ($sa_needed)| if $@; |
192
|
|
|
|
|
|
|
delete $new_spec{required}; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
if ( defined $new_spec{style} ) { |
195
|
|
|
|
|
|
|
eval { $param_style_spec = Class::Generate::Array->new($new_spec{style}) }; |
196
|
|
|
|
|
|
|
croak qq|$cm: Invalid parameter-passing style ($sa_needed)| if $@; |
197
|
|
|
|
|
|
|
delete $new_spec{style}; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
$class->constructor(Class::Generate::Constructor->new(%new_spec)); |
200
|
|
|
|
|
|
|
if ( defined $required_items ) { |
201
|
|
|
|
|
|
|
for ( $required_items->values ) { |
202
|
|
|
|
|
|
|
if ( /^\w+$/ ) { |
203
|
|
|
|
|
|
|
croak qq|$cm: Required params list for constructor contains unknown member "$_"| |
204
|
|
|
|
|
|
|
if ! defined $specs{$_}; |
205
|
|
|
|
|
|
|
$required{$_} = 1; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
else { |
208
|
|
|
|
|
|
|
$class->constructor->add_constraints($_); |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
else { |
214
|
|
|
|
|
|
|
$class->constructor(Class::Generate::Constructor->new); |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
my $actual_name; |
218
|
|
|
|
|
|
|
for my $member_name ( grep $_ ne 'new', keys %specs ) { |
219
|
|
|
|
|
|
|
$actual_name = $member_name; |
220
|
|
|
|
|
|
|
$actual_name =~ s/^&//; |
221
|
|
|
|
|
|
|
croak qq|$cm: Invalid member/method name "$actual_name"| unless $actual_name =~ /^[A-Za-z_]\w*$/; |
222
|
|
|
|
|
|
|
croak qq|$cm: "$instance_var" is reserved| unless $actual_name ne $class_options{instance_var}; |
223
|
|
|
|
|
|
|
if ( substr($member_name, 0, 1) eq '&' ) { |
224
|
|
|
|
|
|
|
&$parse_method_specification($member_name, $actual_name, \%specs); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
else { |
227
|
|
|
|
|
|
|
&$parse_member_specification($member_name, \%specs, \%required); |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
$class->constructor->style(&$constructor_parameter_passing_style); |
231
|
|
|
|
|
|
|
}; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
$parse_method_specification = sub { |
234
|
|
|
|
|
|
|
my ($member_name, $actual_name, $specs) = @_; |
235
|
|
|
|
|
|
|
my (%spec, $method); |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
eval { %spec = %{Class::Generate::Hash->new($$specs{$member_name} || die, 'body')} }; |
238
|
|
|
|
|
|
|
croak &$invalid_spec_message('method', $actual_name, 'body') if $@; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
if ( $spec{class_method} ) { |
241
|
|
|
|
|
|
|
croak qq|$cm: Method "$actual_name": A class method cannot be protected| if $spec{protected}; |
242
|
|
|
|
|
|
|
$method = Class::Generate::Class_Method->new($actual_name, $spec{body}); |
243
|
|
|
|
|
|
|
if ( $spec{objects} ) { |
244
|
|
|
|
|
|
|
eval { $method->add_objects((Class::Generate::Array->new($spec{objects}))->values) }; |
245
|
|
|
|
|
|
|
croak qq|$cm: Invalid specification for objects of "$actual_name" ($sa_needed)| if $@; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
delete $spec{objects} if exists $spec{objects}; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
else { |
250
|
|
|
|
|
|
|
$method = Class::Generate::Method->new($actual_name, $spec{body}); |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
delete $spec{class_method} if exists $spec{class_method}; |
253
|
|
|
|
|
|
|
$class->user_defined_methods($actual_name, $method); |
254
|
|
|
|
|
|
|
&$set_attributes($actual_name, $method, 'Method', 'body', \%spec); |
255
|
|
|
|
|
|
|
}; |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
$parse_member_specification = sub { |
258
|
|
|
|
|
|
|
my ($member_name, $specs, $required) = @_; |
259
|
|
|
|
|
|
|
my (%spec, $member, %member_params); |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
eval { %spec = %{Class::Generate::Hash->new($$specs{$member_name} || die, 'type')} }; |
262
|
|
|
|
|
|
|
croak &$invalid_spec_message('member', $member_name, 'type') if $@; |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
$spec{required} = 1 if $$required{$member_name}; |
265
|
|
|
|
|
|
|
if ( exists $spec{default} ) { |
266
|
|
|
|
|
|
|
if ( warnings::enabled() && $class_options{check_default} ) { |
267
|
|
|
|
|
|
|
eval { Class::Generate::Support::verify_value($spec{default}, $spec{type}) }; |
268
|
|
|
|
|
|
|
warnings::warn(qq|$cm: Default value for "$member_name" is not correctly typed|) if $@; |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
&$store_initial_value_reference(\$spec{default}, $member_name) if ref $spec{default}; |
271
|
|
|
|
|
|
|
$member_params{default} = $spec{default}; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
%member_params = map defined $spec{$_} ? ($_ => $spec{$_}) : (), qw(post pre assert); |
274
|
|
|
|
|
|
|
if ( $spec{type} =~ m/^[\$@%]?($class_name_regexp)$/o ) { |
275
|
|
|
|
|
|
|
$member_params{base} = $1; |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
elsif ( $spec{type} !~ m/^[\$\@\%]$/ ) { |
278
|
|
|
|
|
|
|
croak qq|$cm: Member "$member_name": "$spec{type}" is not a valid type|; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
if ( $spec{required} && ($spec{private} || $spec{protected}) ) { |
281
|
|
|
|
|
|
|
warnings::warn(qq|$cm: "required" attribute ignored for private/protected member "$member_name"|) if warnings::enabled(); |
282
|
|
|
|
|
|
|
delete $spec{required}; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
if ( $spec{private} && $spec{protected} ) { |
285
|
|
|
|
|
|
|
warnings::warn(qq|$cm: Member "$member_name" declared both private and protected (protected assumed)|) if warnings::enabled(); |
286
|
|
|
|
|
|
|
delete $spec{private}; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
delete @member_params{grep ! defined $member_params{$_}, keys %member_params}; |
289
|
|
|
|
|
|
|
if ( substr($spec{type}, 0, 1) eq '@' ) { |
290
|
|
|
|
|
|
|
$member = Class::Generate::Array_Member->new($member_name, %member_params); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
elsif ( substr($spec{type}, 0, 1) eq '%' ) { |
293
|
|
|
|
|
|
|
$member = Class::Generate::Hash_Member->new($member_name, %member_params); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
else { |
296
|
|
|
|
|
|
|
$member = Class::Generate::Scalar_Member->new($member_name, %member_params); |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
delete $spec{type}; |
299
|
|
|
|
|
|
|
$class->members($member_name, $member); |
300
|
|
|
|
|
|
|
&$set_attributes($member_name, $member, 'Member', undef, \%spec); |
301
|
|
|
|
|
|
|
}; |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
$parse_any_flags = sub { |
304
|
|
|
|
|
|
|
my $params = $_[0]; |
305
|
|
|
|
|
|
|
my %flags = map substr($_, 0, 1) eq '-' ? ($_ => $$params{$_}) : (), keys %$params; |
306
|
|
|
|
|
|
|
return if ! %flags; |
307
|
|
|
|
|
|
|
flag: |
308
|
|
|
|
|
|
|
while ( my ($flag, $value) = each %flags ) { |
309
|
|
|
|
|
|
|
$flag eq '-use' and do { |
310
|
|
|
|
|
|
|
eval { $use_packages = Class::Generate::Array->new($value) }; |
311
|
|
|
|
|
|
|
croak qq|"-use" flag $sa_needed| if $@; |
312
|
|
|
|
|
|
|
next flag; |
313
|
|
|
|
|
|
|
}; |
314
|
|
|
|
|
|
|
$flag eq '-class_vars' and do { |
315
|
|
|
|
|
|
|
eval { $class_vars = Class::Generate::Array->new($value) }; |
316
|
|
|
|
|
|
|
croak qq|"-class_vars" flag $sa_needed| if $@; |
317
|
|
|
|
|
|
|
for my $var_spec ( grep ref($_), $class_vars->values ) { |
318
|
|
|
|
|
|
|
croak 'Each class variable must be scalar or hash reference' |
319
|
|
|
|
|
|
|
unless UNIVERSAL::isa($var_spec, 'HASH'); |
320
|
|
|
|
|
|
|
for my $var ( grep ref($$var_spec{$_}), keys %$var_spec ) { |
321
|
|
|
|
|
|
|
&$store_initial_value_reference(\$$var_spec{$var}, $var); |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
next flag; |
325
|
|
|
|
|
|
|
}; |
326
|
|
|
|
|
|
|
$flag eq '-virtual' and do { |
327
|
|
|
|
|
|
|
$class_options{virtual} = $value; |
328
|
|
|
|
|
|
|
next flag; |
329
|
|
|
|
|
|
|
}; |
330
|
|
|
|
|
|
|
$flag eq '-exclude' and do { |
331
|
|
|
|
|
|
|
eval { $excluded_methods = Class::Generate::Array->new($value) }; |
332
|
|
|
|
|
|
|
croak qq|"-exclude" flag $sa_needed| if $@; |
333
|
|
|
|
|
|
|
next flag; |
334
|
|
|
|
|
|
|
}; |
335
|
|
|
|
|
|
|
$flag eq '-comment' and do { |
336
|
|
|
|
|
|
|
$class_options{comment} = $value; |
337
|
|
|
|
|
|
|
next flag; |
338
|
|
|
|
|
|
|
}; |
339
|
|
|
|
|
|
|
$flag eq '-options' and do { |
340
|
|
|
|
|
|
|
croak qq|Options must be in hash reference| unless UNIVERSAL::isa($value, 'HASH'); |
341
|
|
|
|
|
|
|
if ( exists $$value{allow_redefine} ) { |
342
|
|
|
|
|
|
|
$allow_redefine_for_class = $$value{allow_redefine}; |
343
|
|
|
|
|
|
|
delete $$value{allow_redefine}; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
option: |
346
|
|
|
|
|
|
|
while ( my ($o, $o_value) = each %$value ) { |
347
|
|
|
|
|
|
|
if ( ! $valid_option{$o} ) { |
348
|
|
|
|
|
|
|
warnings::warn(qq|Unknown option "$o" ignored|) if warnings::enabled(); |
349
|
|
|
|
|
|
|
next option; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
$class_options{$o} = $o_value; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
if ( exists $class_options{warnings} ) { |
355
|
|
|
|
|
|
|
my $w = $class_options{warnings}; |
356
|
|
|
|
|
|
|
if ( ref $w ) { |
357
|
|
|
|
|
|
|
croak 'Warnings must be scalar value or array reference' unless UNIVERSAL::isa($w, 'ARRAY'); |
358
|
|
|
|
|
|
|
croak 'Warnings array reference must have even number of elements' unless $#$w % 2 == 1; |
359
|
|
|
|
|
|
|
for ( my $i = 0; $i <= $#$w; $i += 2 ) { |
360
|
|
|
|
|
|
|
croak qq|Warnings array: Unknown key "$$w[$i]"| unless exists $warnings_keys{$$w[$i]}; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
next flag; |
366
|
|
|
|
|
|
|
}; |
367
|
|
|
|
|
|
|
warnings::warn(qq|Unknown flag "$flag" ignored|) if warnings::enabled(); |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
delete @$params{keys %flags}; |
370
|
|
|
|
|
|
|
}; |
371
|
|
|
|
|
|
|
# Set the appropriate attributes of |
372
|
|
|
|
|
|
|
$set_attributes = sub { # a member or method w.r.t. a class. |
373
|
|
|
|
|
|
|
my ($name, $m, $type, $exclusion, $spec) = @_; |
374
|
|
|
|
|
|
|
for my $attr ( defined $exclusion ? grep($_ ne $exclusion, keys %$spec) : keys %$spec ) { |
375
|
|
|
|
|
|
|
if ( $m->can($attr) ) { |
376
|
|
|
|
|
|
|
$m->$attr($$spec{$attr}); |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
elsif ( $class->can($attr) ) { |
379
|
|
|
|
|
|
|
$class->$attr($name, $$spec{$attr}); |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
else { |
382
|
|
|
|
|
|
|
warnings::warn(qq|$cm: $type "$name": Unknown attribute "$attr"|) if warnings::enabled(); |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
}; |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
my $containing_package = __PACKAGE__ . '::'; |
388
|
|
|
|
|
|
|
my $initial_value_form = $containing_package . '_initial_values'; |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
$store_initial_value_reference = sub { # Store initial values that are |
391
|
|
|
|
|
|
|
my ($default_value, $var_name) = @_; # references in an accessible |
392
|
|
|
|
|
|
|
push @_initial_values, $$default_value; # place. |
393
|
|
|
|
|
|
|
$$default_value = "\$$initial_value_form" . "[$#_initial_values]"; |
394
|
|
|
|
|
|
|
warnings::warn(qq|Cannot save reference as initial value for "$var_name"|) |
395
|
|
|
|
|
|
|
if $class_options{save} && warnings::enabled(); |
396
|
|
|
|
|
|
|
}; |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
$class_defined = sub { # Return TRUE if the argument |
399
|
|
|
|
|
|
|
my $class_name = $_[0]; # is the name of a Perl package. |
400
|
|
|
|
|
|
|
return eval '%' . $class_name . '::'; |
401
|
|
|
|
|
|
|
}; |
402
|
|
|
|
|
|
|
# Do the main work of processing a class. |
403
|
|
|
|
|
|
|
$process_class = sub { # Parse its specification, generate a |
404
|
|
|
|
|
|
|
my $class_spec = $_[0]; # form, and evaluate that form. |
405
|
|
|
|
|
|
|
my (@warnings, $errors); |
406
|
|
|
|
|
|
|
&$croak_if_duplicate_names($class_spec); |
407
|
|
|
|
|
|
|
for my $var ( grep defined $class_options{$_}, qw(instance_var class_var) ) { |
408
|
|
|
|
|
|
|
croak qq|$cm: Value of $var option must be an identifier (without a "\$")| |
409
|
|
|
|
|
|
|
unless $class_options{$var} =~ /^[A-Za-z_]\w*$/; |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
&$parse_class_specification(UNIVERSAL::isa($class_spec, 'ARRAY') ? @$class_spec : %$class_spec); |
412
|
|
|
|
|
|
|
Class::Generate::Member_Names::set_element_regexps(); |
413
|
|
|
|
|
|
|
$class->add_class_vars($class_vars->values) if $class_vars; |
414
|
|
|
|
|
|
|
$class->add_use_packages($use_packages->values) if $use_packages; |
415
|
|
|
|
|
|
|
$class->warnings($class_options{warnings}) if $class_options{warnings}; |
416
|
|
|
|
|
|
|
$class->check_params($class_options{check_params}) if $class_options{check_params}; |
417
|
|
|
|
|
|
|
$class->excluded_methods_regexp(join '|', map "(?:$_)", $excluded_methods->values) |
418
|
|
|
|
|
|
|
if $excluded_methods; |
419
|
|
|
|
|
|
|
if ( warnings::enabled() && $class_options{check_code} ) { |
420
|
|
|
|
|
|
|
Class::Generate::Code_Checker::check_user_defined_code($class, $cm, \@warnings, \$errors); |
421
|
|
|
|
|
|
|
for my $warning ( @warnings ) { |
422
|
|
|
|
|
|
|
warnings::warn($warning); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
warnings::warn($errors) if $errors; |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
my $form = $class->form; |
428
|
|
|
|
|
|
|
if ( $class_options{save} ) { |
429
|
|
|
|
|
|
|
my ($class_file, $ob, $cb); |
430
|
|
|
|
|
|
|
if ( $class_options{save} =~ /\.p[ml]$/ ) { |
431
|
|
|
|
|
|
|
$class_file = $class_options{save}; |
432
|
|
|
|
|
|
|
open CLASS_FILE, ">>$class_file" or croak qq|$cm: Cannot append to "$class_file": $!|; |
433
|
|
|
|
|
|
|
$ob = "{\n"; # The form is enclosed in braces to prevent |
434
|
|
|
|
|
|
|
$cb = "}\n"; # renaming duplicate "my" variables. |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
else { |
437
|
|
|
|
|
|
|
$class_file = $class_name . '.pm'; |
438
|
|
|
|
|
|
|
$class_file =~ s|::|/|g; |
439
|
|
|
|
|
|
|
open CLASS_FILE, ">$class_file" or croak qq|$cm: Cannot save to "$class_file": $!|; |
440
|
|
|
|
|
|
|
$ob = $cb = ''; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
$form =~ s/^(my [%@\$]\w+) = ([%@]\{)?\$$initial_value_form\[\d+\]\}?;/$1;/mgo; |
443
|
|
|
|
|
|
|
print CLASS_FILE $ob, $form, $cb, "\n1;\n"; |
444
|
|
|
|
|
|
|
close CLASS_FILE; |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
croak "$cm: Cannot continue after errors" if $errors; |
447
|
|
|
|
|
|
|
{ |
448
|
|
|
|
|
|
|
local $SIG{__WARN__} = sub { }; # Warnings have been reported during |
449
|
13
|
100
|
100
|
13
|
|
113
|
eval $form; # user-defined code analysis. |
|
13
|
100
|
100
|
13
|
|
19
|
|
|
13
|
50
|
33
|
13
|
|
430
|
|
|
13
|
100
|
33
|
13
|
|
244
|
|
|
13
|
100
|
33
|
12
|
|
26
|
|
|
13
|
100
|
33
|
12
|
|
806
|
|
|
13
|
100
|
0
|
12
|
|
79
|
|
|
13
|
100
|
0
|
12
|
|
18
|
|
|
13
|
100
|
0
|
12
|
|
473
|
|
|
13
|
100
|
0
|
10
|
|
104
|
|
|
13
|
100
|
|
9
|
|
18
|
|
|
13
|
100
|
|
9
|
|
10824
|
|
|
12
|
100
|
|
9
|
|
145
|
|
|
12
|
100
|
|
9
|
|
32
|
|
|
12
|
50
|
|
8
|
|
1810
|
|
|
12
|
100
|
|
8
|
|
237
|
|
|
12
|
100
|
|
8
|
|
21
|
|
|
12
|
50
|
|
8
|
|
618
|
|
|
12
|
50
|
|
8
|
|
84
|
|
|
12
|
100
|
|
7
|
|
19
|
|
|
12
|
100
|
|
1
|
|
524
|
|
|
12
|
100
|
|
11
|
|
107
|
|
|
12
|
100
|
|
10
|
|
23
|
|
|
12
|
100
|
|
2
|
|
8819
|
|
|
12
|
50
|
|
9
|
|
123
|
|
|
12
|
100
|
|
0
|
|
19
|
|
|
12
|
100
|
|
0
|
|
1403
|
|
|
10
|
100
|
|
12
|
|
68
|
|
|
10
|
100
|
|
8
|
|
21
|
|
|
10
|
100
|
|
12
|
|
864
|
|
|
9
|
100
|
|
7
|
|
97
|
|
|
9
|
100
|
|
3
|
|
15
|
|
|
9
|
50
|
|
1
|
|
317
|
|
|
9
|
100
|
|
2
|
|
213
|
|
|
9
|
50
|
|
0
|
|
19
|
|
|
9
|
50
|
|
8
|
|
8318
|
|
|
8
|
100
|
|
7
|
|
52
|
|
|
8
|
100
|
|
1
|
|
15
|
|
|
8
|
50
|
|
2
|
|
311
|
|
|
8
|
0
|
|
6
|
|
36
|
|
|
8
|
0
|
|
2
|
|
9
|
|
|
8
|
0
|
|
2
|
|
1024
|
|
|
8
|
50
|
|
3
|
|
42
|
|
|
8
|
50
|
|
3
|
|
8
|
|
|
8
|
50
|
|
37
|
|
285
|
|
|
8
|
0
|
|
39
|
|
37
|
|
|
8
|
0
|
|
57
|
|
11
|
|
|
8
|
0
|
|
18
|
|
6000
|
|
|
8
|
100
|
|
8
|
|
46
|
|
|
8
|
100
|
|
21
|
|
14
|
|
|
8
|
100
|
|
10
|
|
654
|
|
|
8
|
100
|
|
6
|
|
42
|
|
|
8
|
100
|
|
2
|
|
15
|
|
|
8
|
100
|
|
3
|
|
536
|
|
|
8
|
100
|
|
2
|
|
46
|
|
|
8
|
100
|
|
2
|
|
14
|
|
|
8
|
100
|
|
0
|
|
466
|
|
|
7
|
100
|
|
8
|
|
37
|
|
|
7
|
100
|
|
3
|
|
10
|
|
|
7
|
100
|
|
11
|
|
13762
|
|
|
1
|
100
|
|
4
|
|
3
|
|
|
1
|
100
|
|
0
|
|
6
|
|
|
0
|
50
|
|
4
|
|
0
|
|
|
11
|
100
|
|
0
|
|
52
|
|
|
11
|
100
|
|
1
|
|
9
|
|
|
11
|
100
|
|
0
|
|
14
|
|
|
11
|
100
|
|
6
|
|
25
|
|
|
11
|
100
|
|
3
|
|
26
|
|
|
21
|
100
|
|
3
|
|
36
|
|
|
21
|
100
|
|
0
|
|
25
|
|
|
21
|
100
|
|
0
|
|
289
|
|
|
13
|
50
|
|
0
|
|
37
|
|
|
12
|
100
|
|
0
|
|
52
|
|
|
4
|
50
|
|
|
|
35
|
|
|
12
|
100
|
|
|
|
24
|
|
|
3
|
100
|
|
|
|
83
|
|
|
11
|
0
|
|
|
|
25
|
|
|
4
|
0
|
|
|
|
48
|
|
|
4
|
0
|
|
|
|
7
|
|
|
8
|
50
|
|
|
|
22
|
|
|
6
|
50
|
|
|
|
105
|
|
|
11
|
100
|
|
|
|
69
|
|
|
16
|
100
|
|
|
|
24
|
|
|
8
|
50
|
|
|
|
13
|
|
|
19
|
100
|
|
|
|
171
|
|
|
19
|
50
|
|
|
|
42
|
|
|
9
|
100
|
|
|
|
89
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
12
|
100
|
|
|
|
137
|
|
|
12
|
50
|
|
|
|
11
|
|
|
12
|
100
|
|
|
|
10
|
|
|
12
|
50
|
|
|
|
33
|
|
|
6
|
100
|
|
|
|
11
|
|
|
6
|
100
|
|
|
|
4
|
|
|
6
|
0
|
|
|
|
10
|
|
|
14
|
50
|
|
|
|
20
|
|
|
14
|
50
|
|
|
|
28
|
|
|
24
|
50
|
|
|
|
46
|
|
|
16
|
0
|
|
|
|
32
|
|
|
16
|
50
|
|
|
|
30
|
|
|
16
|
100
|
|
|
|
33
|
|
|
15
|
50
|
|
|
|
31
|
|
|
23
|
100
|
|
|
|
36
|
|
|
22
|
50
|
|
|
|
49
|
|
|
23
|
100
|
|
|
|
50
|
|
|
26
|
50
|
|
|
|
176
|
|
|
21
|
50
|
|
|
|
42
|
|
|
20
|
50
|
|
|
|
53
|
|
|
20
|
0
|
|
|
|
148
|
|
|
9
|
50
|
|
|
|
23
|
|
|
3
|
0
|
|
|
|
7
|
|
|
3
|
50
|
|
|
|
6
|
|
|
3
|
0
|
|
|
|
36
|
|
|
2
|
100
|
|
|
|
9
|
|
|
3
|
50
|
|
|
|
12
|
|
|
4
|
100
|
|
|
|
8
|
|
|
4
|
50
|
|
|
|
11
|
|
|
2
|
50
|
|
|
|
5
|
|
|
2
|
0
|
|
|
|
5
|
|
|
3
|
0
|
|
|
|
9
|
|
|
2
|
0
|
|
|
|
5
|
|
|
3
|
0
|
|
|
|
53
|
|
|
4
|
0
|
|
|
|
24
|
|
|
4
|
0
|
|
|
|
10
|
|
|
7
|
|
|
|
|
6
|
|
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
21
|
|
|
6
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
100
|
|
|
6
|
|
|
|
|
19
|
|
|
8
|
|
|
|
|
71
|
|
|
8
|
|
|
|
|
51
|
|
|
9
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
33
|
|
|
9
|
|
|
|
|
21
|
|
|
7
|
|
|
|
|
32
|
|
|
5
|
|
|
|
|
46
|
|
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
31
|
|
|
2
|
|
|
|
|
12
|
|
|
1
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
13
|
|
|
10
|
|
|
|
|
51
|
|
|
10
|
|
|
|
|
33
|
|
|
11
|
|
|
|
|
33
|
|
|
7
|
|
|
|
|
69
|
|
|
2
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
4
|
|
|
0
|
|
|
|
|
0
|
|
|
6
|
|
|
|
|
170
|
|
|
6
|
|
|
|
|
17
|
|
|
6
|
|
|
|
|
31
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
2
|
|
|
|
|
23
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
45
|
|
|
2
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
15
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
15
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
1
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
48
|
|
|
1
|
|
|
|
|
6
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
5
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
5
|
|
|
|
|
308
|
|
|
5
|
|
|
|
|
17
|
|
|
4
|
|
|
|
|
25
|
|
|
35
|
|
|
|
|
1111
|
|
|
34
|
|
|
|
|
134
|
|
|
34
|
|
|
|
|
293
|
|
|
32
|
|
|
|
|
40
|
|
|
34
|
|
|
|
|
222
|
|
|
28
|
|
|
|
|
87
|
|
|
28
|
|
|
|
|
77
|
|
|
26
|
|
|
|
|
251
|
|
|
23
|
|
|
|
|
114
|
|
|
10
|
|
|
|
|
45
|
|
|
58
|
|
|
|
|
1377
|
|
|
48
|
|
|
|
|
216
|
|
|
49
|
|
|
|
|
148
|
|
|
43
|
|
|
|
|
195
|
|
|
46
|
|
|
|
|
110
|
|
|
46
|
|
|
|
|
134
|
|
|
43
|
|
|
|
|
163
|
|
|
41
|
|
|
|
|
783
|
|
|
23
|
|
|
|
|
403
|
|
|
30
|
|
|
|
|
86
|
|
|
27
|
|
|
|
|
101
|
|
|
21
|
|
|
|
|
59
|
|
|
15
|
|
|
|
|
56
|
|
|
13
|
|
|
|
|
33
|
|
|
63
|
|
|
|
|
1484
|
|
|
61
|
|
|
|
|
556
|
|
|
59
|
|
|
|
|
114
|
|
|
60
|
|
|
|
|
99
|
|
|
56
|
|
|
|
|
161
|
|
|
56
|
|
|
|
|
173
|
|
|
56
|
|
|
|
|
497
|
|
|
33
|
|
|
|
|
487
|
|
|
32
|
|
|
|
|
385
|
|
|
12
|
|
|
|
|
48
|
|
|
24
|
|
|
|
|
71
|
|
|
9
|
|
|
|
|
38
|
|
|
32
|
|
|
|
|
727
|
|
|
32
|
|
|
|
|
99
|
|
|
32
|
|
|
|
|
60
|
|
|
36
|
|
|
|
|
256
|
|
|
31
|
|
|
|
|
75
|
|
|
28
|
|
|
|
|
86
|
|
|
27
|
|
|
|
|
66
|
|
|
29
|
|
|
|
|
129
|
|
|
28
|
|
|
|
|
66
|
|
|
23
|
|
|
|
|
92
|
|
|
27
|
|
|
|
|
145
|
|
|
18
|
|
|
|
|
384
|
|
|
18
|
|
|
|
|
86
|
|
|
13
|
|
|
|
|
31
|
|
|
15
|
|
|
|
|
204
|
|
|
8
|
|
|
|
|
20
|
|
|
8
|
|
|
|
|
24
|
|
|
9
|
|
|
|
|
114
|
|
|
20
|
|
|
|
|
391
|
|
|
18
|
|
|
|
|
72
|
|
|
12
|
|
|
|
|
137
|
|
|
9
|
|
|
|
|
28
|
|
|
10
|
|
|
|
|
76
|
|
|
6
|
|
|
|
|
46
|
|
|
6
|
|
|
|
|
117
|
|
|
5
|
|
|
|
|
823
|
|
|
4
|
|
|
|
|
50
|
|
|
4
|
|
|
|
|
291
|
|
|
3
|
|
|
|
|
15
|
|
|
16
|
|
|
|
|
559
|
|
|
14
|
|
|
|
|
43
|
|
|
14
|
|
|
|
|
29
|
|
|
14
|
|
|
|
|
12
|
|
|
16
|
|
|
|
|
178
|
|
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
30
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
2
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
4
|
|
|
|
|
23
|
|
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
6
|
|
|
5
|
|
|
|
|
11
|
|
|
0
|
|
|
|
|
0
|
|
|
8
|
|
|
|
|
164
|
|
|
8
|
|
|
|
|
21
|
|
|
3
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
61
|
|
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
69
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
29
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
28
|
|
|
2
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
2
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
8
|
|
|
|
|
256
|
|
|
8
|
|
|
|
|
15
|
|
|
2
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
3
|
|
|
6
|
|
|
|
|
16
|
|
|
4
|
|
|
|
|
11
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
33
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
4
|
|
|
0
|
|
|
|
|
0
|
|
|
3
|
|
|
|
|
60
|
|
|
3
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
11
|
|
|
|
|
278
|
|
|
11
|
|
|
|
|
21
|
|
|
1
|
|
|
|
|
5
|
|
|
0
|
|
|
|
|
0
|
|
|
10
|
|
|
|
|
18
|
|
|
9
|
|
|
|
|
77
|
|
|
2
|
|
|
|
|
15
|
|
|
2
|
|
|
|
|
27
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1
|
|
|
0
|
|
|
|
|
0
|
|
|
4
|
|
|
|
|
117
|
|
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
14
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
4
|
|
|
|
|
72
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
22
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
67
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
4
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
6
|
|
|
|
|
147
|
|
|
6
|
|
|
|
|
14
|
|
|
4
|
|
|
|
|
12
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
3
|
|
|
|
|
35
|
|
|
3
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
29
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
0
|
|
|
|
|
0
|
|
|
3
|
|
|
|
|
101
|
|
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
9
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
if ( $@ ) { |
451
|
|
|
|
|
|
|
my @lines = split("\n", $form); |
452
|
|
|
|
|
|
|
my ($l) = ($@ =~ /(\d+)\.$/); |
453
|
|
|
|
|
|
|
$@ =~ s/\(eval \d+\) //; |
454
|
|
|
|
|
|
|
croak "$cm: Evaluation failed (problem in ", __PACKAGE__, "?)\n", |
455
|
|
|
|
|
|
|
$@, "\n", join("\n", @lines[$l-1 .. $l+1]), "\n"; |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
Class::Generate::Class_Holder::store($class); |
459
|
|
|
|
|
|
|
}; |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
$constructor_parameter_passing_style = sub { # Establish the parameter-passing style |
462
|
|
|
|
|
|
|
my ($style, # for a class' constructor, meanwhile |
463
|
|
|
|
|
|
|
@values, # checking for mismatches w.r.t. the |
464
|
|
|
|
|
|
|
$parent_with_constructor, # class' superclass. Return an |
465
|
|
|
|
|
|
|
$parent_constructor_package_name); # appropriate style. |
466
|
|
|
|
|
|
|
if ( defined $class->parents ) { |
467
|
|
|
|
|
|
|
$parent_with_constructor = Class::Generate::Support::class_containing_method('new', $class); |
468
|
|
|
|
|
|
|
$parent_constructor_package_name = (ref $parent_with_constructor ? $parent_with_constructor->name : $parent_with_constructor); |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
(($style, @values) = $param_style_spec->values)[0] eq 'key_value' and do { |
471
|
|
|
|
|
|
|
if ( defined $parent_with_constructor && ref $parent_with_constructor && index(ref $parent_with_constructor, $containing_package) == 0 ) { |
472
|
|
|
|
|
|
|
my $invoked_constructor_style = $parent_with_constructor->constructor->style; |
473
|
|
|
|
|
|
|
unless ( $invoked_constructor_style->isa($containing_package . 'Key_Value') || |
474
|
|
|
|
|
|
|
$invoked_constructor_style->isa($containing_package . 'Own') ) { |
475
|
|
|
|
|
|
|
warnings::warn(qq{$cm: Probable mismatch calling constructor in superclass "$parent_constructor_package_name"}) if warnings::enabled(); |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
return Class::Generate::Key_Value->new('params', $class->public_member_names); |
479
|
|
|
|
|
|
|
}; |
480
|
|
|
|
|
|
|
$style eq 'positional' and do { |
481
|
|
|
|
|
|
|
&$check_for_invalid_parameter_names(@values); |
482
|
|
|
|
|
|
|
my @member_names = $class->public_member_names; |
483
|
|
|
|
|
|
|
croak "$cm: Missing/extra members in style" unless $#values == $#member_names; |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
return Class::Generate::Positional->new(@values); |
486
|
|
|
|
|
|
|
}; |
487
|
|
|
|
|
|
|
$style eq 'mix' and do { |
488
|
|
|
|
|
|
|
&$check_for_invalid_parameter_names(@values); |
489
|
|
|
|
|
|
|
my @member_names = $class->public_member_names; |
490
|
|
|
|
|
|
|
croak "$cm: Extra parameters in style specifier" unless $#values <= $#member_names; |
491
|
|
|
|
|
|
|
my %kv_members = map(($_ => 1), @member_names); |
492
|
|
|
|
|
|
|
delete @kv_members{@values}; |
493
|
|
|
|
|
|
|
return Class::Generate::Mix->new('params', [@values], keys %kv_members); |
494
|
|
|
|
|
|
|
}; |
495
|
|
|
|
|
|
|
$style eq 'own' and do { |
496
|
|
|
|
|
|
|
for ( my $i = 0; $i <= $#values; $i++ ) { |
497
|
|
|
|
|
|
|
&$store_initial_value_reference(\$values[$i], $parent_constructor_package_name . '::new') if ref $values[$i]; |
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
return Class::Generate::Own->new([@values]); |
500
|
|
|
|
|
|
|
}; |
501
|
|
|
|
|
|
|
croak qq|$cm: Invalid parameter passing style "$style"|; |
502
|
|
|
|
|
|
|
}; |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
$check_for_invalid_parameter_names = sub { |
505
|
|
|
|
|
|
|
my @param_names = @_; |
506
|
|
|
|
|
|
|
my $i = 0; |
507
|
|
|
|
|
|
|
for my $param ( @param_names ) { |
508
|
|
|
|
|
|
|
croak qq|$cm: Error in new => { style => '... $param' }: $param is not a member| |
509
|
|
|
|
|
|
|
if ! defined $class->members($param); |
510
|
|
|
|
|
|
|
croak qq|$cm: Error in new => { style => '... $param' }: $param is not a public member| |
511
|
|
|
|
|
|
|
if $class->private($param) || $class->protected($param); |
512
|
|
|
|
|
|
|
} |
513
|
|
|
|
|
|
|
my %uses; |
514
|
|
|
|
|
|
|
for my $param ( @param_names ) { |
515
|
|
|
|
|
|
|
$uses{$param}++; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
%uses = map(($uses{$_} > 1 ? ($_ => $uses{$_}) : ()), keys %uses); |
518
|
|
|
|
|
|
|
if ( %uses ) { |
519
|
|
|
|
|
|
|
croak "$cm: Error in new => { style => '...' }: ", join('; ', map qq|Name "$_" used $uses{$_} times|, keys %uses); |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
}; |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
$croak_if_duplicate_names = sub { |
524
|
|
|
|
|
|
|
my $class_spec = $_[0]; |
525
|
|
|
|
|
|
|
my (@names, %uses); |
526
|
|
|
|
|
|
|
if ( UNIVERSAL::isa($class_spec, 'ARRAY') ) { |
527
|
|
|
|
|
|
|
for ( my $i = 0; $i <= $#$class_spec; $i += 2 ) { |
528
|
|
|
|
|
|
|
push @names, $$class_spec[$i]; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
else { |
532
|
|
|
|
|
|
|
@names = keys %$class_spec; |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
for ( @names ) { |
535
|
|
|
|
|
|
|
$uses{substr($_, 0, 1) eq '&' ? substr($_, 1) : $_}++; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
%uses = map(($uses{$_} > 1 ? ($_ => $uses{$_}) : ()), keys %uses); |
538
|
|
|
|
|
|
|
if ( %uses ) { |
539
|
|
|
|
|
|
|
croak "$cm: ", join('; ', map qq|Name "$_" used $uses{$_} times|, keys %uses); |
540
|
|
|
|
|
|
|
} |
541
|
|
|
|
|
|
|
}; |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
$invalid_spec_message = sub { |
544
|
|
|
|
|
|
|
return sprintf qq|$cm: Invalid specification of %s "%s" ($sh_needed with "%s" key)|, @_; |
545
|
|
|
|
|
|
|
}; |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
package Class::Generate::Class_Holder; # This package encapsulates functions |
548
|
15
|
|
|
15
|
|
271
|
use strict; # related to storing and retrieving |
|
15
|
|
|
|
|
46
|
|
|
15
|
|
|
|
|
18349
|
|
549
|
|
|
|
|
|
|
# information on classes. It lets classes |
550
|
|
|
|
|
|
|
# saved in files be reused transparently. |
551
|
|
|
|
|
|
|
my %classes; |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
sub store($) { # Given a class, store it so it's |
554
|
77
|
|
|
65
|
|
149
|
my $class = $_[0]; # accessible in future invocations of |
555
|
77
|
|
|
|
|
525
|
$classes{$class->name} = $class; # class() and subclass(). |
556
|
|
|
|
|
|
|
} |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
# Given a class name, try to return an instance of Class::Generate::Class |
559
|
|
|
|
|
|
|
# that models the class. The instance comes from one of 3 places. We |
560
|
|
|
|
|
|
|
# first try to get it from wherever store() puts it. If that fails, |
561
|
|
|
|
|
|
|
# we check to see if the variable %::_cginfo exists (see |
562
|
|
|
|
|
|
|
# form(), below); if it does, we use the information it contains to |
563
|
|
|
|
|
|
|
# create an instance of Class::Generate::Class. If %::_cginfo |
564
|
|
|
|
|
|
|
# doesn't exist, the package wasn't created by Class::Generate. We try |
565
|
|
|
|
|
|
|
# to infer some characteristics of the class. |
566
|
|
|
|
|
|
|
sub get($;$) { |
567
|
45
|
|
|
35
|
|
427
|
my ($class_name, $default_type) = @_; |
568
|
41
|
100
|
|
|
|
397
|
return $classes{$class_name} if exists $classes{$class_name}; |
569
|
|
|
|
|
|
|
|
570
|
7
|
100
|
|
|
|
134
|
return undef if ! eval '%' . $class_name . '::'; # Package doesn't exist. |
571
|
|
|
|
|
|
|
|
572
|
6
|
|
|
|
|
100
|
my ($class, %info); |
573
|
2
|
100
|
|
|
|
4
|
if ( ! eval "exists \$" . $class_name . '::{_cginfo}' ) { # Package exists but is |
574
|
2
|
100
|
|
|
|
7
|
return undef if ! defined $default_type; # not a class generated |
575
|
2
|
50
|
|
|
|
4
|
if ( $default_type eq 'ARRAY' ) { # by Class::Generate. |
576
|
2
|
|
|
|
|
2
|
$class = new Class::Generate::Array_Class $class_name; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
else { |
579
|
6
|
|
|
|
|
131
|
$class = new Class::Generate::Hash_Class $class_name; |
580
|
|
|
|
|
|
|
} |
581
|
4
|
|
|
|
|
51
|
$class->constructor(new Class::Generate::Constructor); |
582
|
5
|
|
|
|
|
22
|
$class->constructor->style(new Class::Generate::Own); |
583
|
3
|
|
|
|
|
28
|
$classes{$class_name} = $class; |
584
|
4
|
|
|
|
|
73
|
return $class; |
585
|
|
|
|
|
|
|
} |
586
|
|
|
|
|
|
|
|
587
|
4
|
|
|
|
|
58
|
eval '%info = %' . $class_name . '::_cginfo'; |
588
|
4
|
100
|
|
|
|
36
|
if ( $info{base} eq 'ARRAY' ) { |
589
|
3
|
|
|
|
|
21
|
$class = Class::Generate::Array_Class->new($class_name, last => $info{last}); |
590
|
|
|
|
|
|
|
} |
591
|
|
|
|
|
|
|
else { |
592
|
3
|
|
|
|
|
32
|
$class = Class::Generate::Hash_Class->new($class_name); |
593
|
|
|
|
|
|
|
} |
594
|
2
|
50
|
|
|
|
27
|
if ( exists $info{members} ) { # Add members ... |
595
|
2
|
|
|
|
|
5
|
while ( my ($name, $mem_info_ref) = each %{$info{members}} ) { |
|
2
|
|
|
|
|
26
|
|
596
|
2
|
|
|
|
|
40
|
my ($member, %mem_info); |
597
|
2
|
|
|
|
|
6
|
%mem_info = %$mem_info_ref; |
598
|
|
|
|
|
|
|
DEFN: { |
599
|
2
|
100
|
|
|
|
37
|
$mem_info{type} eq "\$" and do { $member = Class::Generate::Scalar_Member->new($name); last DEFN }; |
|
3
|
|
|
|
|
116
|
|
|
3
|
|
|
|
|
50
|
|
|
3
|
|
|
|
|
52
|
|
600
|
3
|
100
|
|
|
|
7
|
$mem_info{type} eq '@' and do { $member = Class::Generate::Array_Member->new($name); last DEFN }; |
|
4
|
|
|
|
|
146
|
|
|
4
|
|
|
|
|
19
|
|
601
|
4
|
100
|
|
|
|
21
|
$mem_info{type} eq '%' and do { $member = Class::Generate::Hash_Member->new($name); last DEFN }; |
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
7
|
|
602
|
|
|
|
|
|
|
} |
603
|
2
|
100
|
|
|
|
4
|
$member->base($mem_info{base}) if exists $mem_info{base}; |
604
|
2
|
|
|
|
|
5
|
$class->members($name, $member); |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
} |
607
|
2
|
50
|
|
|
|
4
|
if ( exists $info{class_methods} ) { # Add methods... |
608
|
2
|
|
|
|
|
5
|
for my $name ( @{$info{class_methods}} ) { |
|
2
|
|
|
|
|
14
|
|
609
|
2
|
|
|
|
|
3
|
$class->user_defined_methods($name, Class::Generate::Class_Method->new($name)); |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
} |
612
|
2
|
100
|
|
|
|
4
|
if ( exists $info{instance_methods} ) { |
613
|
3
|
|
|
|
|
92
|
for my $name ( @{$info{instance_methods}} ) { |
|
1
|
|
|
|
|
2
|
|
614
|
1
|
|
|
|
|
2
|
$class->user_defined_methods($name, Class::Generate::Method->new($name)); |
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
} |
617
|
4
|
50
|
|
|
|
175
|
if ( exists $info{protected} ) { # Set access ... |
618
|
4
|
|
|
|
|
16
|
for my $protected_member ( @{$info{protected}} ) { |
|
4
|
|
|
|
|
23
|
|
619
|
1
|
|
|
|
|
87
|
$class->protected($protected_member, 1); |
620
|
|
|
|
|
|
|
} |
621
|
|
|
|
|
|
|
} |
622
|
1
|
100
|
|
|
|
6
|
if ( exists $info{private} ) { |
623
|
1
|
|
|
|
|
6
|
for my $private_member ( @{$info{private}} ) { |
|
1
|
|
|
|
|
5
|
|
624
|
1
|
|
|
|
|
5
|
$class->private($private_member, 1); |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
} |
627
|
1
|
50
|
|
|
|
3
|
$class->excluded_methods_regexp($info{emr}) if exists $info{emr}; |
628
|
1
|
|
|
|
|
36
|
$class->constructor(new Class::Generate::Constructor); |
629
|
|
|
|
|
|
|
CONSTRUCTOR_STYLE: { |
630
|
1
|
100
|
|
|
|
2
|
exists $info{kv_style} and do { |
|
1
|
|
|
|
|
7
|
|
631
|
1
|
|
|
|
|
38
|
$class->constructor->style(new Class::Generate::Key_Value 'params', @{$info{kv_style}}); |
|
1
|
|
|
|
|
29
|
|
632
|
0
|
|
|
|
|
0
|
last CONSTRUCTOR_STYLE; |
633
|
|
|
|
|
|
|
}; |
634
|
5
|
50
|
|
|
|
129
|
exists $info{pos_style} and do { |
635
|
5
|
|
|
|
|
30
|
$class->constructor->style(new Class::Generate::Positional(@{$info{pos_style}})); |
|
5
|
|
|
|
|
34
|
|
636
|
3
|
|
|
|
|
4
|
last CONSTRUCTOR_STYLE; |
637
|
|
|
|
|
|
|
}; |
638
|
3
|
50
|
|
|
|
13
|
exists $info{mix_style} and do { |
639
|
3
|
|
|
|
|
12
|
$class->constructor->style(new Class::Generate::Mix('params', |
640
|
3
|
|
|
|
|
9
|
[@{$info{mix_style}{keyed}}], |
641
|
3
|
|
|
|
|
16
|
@{$info{mix_style}{pos}})); |
642
|
3
|
|
|
|
|
7
|
last CONSTRUCTOR_STYLE; |
643
|
|
|
|
|
|
|
}; |
644
|
3
|
50
|
|
|
|
10
|
exists $info{own_style} and do { |
645
|
3
|
|
|
|
|
8
|
$class->constructor->style(new Class::Generate::Own(@{$info{own_style}})); |
|
3
|
|
|
|
|
9
|
|
646
|
3
|
|
|
|
|
5
|
last CONSTRUCTOR_STYLE; |
647
|
|
|
|
|
|
|
}; |
648
|
|
|
|
|
|
|
} |
649
|
|
|
|
|
|
|
|
650
|
3
|
|
|
|
|
6
|
$classes{$class_name} = $class; |
651
|
3
|
|
|
|
|
16
|
return $class; |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
sub remove($) { |
655
|
3
|
|
|
8
|
|
6
|
delete $classes{$_[0]}; |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
sub form($) { |
659
|
64
|
|
|
65
|
|
147
|
my $class = $_[0]; |
660
|
64
|
|
|
|
|
121
|
my $form = qq|use vars qw(\%_cginfo);\n| . '%_cginfo = ('; |
661
|
70
|
100
|
|
|
|
819
|
if ( $class->isa('Class::Generate::Array_Class') ) { |
662
|
27
|
|
|
|
|
185
|
$form .= q|base => 'ARRAY', last => | . $class->last; |
663
|
|
|
|
|
|
|
} |
664
|
|
|
|
|
|
|
else { |
665
|
47
|
|
|
|
|
133
|
$form .= q|base => 'HASH'|; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
63
|
100
|
|
|
|
174
|
if ( my @members = $class->members_values ) { |
669
|
57
|
|
|
|
|
454
|
$form .= ', members => { ' . join(', ', map(member($_), @members)) . ' }'; |
670
|
|
|
|
|
|
|
} |
671
|
64
|
|
|
|
|
132
|
my (@class_methods, @instance_methods); |
672
|
63
|
|
|
|
|
217
|
for my $m ( $class->user_defined_methods_values ) { |
673
|
30
|
100
|
|
|
|
166
|
if ( $m->isa('Class::Generate::Class_Method') ) { |
674
|
3
|
|
|
|
|
39
|
push @class_methods, $m->name; |
675
|
|
|
|
|
|
|
} |
676
|
|
|
|
|
|
|
else { |
677
|
27
|
|
|
|
|
77
|
push @instance_methods, $m->name; |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
} |
680
|
62
|
|
|
|
|
239
|
$form .= comma_prefixed_list_of_values('class_methods', @class_methods); |
681
|
61
|
|
|
|
|
137
|
$form .= comma_prefixed_list_of_values('instance_methods', @instance_methods); |
682
|
61
|
|
|
|
|
127
|
$form .= comma_prefixed_list_of_values('protected', do { my %p = $class->protected; keys %p }); |
|
61
|
|
|
|
|
197
|
|
|
61
|
|
|
|
|
184
|
|
683
|
64
|
|
|
|
|
315
|
$form .= comma_prefixed_list_of_values('private', do { my %p = $class->private; keys %p }); |
|
64
|
|
|
|
|
173
|
|
|
64
|
|
|
|
|
157
|
|
684
|
|
|
|
|
|
|
|
685
|
61
|
100
|
|
|
|
186
|
if ( my $emr = $class->excluded_methods_regexp ) { |
686
|
7
|
|
|
|
|
18
|
$emr =~ s/\'/\\\'/g; |
687
|
7
|
|
|
|
|
15
|
$form .= ", emr => '$emr'"; |
688
|
|
|
|
|
|
|
} |
689
|
61
|
100
|
|
|
|
171
|
if ( (my $constructor = $class->constructor) ) { |
690
|
61
|
|
|
|
|
191
|
my $style = $constructor->style; |
691
|
|
|
|
|
|
|
STYLE: { |
692
|
61
|
100
|
|
|
|
90
|
$style->isa('Class::Generate::Key_Value') and do { |
|
61
|
|
|
|
|
415
|
|
693
|
41
|
|
|
|
|
277
|
my @kpn = $style->keyed_param_names; |
694
|
41
|
100
|
|
|
|
103
|
if ( @kpn ) { |
695
|
33
|
|
|
|
|
82
|
$form .= comma_prefixed_list_of_values('kv_style', $style->keyed_param_names); |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
else { |
698
|
8
|
|
|
|
|
11
|
$form .= ', kv_style => []'; |
699
|
|
|
|
|
|
|
} |
700
|
41
|
|
|
|
|
125
|
last STYLE; |
701
|
|
|
|
|
|
|
}; |
702
|
22
|
100
|
|
|
|
249
|
$style->isa('Class::Generate::Positional') and do { |
703
|
12
|
|
|
|
|
27
|
my @members = sort { $style->order($a) <=> $style->order($b) } do { my %m = $style->order; keys %m }; |
|
7
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
73
|
|
|
10
|
|
|
|
|
44
|
|
704
|
11
|
100
|
|
|
|
33
|
if ( @members ) { |
705
|
10
|
|
|
|
|
32
|
$form .= comma_prefixed_list_of_values('pos_style', @members); |
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
else { |
708
|
2
|
|
|
|
|
8
|
$form .= ', pos_style => []'; |
709
|
|
|
|
|
|
|
} |
710
|
10
|
|
|
|
|
34
|
last STYLE; |
711
|
|
|
|
|
|
|
}; |
712
|
10
|
100
|
|
|
|
66
|
$style->isa('Class::Generate::Mix') and do { |
713
|
5
|
|
|
|
|
19
|
my @keyed_members = $style->keyed_param_names; |
714
|
5
|
|
|
|
|
11
|
my @pos_members = sort { $style->order($a) <=> $style->order($b) } do { my %m = $style->order; keys %m }; |
|
1
|
|
|
|
|
3
|
|
|
5
|
|
|
|
|
20
|
|
|
5
|
|
|
|
|
20
|
|
715
|
8
|
100
|
100
|
|
|
196
|
if ( @keyed_members || @pos_members ) { |
716
|
7
|
|
|
|
|
27
|
my $km_form = list_of_values('keyed', @keyed_members); |
717
|
6
|
|
|
|
|
26
|
my $pm_form = list_of_values('pos', @pos_members); |
718
|
4
|
|
|
|
|
26
|
$form .= ', mix_style => {' . join(', ', grep(length > 0, ($km_form, $pm_form))) . '}'; |
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
else { |
721
|
3
|
|
|
|
|
74
|
$form .= ', mix_style => {}'; |
722
|
|
|
|
|
|
|
} |
723
|
7
|
|
|
|
|
31
|
last STYLE; |
724
|
|
|
|
|
|
|
}; |
725
|
6
|
100
|
|
|
|
31
|
$style->isa('Class::Generate::Own') and do { |
726
|
5
|
|
|
|
|
19
|
my @super_values = $style->super_values; |
727
|
6
|
100
|
|
|
|
78
|
if ( @super_values ) { |
728
|
4
|
|
|
|
|
12
|
for my $sv ( @super_values) { |
729
|
6
|
|
|
|
|
27
|
$sv =~ s/\'/\\\'/g; |
730
|
|
|
|
|
|
|
} |
731
|
3
|
|
|
|
|
7
|
$form .= comma_prefixed_list_of_values('own_style', @super_values); |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
else { |
734
|
3
|
|
|
|
|
65
|
$form .= ', own_style => []'; |
735
|
|
|
|
|
|
|
} |
736
|
6
|
|
|
|
|
21
|
last STYLE; |
737
|
|
|
|
|
|
|
}; |
738
|
|
|
|
|
|
|
} |
739
|
|
|
|
|
|
|
} |
740
|
62
|
|
|
|
|
94
|
$form .= ');' . "\n"; |
741
|
61
|
|
|
|
|
192
|
return $form; |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
sub member($) { |
745
|
136
|
|
|
136
|
|
308
|
my $member = $_[0]; |
746
|
137
|
|
|
|
|
111
|
my $base; |
747
|
137
|
|
|
|
|
263
|
my $form = $member->name . ' => {'; |
748
|
133
|
100
|
|
|
|
841
|
$form .= " type => '" . ($member->isa('Class::Generate::Scalar_Member') ? "\$" : |
|
|
100
|
|
|
|
|
|
749
|
|
|
|
|
|
|
$member->isa('Class::Generate::Array_Member') ? '@' : '%') . "'"; |
750
|
134
|
100
|
|
|
|
363
|
if ( defined ($base = $member->base) ) { |
751
|
17
|
|
|
|
|
25
|
$form .= ", base => '$base'"; |
752
|
|
|
|
|
|
|
} |
753
|
134
|
|
|
|
|
449
|
return $form . '}'; |
754
|
|
|
|
|
|
|
} |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
sub list_of_values($@) { |
757
|
76
|
|
|
79
|
|
165
|
my ($key, @list) = @_; |
758
|
77
|
100
|
|
|
|
241
|
return '' if ! @list; |
759
|
76
|
|
|
|
|
533
|
return "$key => [" . join(', ', map("'$_'", @list)) . ']'; |
760
|
|
|
|
|
|
|
} |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
sub comma_prefixed_list_of_values($@) { |
763
|
290
|
100
|
|
290
|
|
823
|
return $#_ > 0 ? ', ' . list_of_values($_[0], @_[1..$#_]) : ''; |
764
|
|
|
|
|
|
|
} |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
package Class::Generate::Member_Names; # This package encapsulates functions |
767
|
15
|
|
|
15
|
|
234
|
use strict; # to handle name substitution in |
|
14
|
|
|
|
|
31
|
|
|
14
|
|
|
|
|
19113
|
|
768
|
|
|
|
|
|
|
# user-defined code. |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
my ($member_regexp, # Regexp of accessible members. |
771
|
|
|
|
|
|
|
$accessor_regexp, # Regexp of accessible member accessors (x_size, etc.). |
772
|
|
|
|
|
|
|
$user_defined_methods_regexp, # Regexp of accessible user-defined instance methods. |
773
|
|
|
|
|
|
|
$nonpublic_member_regexp, # (For class methods) Regexp of accessors for protected and private members. |
774
|
|
|
|
|
|
|
$private_class_methods_regexp); # (Ditto) Regexp of private class methods. |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
sub accessible_member_regexps($;$); |
777
|
|
|
|
|
|
|
sub accessible_members($;$); |
778
|
|
|
|
|
|
|
sub accessible_accessor_regexps($;$); |
779
|
|
|
|
|
|
|
sub accessible_user_defined_method_regexps($;$); |
780
|
|
|
|
|
|
|
sub class_of($$;$); |
781
|
|
|
|
|
|
|
sub member_index($$); |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
sub set_element_regexps() { # Establish the regexps for |
784
|
61
|
|
|
62
|
|
79
|
my @names; # name substitution. |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
# First for members... |
787
|
61
|
|
|
|
|
190
|
@names = accessible_member_regexps($class); |
788
|
61
|
100
|
|
|
|
201
|
if ( ! @names ) { |
789
|
2
|
|
|
|
|
2
|
undef $member_regexp; |
790
|
|
|
|
|
|
|
} |
791
|
|
|
|
|
|
|
else { |
792
|
59
|
|
|
|
|
327
|
$member_regexp = '(?:\b(?:my|local)\b[^=;()]+)?(' . join('|', sort { length $b <=> length $a } @names) . ')\b'; |
|
245
|
|
|
|
|
471
|
|
793
|
|
|
|
|
|
|
} |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
# Next for accessors (e.g., x_size)... |
796
|
61
|
|
|
|
|
230
|
@names = accessible_accessor_regexps($class); |
797
|
61
|
100
|
|
|
|
207
|
if ( ! @names ) { |
798
|
2
|
|
|
|
|
2
|
undef $accessor_regexp; |
799
|
|
|
|
|
|
|
} |
800
|
|
|
|
|
|
|
else { |
801
|
59
|
|
|
|
|
225
|
$accessor_regexp = '&(' . join('|', sort { length $b <=> length $a } @names) . ')\b(?:\s*\()?'; |
|
1143
|
|
|
|
|
1120
|
|
802
|
|
|
|
|
|
|
} |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
# Next for user-defined instance methods... |
805
|
61
|
|
|
|
|
209
|
@names = accessible_user_defined_method_regexps($class); |
806
|
61
|
100
|
|
|
|
161
|
if ( ! @names ) { |
807
|
47
|
|
|
|
|
86
|
undef $user_defined_methods_regexp; |
808
|
|
|
|
|
|
|
} |
809
|
|
|
|
|
|
|
else { |
810
|
15
|
|
|
|
|
47
|
$user_defined_methods_regexp = '&(' . join('|', sort { length $b <=> length $a } @names) . ')\b(?:\s*\()?'; |
|
40
|
|
|
|
|
72
|
|
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
# Next for protected and private members, and instance methods in class methods... |
814
|
61
|
100
|
|
|
|
381
|
if ( $class->class_methods ) { |
815
|
2
|
|
100
|
|
|
6
|
@names = (map($_->accessor_names($class, $_->name), grep $class->protected($_->name) || $class->private($_->name), $class->members_values), |
|
|
|
100
|
|
|
|
|
816
|
|
|
|
|
|
|
grep($class->private($_) || $class->protected($_), map($_->name, $class->instance_methods))); |
817
|
2
|
100
|
|
|
|
7
|
if ( ! @names ) { |
818
|
1
|
|
|
|
|
2
|
undef $nonpublic_member_regexp; |
819
|
|
|
|
|
|
|
} |
820
|
|
|
|
|
|
|
else { |
821
|
1
|
|
|
|
|
2
|
$nonpublic_member_regexp = join('|', sort { length $b <=> length $a } @names); |
|
0
|
|
|
|
|
0
|
|
822
|
|
|
|
|
|
|
} |
823
|
|
|
|
|
|
|
} |
824
|
|
|
|
|
|
|
else { |
825
|
59
|
|
|
|
|
85
|
undef $nonpublic_member_regexp; |
826
|
|
|
|
|
|
|
} |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
# Finally for private class methods invoked from class and instance methods. |
829
|
61
|
50
|
100
|
|
|
227
|
if ( my @private_class_methods = grep $_->isa('Class::Generate::Class_Method') && |
830
|
|
|
|
|
|
|
$class->private($_->name), $class->user_defined_methods ) { |
831
|
0
|
|
|
|
|
0
|
$private_class_methods_regexp = $class->name . |
832
|
|
|
|
|
|
|
'\s*->\s*(' . |
833
|
|
|
|
|
|
|
join('|', map $_->name, @private_class_methods) . |
834
|
|
|
|
|
|
|
')' . |
835
|
|
|
|
|
|
|
'(\s*\((?:\s*\))?)?'; |
836
|
|
|
|
|
|
|
} |
837
|
|
|
|
|
|
|
else { |
838
|
61
|
|
|
|
|
107
|
undef $private_class_methods_regexp; |
839
|
|
|
|
|
|
|
} |
840
|
|
|
|
|
|
|
} |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
sub substituted($) { # Within a code fragment, replace |
843
|
46
|
|
|
47
|
|
60
|
my $code = $_[0]; # member names and accessors with the |
844
|
|
|
|
|
|
|
# appropriate forms. |
845
|
47
|
100
|
|
|
|
1243
|
$code =~ s/$member_regexp/member_invocation($1, $&)/eg if defined $member_regexp; |
|
92
|
|
|
|
|
211
|
|
846
|
47
|
100
|
|
|
|
773
|
$code =~ s/$accessor_regexp/accessor_invocation($1, $+, $&)/eg if defined $accessor_regexp; |
|
26
|
|
|
|
|
38
|
|
847
|
46
|
100
|
|
|
|
405
|
$code =~ s/$user_defined_methods_regexp/accessor_invocation($1, $1, $&)/eg if defined $user_defined_methods_regexp; |
|
7
|
|
|
|
|
184
|
|
848
|
46
|
50
|
|
|
|
246
|
$code =~ s/$private_class_methods_regexp/nonpublic_method_invocation("'" . $class->name . "'", $1, $2)/eg if defined $private_class_methods_regexp; |
|
0
|
|
|
|
|
0
|
|
849
|
46
|
|
|
|
|
134
|
return $code; |
850
|
|
|
|
|
|
|
} |
851
|
|
|
|
|
|
|
# Perform the actual substitution |
852
|
|
|
|
|
|
|
sub member_invocation($$) { # for member references. |
853
|
91
|
|
|
94
|
|
338
|
my ($member_reference, $match) = @_; |
854
|
91
|
|
|
|
|
86
|
my ($name, $type, $form, $index); |
855
|
91
|
50
|
|
|
|
1590
|
return $member_reference if $match =~ /\A(?:my|local)\b[^=;()]+$member_reference$/s; |
856
|
91
|
|
|
|
|
327
|
$member_reference =~ /^(\W+)(\w+)$/; |
857
|
91
|
|
|
|
|
151
|
$name = $2; |
858
|
91
|
50
|
|
|
|
184
|
return $member_reference if ! defined ($index = member_index($class, $name)); |
859
|
91
|
|
|
|
|
155
|
$type = $1; |
860
|
91
|
|
|
|
|
158
|
$form = $class->instance_var . '->' . $index; |
861
|
91
|
100
|
|
|
|
852
|
return $type eq '$' ? $form : $type . '{' . $form . '}'; |
862
|
|
|
|
|
|
|
} |
863
|
|
|
|
|
|
|
# Perform the actual substitution for |
864
|
|
|
|
|
|
|
sub accessor_invocation($$$) { # accessor and user-defined method references. |
865
|
33
|
|
|
34
|
|
71
|
my ($accessor_name, $element_name, $match) = @_; |
866
|
33
|
|
|
|
|
46
|
my $prefix = $class->instance_var . '->'; |
867
|
33
|
|
|
|
|
150
|
my $c = class_of($element_name, $class); |
868
|
33
|
100
|
100
|
|
|
56
|
if ( ! ($c->protected($element_name) || $c->private($element_name)) ) { |
869
|
2
|
50
|
|
|
|
14
|
return $prefix . $accessor_name . (substr($match, -1) eq '(' ? '(' : ''); |
870
|
|
|
|
|
|
|
} |
871
|
31
|
100
|
100
|
|
|
51
|
if ( $c->private($element_name) || $c->name eq $class->name ) { |
872
|
25
|
100
|
|
|
|
72
|
return "$prefix\$$accessor_name(" if substr($match, -1) eq '('; |
873
|
18
|
|
|
|
|
70
|
return "$prefix\$$accessor_name()"; |
874
|
|
|
|
|
|
|
} |
875
|
6
|
|
|
|
|
21
|
my $form = "&{$prefix" . $class->protected_members_info_index . qq|->{'$accessor_name'}}(|; |
876
|
6
|
|
|
|
|
12
|
$form .= $class->instance_var . ','; |
877
|
6
|
100
|
|
|
|
52
|
return substr($match, -1) eq '(' ? $form : $form . ')'; |
878
|
|
|
|
|
|
|
} |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
sub substituted_in_class_method { |
881
|
2
|
|
|
5
|
|
4
|
my $method = $_[0]; |
882
|
2
|
|
|
|
|
3
|
my (@objs, $code, @private_class_methods); |
883
|
2
|
|
|
|
|
7
|
$code = $method->body; |
884
|
2
|
50
|
100
|
|
|
18
|
if ( defined $nonpublic_member_regexp && (@objs = $method->objects) ) { |
885
|
0
|
|
|
|
|
0
|
my $nonpublic_member_invocation_regexp = '(' . join('|', map(quotemeta($_), @objs)) . ')' . |
886
|
|
|
|
|
|
|
'\s*->\s*(' . $nonpublic_member_regexp . ')' . |
887
|
|
|
|
|
|
|
'(\s*\((?:\s*\))?)?'; |
888
|
0
|
|
|
|
|
0
|
$code =~ s/$nonpublic_member_invocation_regexp/nonpublic_method_invocation($1, $2, $3)/ge; |
|
0
|
|
|
|
|
0
|
|
889
|
|
|
|
|
|
|
} |
890
|
2
|
100
|
|
|
|
6
|
if ( defined $private_class_methods_regexp ) { |
891
|
0
|
|
|
|
|
0
|
$code =~ s/$private_class_methods_regexp/nonpublic_method_invocation("'" . $class->name . "'", $1, $2)/ge; |
|
0
|
|
|
|
|
0
|
|
892
|
|
|
|
|
|
|
} |
893
|
2
|
|
|
|
|
19
|
return $code; |
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
sub nonpublic_method_invocation { # Perform the actual |
897
|
0
|
|
|
0
|
|
0
|
my ($object, $nonpublic_member, $paren_matter) = @_; # substitution for |
898
|
0
|
|
|
|
|
0
|
my $form = '&$' . $nonpublic_member . '(' . $object; # nonpublic method and |
899
|
0
|
0
|
|
|
|
0
|
if ( defined $paren_matter ) { # member references. |
900
|
0
|
0
|
|
|
|
0
|
if ( index($paren_matter, ')') != -1 ) { |
901
|
0
|
|
|
|
|
0
|
$form .= ')'; |
902
|
|
|
|
|
|
|
} |
903
|
|
|
|
|
|
|
else { |
904
|
0
|
|
|
|
|
0
|
$form .= ', '; |
905
|
|
|
|
|
|
|
} |
906
|
|
|
|
|
|
|
} |
907
|
|
|
|
|
|
|
else { |
908
|
0
|
|
|
|
|
0
|
$form .= ')'; |
909
|
|
|
|
|
|
|
} |
910
|
0
|
|
|
|
|
0
|
return $form; |
911
|
|
|
|
|
|
|
} |
912
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
sub member_index($$) { |
914
|
103
|
|
|
103
|
|
104
|
my ($class, $member_name) = @_; |
915
|
103
|
100
|
|
|
|
171
|
return $class->index($member_name) if defined $class->members($member_name); |
916
|
12
|
|
|
|
|
236
|
for my $parent ( grep ref $_, $class->parents ) { |
917
|
12
|
|
|
|
|
23
|
my $index = member_index($parent, $member_name); |
918
|
12
|
50
|
|
|
|
39
|
return $index if defined $index; |
919
|
|
|
|
|
|
|
} |
920
|
0
|
|
|
|
|
0
|
return undef; |
921
|
|
|
|
|
|
|
} |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
sub accessible_member_regexps($;$) { |
924
|
76
|
|
|
76
|
|
122
|
my ($class, $disallow_private_members) = @_; |
925
|
76
|
|
|
|
|
82
|
my @members; |
926
|
76
|
100
|
|
|
|
156
|
if ( $disallow_private_members ) { |
927
|
15
|
|
|
|
|
34
|
@members = grep ! $class->private($_->name), $class->members_values; |
928
|
|
|
|
|
|
|
} |
929
|
|
|
|
|
|
|
else { |
930
|
61
|
|
|
|
|
234
|
@members = $class->members_values; |
931
|
|
|
|
|
|
|
} |
932
|
76
|
|
|
|
|
331
|
return (map($_->method_regexp($class), @members), |
933
|
|
|
|
|
|
|
map(accessible_member_regexps($_, 1), grep(ref $_, $class->parents))); |
934
|
|
|
|
|
|
|
} |
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
sub accessible_members($;$) { |
937
|
76
|
|
|
76
|
|
126
|
my ($class, $disallow_private_members) = @_; |
938
|
76
|
|
|
|
|
91
|
my @members; |
939
|
76
|
100
|
|
|
|
154
|
if ( $disallow_private_members ) { |
940
|
15
|
|
|
|
|
45
|
@members = grep ! $class->private($_->name), $class->members_values; |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
else { |
943
|
61
|
|
|
|
|
140
|
@members = $class->members_values; |
944
|
|
|
|
|
|
|
} |
945
|
76
|
|
|
|
|
242
|
return (@members, map(accessible_members($_, 1), grep(ref $_, $class->parents))); |
946
|
|
|
|
|
|
|
} |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
sub accessible_accessor_regexps($;$) { |
949
|
76
|
|
|
76
|
|
194
|
my ($class, $disallow_private_members) = @_; |
950
|
76
|
|
|
|
|
99
|
my ($member_name, @accessor_names); |
951
|
76
|
|
|
|
|
221
|
for my $member ( $class->members_values ) { |
952
|
166
|
100
|
100
|
|
|
401
|
next if $class->private($member_name = $member->name) && $disallow_private_members; |
953
|
165
|
|
|
|
|
486
|
for my $accessor_name ( grep $class->include_method($_), $member->accessor_names($class, $member_name) ) { |
954
|
466
|
|
|
|
|
3489
|
$accessor_name =~ s/$member_name/($&)/; |
955
|
466
|
|
|
|
|
1003
|
push @accessor_names, $accessor_name; |
956
|
|
|
|
|
|
|
} |
957
|
|
|
|
|
|
|
} |
958
|
76
|
|
|
|
|
282
|
return (@accessor_names, map(accessible_accessor_regexps($_, 1), grep(ref $_, $class->parents))); |
959
|
|
|
|
|
|
|
} |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
sub accessible_user_defined_method_regexps($;$) { |
962
|
76
|
|
|
76
|
|
194
|
my ($class, $disallow_private_methods) = @_; |
963
|
76
|
100
|
|
|
|
461
|
return (($disallow_private_methods ? grep ! $class->private($_), $class->user_defined_methods_keys : $class->user_defined_methods_keys), |
964
|
|
|
|
|
|
|
map(accessible_user_defined_method_regexps($_, 1), grep(ref $_, $class->parents))); |
965
|
|
|
|
|
|
|
} |
966
|
|
|
|
|
|
|
# Given element E and class C, return C if E is an |
967
|
|
|
|
|
|
|
sub class_of($$;$) { # element of C; if not, search parents recursively. |
968
|
39
|
|
|
39
|
|
41
|
my ($element_name, $class, $disallow_private_members) = @_; |
969
|
39
|
100
|
100
|
|
|
56
|
return $class if (defined $class->members($element_name) || defined $class->user_defined_methods($element_name)) && (! $disallow_private_members || ! $class->private($element_name)); |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
970
|
6
|
|
|
|
|
15
|
for my $parent ( grep ref $_, $class->parents ) { |
971
|
6
|
|
|
|
|
145
|
my $c = class_of($element_name, $parent, 1); |
972
|
6
|
50
|
|
|
|
19
|
return $c if defined $c; |
973
|
|
|
|
|
|
|
} |
974
|
0
|
|
|
|
|
0
|
return undef; |
975
|
|
|
|
|
|
|
} |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
package Class::Generate::Code_Checker; # This package encapsulates |
978
|
14
|
|
|
15
|
|
232
|
use strict; # checking for warnings and |
|
14
|
|
|
|
|
34
|
|
|
14
|
|
|
|
|
364
|
|
979
|
14
|
|
|
15
|
|
179
|
use Carp; # errors in user-defined code. |
|
16
|
|
|
|
|
33
|
|
|
16
|
|
|
|
|
10481
|
|
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
my $package_decl; |
982
|
|
|
|
|
|
|
my $member_error_message = '%s, member "%s": In "%s" code: %s'; |
983
|
|
|
|
|
|
|
my $method_error_message = '%s, method "%s": %s'; |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
sub create_code_checking_package($); |
986
|
|
|
|
|
|
|
sub fragment_as_sub($$\@;\@); |
987
|
|
|
|
|
|
|
sub collect_code_problems($$$$@); |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
# Check each user-defined code fragment in $class for errors. This includes |
990
|
|
|
|
|
|
|
# pre, post, and assert code, as well as user-defined methods. Set |
991
|
|
|
|
|
|
|
# $errors_found according to whether errors (not warnings) were found. |
992
|
|
|
|
|
|
|
sub check_user_defined_code($$$$) { |
993
|
61
|
|
|
61
|
|
124
|
my ($class, $class_name_label, $warnings, $errors) = @_; |
994
|
61
|
|
|
|
|
97
|
my ($code, $instance_var, @valid_variables, @class_vars, $w, $e, @members, $problems_in_pre, %seen); |
995
|
61
|
|
|
|
|
188
|
create_code_checking_package $class; |
996
|
61
|
100
|
|
|
|
254
|
@valid_variables = map { $seen{$_->name} ? () : do { $seen{$_->name} = 1; $_->as_var } } |
|
298
|
|
|
|
|
446
|
|
|
165
|
|
|
|
|
266
|
|
|
165
|
|
|
|
|
488
|
|
997
|
|
|
|
|
|
|
((@members = $class->members_values), |
998
|
|
|
|
|
|
|
Class::Generate::Member_Names::accessible_members($class)); |
999
|
61
|
|
|
|
|
302
|
@class_vars = $class->class_vars; |
1000
|
61
|
|
|
|
|
264
|
$instance_var = $class->instance_var; |
1001
|
61
|
|
|
|
|
128
|
@$warnings = (); |
1002
|
61
|
|
|
|
|
145
|
undef $$errors; |
1003
|
61
|
|
|
|
|
168
|
for my $member ( $class->constructor, @members ) { |
1004
|
194
|
50
|
|
|
|
502
|
if ( defined ($code = $member->pre) ) { |
1005
|
0
|
|
|
|
|
0
|
$code = fragment_as_sub $code, $instance_var, @class_vars, @valid_variables; |
1006
|
0
|
|
|
|
|
0
|
collect_code_problems $code, |
1007
|
|
|
|
|
|
|
$warnings, $errors, |
1008
|
|
|
|
|
|
|
$member_error_message, $class_name_label, $member->name, 'pre'; |
1009
|
0
|
|
0
|
|
|
0
|
$problems_in_pre = @$warnings || $$errors; |
1010
|
|
|
|
|
|
|
} |
1011
|
|
|
|
|
|
|
# Because post shares pre's scope, check post with pre prepended. |
1012
|
|
|
|
|
|
|
# Strip newlines in pre to preserve line numbers in post. |
1013
|
194
|
100
|
|
|
|
458
|
if ( defined ($code = $member->post) ) { |
1014
|
13
|
|
|
|
|
38
|
my $pre = $member->pre; |
1015
|
13
|
50
|
33
|
|
|
52
|
if ( defined $pre && ! $problems_in_pre ) { # Don't report errors |
1016
|
0
|
|
|
|
|
0
|
$pre =~ s/\n+/ /g; # in pre again. |
1017
|
0
|
|
|
|
|
0
|
$code = $pre . $code; |
1018
|
|
|
|
|
|
|
} |
1019
|
13
|
|
|
|
|
85
|
$code = fragment_as_sub $code, $instance_var, @class_vars, @valid_variables; |
1020
|
13
|
|
|
|
|
53
|
collect_code_problems $code, |
1021
|
|
|
|
|
|
|
$warnings, $errors, |
1022
|
|
|
|
|
|
|
$member_error_message, $class_name_label, $member->name, 'post'; |
1023
|
|
|
|
|
|
|
} |
1024
|
194
|
100
|
|
|
|
452
|
if ( defined ($code = $member->assert) ) { |
1025
|
5
|
|
|
|
|
26
|
$code = fragment_as_sub "unless($code){die}" , $instance_var, @class_vars, @valid_variables; |
1026
|
5
|
|
|
|
|
16
|
collect_code_problems $code, |
1027
|
|
|
|
|
|
|
$warnings, $errors, |
1028
|
|
|
|
|
|
|
$member_error_message, $class_name_label, $member->name, 'assert'; |
1029
|
|
|
|
|
|
|
} |
1030
|
|
|
|
|
|
|
} |
1031
|
61
|
|
|
|
|
200
|
for my $method ( $class->user_defined_methods_values ) { |
1032
|
28
|
100
|
|
|
|
141
|
if ( $method->isa('Class::Generate::Class_Method') ) { |
1033
|
2
|
|
|
|
|
17
|
$code = fragment_as_sub $method->body, $class->class_var, @class_vars; |
1034
|
|
|
|
|
|
|
} |
1035
|
|
|
|
|
|
|
else { |
1036
|
26
|
|
|
|
|
53
|
$code = fragment_as_sub $method->body, $instance_var, @class_vars, @valid_variables; |
1037
|
|
|
|
|
|
|
} |
1038
|
28
|
|
|
|
|
86
|
collect_code_problems $code, $warnings, $errors, $method_error_message, $class_name_label, $method->name; |
1039
|
|
|
|
|
|
|
} |
1040
|
|
|
|
|
|
|
} |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
sub create_code_checking_package($) { # Each class with user-defined code gets |
1043
|
61
|
|
|
61
|
|
89
|
my $class = $_[0]; # its own package in which that code is |
1044
|
|
|
|
|
|
|
# evaluated. Create said package. |
1045
|
61
|
|
|
|
|
240
|
$package_decl = 'package ' . __PACKAGE__ . '::check::' . $class->name . ";"; |
1046
|
61
|
50
|
|
|
|
273
|
$package_decl .= 'use strict;' if $class->strict; |
1047
|
61
|
|
|
|
|
101
|
my $packages = ''; |
1048
|
61
|
50
|
|
|
|
185
|
if ( $class->check_params ) { |
1049
|
61
|
|
|
|
|
99
|
$packages .= 'use Carp;'; |
1050
|
61
|
|
|
|
|
272
|
$packages .= join(';', $class->warnings_pragmas); |
1051
|
|
|
|
|
|
|
} |
1052
|
61
|
|
|
|
|
321
|
$packages .= join('', map('use ' . $_ . ';', $class->use_packages)); |
1053
|
61
|
100
|
|
|
|
158
|
$packages .= 'use vars qw(@ISA);' if $class->parents; |
1054
|
13
|
|
|
13
|
|
146
|
eval $package_decl . $packages; |
|
13
|
|
|
13
|
|
17
|
|
|
13
|
|
|
13
|
|
500
|
|
|
13
|
|
|
12
|
|
85
|
|
|
13
|
|
|
12
|
|
17
|
|
|
13
|
|
|
12
|
|
1002
|
|
|
13
|
|
|
12
|
|
439
|
|
|
13
|
|
|
10
|
|
23
|
|
|
13
|
|
|
9
|
|
298
|
|
|
12
|
|
|
8
|
|
103
|
|
|
12
|
|
|
8
|
|
26
|
|
|
12
|
|
|
8
|
|
562
|
|
|
12
|
|
|
7
|
|
116
|
|
|
12
|
|
|
7
|
|
21
|
|
|
12
|
|
|
7
|
|
701
|
|
|
12
|
|
|
17
|
|
89
|
|
|
12
|
|
|
3
|
|
34
|
|
|
12
|
|
|
8
|
|
337
|
|
|
12
|
|
|
|
|
90
|
|
|
12
|
|
|
|
|
23
|
|
|
12
|
|
|
|
|
547
|
|
|
10
|
|
|
|
|
82
|
|
|
10
|
|
|
|
|
15
|
|
|
10
|
|
|
|
|
500
|
|
|
9
|
|
|
|
|
64
|
|
|
9
|
|
|
|
|
13
|
|
|
9
|
|
|
|
|
202
|
|
|
8
|
|
|
|
|
87
|
|
|
8
|
|
|
|
|
100
|
|
|
8
|
|
|
|
|
249
|
|
|
8
|
|
|
|
|
113
|
|
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
451
|
|
|
8
|
|
|
|
|
73
|
|
|
8
|
|
|
|
|
17
|
|
|
8
|
|
|
|
|
171
|
|
|
7
|
|
|
|
|
39
|
|
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
568
|
|
|
7
|
|
|
|
|
39
|
|
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
379
|
|
|
7
|
|
|
|
|
32
|
|
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
269
|
|
|
61
|
|
|
|
|
5141
|
|
|
17
|
|
|
|
|
471
|
|
|
17
|
|
|
|
|
138
|
|
|
6
|
|
|
|
|
20
|
|
|
5
|
|
|
|
|
23
|
|
|
11
|
|
|
|
|
71
|
|
|
9
|
|
|
|
|
26
|
|
|
5
|
|
|
|
|
70
|
|
|
4
|
|
|
|
|
55
|
|
|
4
|
|
|
|
|
63
|
|
1055
|
|
|
|
|
|
|
} |
1056
|
|
|
|
|
|
|
# Evaluate a code fragment, passing on |
1057
|
|
|
|
|
|
|
sub collect_code_problems($$$$@) { # warnings and errors. |
1058
|
46
|
|
|
46
|
|
93
|
my ($code_form, $warnings, $errors, $error_message, @params) = @_; |
1059
|
46
|
|
|
|
|
44
|
my @warnings; |
1060
|
46
|
|
|
0
|
|
765
|
local $SIG{__WARN__} = sub { push @warnings, $_[0] }; |
|
0
|
|
|
|
|
0
|
|
1061
|
46
|
|
|
|
|
120
|
local $SIG{__DIE__}; |
1062
|
10
|
|
|
10
|
|
85
|
eval $package_decl . $code_form; |
|
9
|
|
|
10
|
|
11
|
|
|
9
|
|
|
5
|
|
646
|
|
|
9
|
|
|
|
|
45
|
|
|
9
|
|
|
|
|
10
|
|
|
9
|
|
|
|
|
519
|
|
|
46
|
|
|
|
|
2871
|
|
|
6
|
|
|
|
|
17
|
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
8
|
|
1063
|
46
|
|
|
|
|
174
|
push @$warnings, map(filtered_message($error_message, $_, @params), @warnings); |
1064
|
46
|
100
|
|
|
|
361
|
$$errors .= filtered_message($error_message, $@, @params) if $@; |
1065
|
|
|
|
|
|
|
} |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
sub filtered_message { # Clean up errors and messages |
1068
|
0
|
|
|
1
|
|
0
|
my ($message, $error, @params) = @_; # a little by removing the |
1069
|
0
|
|
|
|
|
0
|
$error =~ s/\(eval \d+\) //g; # "(eval N)" forms that perl |
1070
|
0
|
|
|
|
|
0
|
return sprintf($message, @params, $error); # inserts. |
1071
|
|
|
|
|
|
|
} |
1072
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
sub fragment_as_sub($$\@;\@) { |
1074
|
46
|
|
|
46
|
|
87
|
my ($code, $id_var, $class_vars, $valid_vars) = @_; |
1075
|
46
|
|
|
|
|
45
|
my $form; |
1076
|
46
|
|
|
|
|
84
|
$form = "sub{my $id_var;"; |
1077
|
46
|
100
|
|
|
|
113
|
if ( $#$class_vars >= 0 ) { |
1078
|
4
|
50
|
|
|
|
14
|
$form .= 'my(' . join(',', map((ref $_ ? keys %$_ : $_), @$class_vars)) . ');'; |
1079
|
|
|
|
|
|
|
} |
1080
|
46
|
100
|
100
|
|
|
209
|
if ( $valid_vars && $#$valid_vars >= 0 ) { |
1081
|
42
|
|
|
|
|
117
|
$form .= 'my(' . join(',', @$valid_vars) . ');'; |
1082
|
|
|
|
|
|
|
} |
1083
|
46
|
|
|
|
|
146
|
$form .= '{' . $code . '}};'; |
1084
|
|
|
|
|
|
|
} |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
package Class::Generate::Array; # Given a string or an ARRAY, return an |
1087
|
16
|
|
|
15
|
|
289
|
use strict; # object that is either the ARRAY or |
|
15
|
|
|
|
|
33
|
|
|
15
|
|
|
|
|
393
|
|
1088
|
15
|
|
|
14
|
|
329
|
use Carp; # the string made into an ARRAY by |
|
14
|
|
|
|
|
29
|
|
|
14
|
|
|
|
|
2357
|
|
1089
|
|
|
|
|
|
|
# splitting the string on white space. |
1090
|
|
|
|
|
|
|
sub new { |
1091
|
63
|
|
|
63
|
|
126
|
my $class = shift; |
1092
|
63
|
|
|
|
|
78
|
my $self; |
1093
|
63
|
100
|
|
|
|
288
|
if ( ! ref $_[0] ) { |
|
|
50
|
|
|
|
|
|
1094
|
60
|
|
|
|
|
249
|
$self = [ split /\s+/, $_[0] ]; |
1095
|
|
|
|
|
|
|
} |
1096
|
|
|
|
|
|
|
elsif ( UNIVERSAL::isa($_[0], 'ARRAY') ) { |
1097
|
3
|
|
|
|
|
7
|
$self = $_[0]; |
1098
|
|
|
|
|
|
|
} |
1099
|
|
|
|
|
|
|
else { |
1100
|
0
|
|
|
|
|
0
|
croak 'Expected string or array reference'; |
1101
|
|
|
|
|
|
|
} |
1102
|
63
|
|
|
|
|
183
|
bless $self, $class; |
1103
|
63
|
|
|
|
|
147
|
return $self; |
1104
|
|
|
|
|
|
|
} |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
sub values { |
1107
|
125
|
|
|
125
|
|
161
|
my $self = shift; |
1108
|
125
|
|
|
|
|
599
|
return @$self; |
1109
|
|
|
|
|
|
|
} |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
package Class::Generate::Hash; # Given a string or a HASH and a key |
1112
|
14
|
|
|
14
|
|
170
|
use strict; # name, return an object that is either |
|
14
|
|
|
|
|
27
|
|
|
14
|
|
|
|
|
297
|
|
1113
|
14
|
|
|
16
|
|
150
|
use Carp; # the HASH or a HASH of the form |
|
15
|
|
|
|
|
39
|
|
|
15
|
|
|
|
|
1603
|
|
1114
|
|
|
|
|
|
|
# (key => string). Also, if the object |
1115
|
|
|
|
|
|
|
sub new { # is a HASH, it *must* contain the key. |
1116
|
162
|
|
|
162
|
|
194
|
my $class = shift; |
1117
|
162
|
|
|
|
|
129
|
my $self; |
1118
|
162
|
|
|
|
|
193
|
my ($value, $key) = @_; |
1119
|
162
|
100
|
|
|
|
314
|
if ( ! ref $value ) { |
1120
|
104
|
|
|
|
|
211
|
$self = { $key => $value }; |
1121
|
|
|
|
|
|
|
} |
1122
|
|
|
|
|
|
|
else { |
1123
|
58
|
50
|
|
|
|
183
|
croak 'Expected string or hash reference' unless UNIVERSAL::isa($value, 'HASH'); |
1124
|
58
|
100
|
|
|
|
222
|
croak qq|Missing "$key"| unless exists $value->{$key}; |
1125
|
57
|
|
|
|
|
80
|
$self = $value; |
1126
|
|
|
|
|
|
|
} |
1127
|
161
|
|
|
|
|
311
|
bless $self, $class; |
1128
|
161
|
|
|
|
|
624
|
return $self; |
1129
|
|
|
|
|
|
|
} |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
package Class::Generate::Support; # Miscellaneous support routines. |
1132
|
15
|
|
|
15
|
|
310
|
no strict; # Definitely NOT strict! |
|
14
|
|
|
|
|
34
|
|
|
14
|
|
|
|
|
2839
|
|
1133
|
|
|
|
|
|
|
# Return the superclass of $class that |
1134
|
|
|
|
|
|
|
sub class_containing_method { # contains the method that the form |
1135
|
46
|
|
|
46
|
|
66
|
my ($method, $class) = @_; # (new $class)->$method would invoke. |
1136
|
46
|
|
|
|
|
129
|
for my $parent ( $class->parents ) {# Return undef if no such class exists. |
1137
|
15
|
50
|
|
|
|
64
|
local *stab = eval ('*' . (ref $parent ? $parent->name : $parent) . '::'); |
1138
|
15
|
50
|
33
|
|
|
332
|
if ( exists $stab{$method} && |
1139
|
15
|
|
|
|
|
58
|
do { local *method_entry = $stab{$method}; defined &method_entry } ) { |
|
15
|
|
|
|
|
75
|
|
1140
|
15
|
|
|
|
|
34
|
return $parent; |
1141
|
|
|
|
|
|
|
} |
1142
|
0
|
|
|
|
|
0
|
return class_containing_method($method, $parent); |
1143
|
|
|
|
|
|
|
} |
1144
|
31
|
|
|
|
|
73
|
return undef; |
1145
|
|
|
|
|
|
|
} |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
my %map = ('@' => 'ARRAY', '%' => 'HASH'); |
1148
|
|
|
|
|
|
|
sub verify_value($$) { # Die if a given value (ref or string) |
1149
|
1
|
|
|
1
|
|
2
|
my ($value, $type) = @_; # is not the specified type. |
1150
|
|
|
|
|
|
|
# The following code is not wrong, but it could be smarter. |
1151
|
1
|
50
|
|
|
|
3
|
if ( $type =~ /^\w/ ) { |
1152
|
0
|
|
|
|
|
0
|
$map{$type} = $type; |
1153
|
|
|
|
|
|
|
} |
1154
|
|
|
|
|
|
|
else { |
1155
|
1
|
|
|
|
|
2
|
$type = substr $type, 0, 1; |
1156
|
|
|
|
|
|
|
} |
1157
|
1
|
50
|
|
|
|
3
|
return if $type eq '$'; |
1158
|
0
|
|
|
0
|
|
0
|
local $SIG{__WARN__} = sub {}; |
|
0
|
|
|
|
|
0
|
|
1159
|
0
|
|
|
|
|
0
|
my $result; |
1160
|
0
|
0
|
|
|
|
0
|
$result = ref $value ? $value : eval $value; |
1161
|
0
|
0
|
|
|
|
0
|
die "Wrong type" if ! UNIVERSAL::isa($result, $map{$type}); |
1162
|
|
|
|
|
|
|
} |
1163
|
|
|
|
|
|
|
|
1164
|
14
|
|
|
14
|
|
331
|
use strict; |
|
14
|
|
|
|
|
36
|
|
|
14
|
|
|
|
|
2180
|
|
1165
|
|
|
|
|
|
|
sub comment_form { # Given arbitrary text, return a form that |
1166
|
1
|
|
|
1
|
|
2
|
my $comment = $_[0]; # is a valid Perl comment of that text. |
1167
|
1
|
|
|
|
|
6
|
$comment =~ s/^/# /mg; |
1168
|
1
|
50
|
|
|
|
7
|
$comment .= "\n" if substr($comment, -1, 1) ne "\n"; |
1169
|
1
|
|
|
|
|
4
|
return $comment; |
1170
|
|
|
|
|
|
|
} |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
sub my_decl_form { # Given a non-empty set of variable names, |
1173
|
8
|
|
|
8
|
|
16
|
my @vars = @_; # return a form declaring them as "my" variables. |
1174
|
8
|
100
|
|
|
|
63
|
return 'my ' . ($#vars == 0 ? $vars[0] : '(' . join(', ', @vars) . ')') . ";\n"; |
1175
|
|
|
|
|
|
|
} |
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
package Class::Generate::Member; # A virtual class describing class |
1178
|
14
|
|
|
14
|
|
228
|
use strict; # members. |
|
14
|
|
|
|
|
27
|
|
|
14
|
|
|
|
|
35963
|
|
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
sub new { |
1181
|
195
|
|
|
195
|
|
240
|
my $class = shift; |
1182
|
195
|
|
|
|
|
643
|
my $self = { name => $_[0], @_[1..$#_] }; |
1183
|
195
|
|
|
|
|
419
|
bless $self, $class; |
1184
|
195
|
|
|
|
|
325
|
return $self; |
1185
|
|
|
|
|
|
|
} |
1186
|
|
|
|
|
|
|
sub name { |
1187
|
3120
|
|
|
3120
|
|
2459
|
my $self = shift; |
1188
|
3120
|
|
|
|
|
7255
|
return $self->{'name'}; |
1189
|
|
|
|
|
|
|
} |
1190
|
|
|
|
|
|
|
sub default { |
1191
|
228
|
|
|
228
|
|
215
|
my $self = shift; |
1192
|
228
|
100
|
|
|
|
849
|
return $self->{'default'} if $#_ == -1; |
1193
|
1
|
|
|
|
|
4
|
$self->{'default'} = $_[0]; |
1194
|
|
|
|
|
|
|
} |
1195
|
|
|
|
|
|
|
sub base { |
1196
|
885
|
|
|
885
|
|
733
|
my $self = shift; |
1197
|
885
|
50
|
|
|
|
3289
|
return $self->{'base'} if $#_ == -1; |
1198
|
0
|
|
|
|
|
0
|
$self->{'base'} = $_[0]; |
1199
|
|
|
|
|
|
|
} |
1200
|
|
|
|
|
|
|
sub assert { |
1201
|
556
|
|
|
556
|
|
579
|
my $self = shift; |
1202
|
556
|
100
|
|
|
|
2013
|
return $self->{'assert'} if $#_ == -1; |
1203
|
3
|
|
|
|
|
24
|
$self->{'assert'} = $_[0]; |
1204
|
|
|
|
|
|
|
} |
1205
|
|
|
|
|
|
|
sub post { |
1206
|
497
|
|
|
497
|
|
582
|
my $self = shift; |
1207
|
497
|
100
|
|
|
|
1668
|
return $self->{'post'} if $#_ == -1; |
1208
|
4
|
|
|
|
|
14
|
$self->{'post'} = possibly_append_semicolon_to($_[0]); |
1209
|
|
|
|
|
|
|
} |
1210
|
|
|
|
|
|
|
sub pre { |
1211
|
420
|
|
|
420
|
|
410
|
my $self = shift; |
1212
|
420
|
50
|
|
|
|
1427
|
return $self->{'pre'} if $#_ == -1; |
1213
|
0
|
|
|
|
|
0
|
$self->{'pre'} = possibly_append_semicolon_to($_[0]); |
1214
|
|
|
|
|
|
|
} |
1215
|
|
|
|
|
|
|
sub possibly_append_semicolon_to { # If user omits a trailing semicolon |
1216
|
4
|
|
|
4
|
|
6
|
my $code = $_[0]; # (or doesn't use braces), add one. |
1217
|
4
|
50
|
|
|
|
25
|
if ( $code !~ /[;\}]\s*\Z/s ) { |
1218
|
0
|
|
|
|
|
0
|
$code =~ s/\s*\Z/;$&/s; |
1219
|
|
|
|
|
|
|
} |
1220
|
4
|
|
|
|
|
32
|
return $code; |
1221
|
|
|
|
|
|
|
} |
1222
|
|
|
|
|
|
|
sub comment { |
1223
|
132
|
|
|
132
|
|
167
|
my $self = shift; |
1224
|
132
|
|
|
|
|
346
|
return $self->{'comment'}; |
1225
|
|
|
|
|
|
|
} |
1226
|
|
|
|
|
|
|
sub key { |
1227
|
134
|
|
|
134
|
|
133
|
my $self = shift; |
1228
|
134
|
100
|
|
|
|
517
|
return $self->{'key'} if $#_ == -1; |
1229
|
3
|
|
|
|
|
13
|
$self->{'key'} = $_[0]; |
1230
|
|
|
|
|
|
|
} |
1231
|
|
|
|
|
|
|
sub nocopy { |
1232
|
98
|
|
|
98
|
|
104
|
my $self = shift; |
1233
|
98
|
100
|
|
|
|
436
|
return $self->{'nocopy'} if $#_ == -1; |
1234
|
2
|
|
|
|
|
11
|
$self->{'nocopy'} = $_[0]; |
1235
|
|
|
|
|
|
|
} |
1236
|
|
|
|
|
|
|
sub assertion { # Return a form that croaks if |
1237
|
7
|
|
|
7
|
|
12
|
my $self = shift; # the member's assertion fails. |
1238
|
7
|
|
|
|
|
10
|
my $class = $_[0]; |
1239
|
7
|
|
|
|
|
20
|
my $assertion = $self->{'assert'}; |
1240
|
7
|
50
|
|
|
|
18
|
return undef if ! defined $assertion; |
1241
|
7
|
|
|
|
|
11
|
my $quoted_form = $assertion; |
1242
|
7
|
|
|
|
|
14
|
$quoted_form =~ s/'/\\'/g; |
1243
|
7
|
|
|
|
|
18
|
$assertion = Class::Generate::Member_Names::substituted($assertion); |
1244
|
7
|
|
|
|
|
172
|
return qq|unless ( $assertion ) { croak '| . $self->name_form($class) . qq|Failed assertion: $quoted_form' }|; |
1245
|
|
|
|
|
|
|
} |
1246
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
sub param_message { # Encapsulate the messages for |
1248
|
84
|
|
|
84
|
|
94
|
my $self = shift; # incorrect parameters. |
1249
|
84
|
|
|
|
|
86
|
my $class = $_[0]; |
1250
|
84
|
|
|
|
|
129
|
my $name = $self->name; |
1251
|
84
|
|
|
|
|
160
|
my $prefix_form = q|croak '| . $class->name . '::new' . ': '; |
1252
|
84
|
100
|
66
|
|
|
190
|
$class->required($name) && ! $self->default and do { |
1253
|
31
|
100
|
|
|
|
99
|
return $prefix_form . qq|Missing or invalid value for $name'| if $self->can_be_invalid; |
1254
|
25
|
|
|
|
|
104
|
return $prefix_form . qq|Missing value for required member $name'|; |
1255
|
|
|
|
|
|
|
}; |
1256
|
53
|
50
|
|
|
|
91
|
$self->can_be_invalid and do { |
1257
|
53
|
|
|
|
|
313
|
return $prefix_form . qq|Invalid value for $name'|; |
1258
|
|
|
|
|
|
|
}; |
1259
|
|
|
|
|
|
|
} |
1260
|
|
|
|
|
|
|
|
1261
|
|
|
|
|
|
|
sub param_test { # Return a form that dies if a constructor |
1262
|
84
|
|
|
84
|
|
88
|
my $self = shift; # parameter is not correctly passed. |
1263
|
84
|
|
|
|
|
86
|
my $class = $_[0]; |
1264
|
84
|
|
|
|
|
176
|
my $name = $self->name; |
1265
|
84
|
|
|
|
|
170
|
my $param = $class->constructor->style->ref($name); |
1266
|
84
|
|
|
|
|
170
|
my $exists = $class->constructor->style->existence_test($name) . ' ' . $param; |
1267
|
|
|
|
|
|
|
|
1268
|
84
|
|
|
|
|
114
|
my $form = ''; |
1269
|
84
|
100
|
66
|
|
|
160
|
if ( $class->required($name) && ! $self->default ) { |
|
|
50
|
|
|
|
|
|
1270
|
31
|
|
|
|
|
92
|
$form .= $self->param_message($class) . ' unless ' . $exists; |
1271
|
31
|
100
|
|
|
|
63
|
$form .= ' && ' . $self->valid_value_form($param) if $self->can_be_invalid; |
1272
|
|
|
|
|
|
|
} |
1273
|
|
|
|
|
|
|
elsif ( $self->can_be_invalid ) { |
1274
|
53
|
|
|
|
|
162
|
$form .= $self->param_message($class) . ' unless ! ' . $exists . ' || ' . $self->valid_value_form($param); |
1275
|
|
|
|
|
|
|
} |
1276
|
84
|
|
|
|
|
1245
|
return $form . ';'; |
1277
|
|
|
|
|
|
|
} |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
sub form { # Return a form for a member and all |
1280
|
132
|
|
|
132
|
|
169
|
my $self = shift; # its relevant associated accessors. |
1281
|
132
|
|
|
|
|
147
|
my $class = $_[0]; |
1282
|
132
|
|
|
|
|
126
|
my ($element, $exists, $lvalue, $values, $form, $body, $member_name); |
1283
|
132
|
|
|
|
|
217
|
$element = $class->instance_var . '->' . $class->index($member_name = $self->name); |
1284
|
132
|
|
|
|
|
345
|
$exists = $class->existence_test . ' ' . $element; |
1285
|
132
|
100
|
|
|
|
697
|
$lvalue = $self->lvalue('$_[0]') if $self->can('lvalue'); |
1286
|
132
|
100
|
|
|
|
571
|
$values = $self->values('$_[0]') if $self->can('values'); |
1287
|
|
|
|
|
|
|
|
1288
|
132
|
|
|
|
|
193
|
$form = ''; |
1289
|
132
|
50
|
|
|
|
383
|
$form .= Class::Generate::Support::comment_form($self->comment) if defined $self->comment; |
1290
|
|
|
|
|
|
|
|
1291
|
132
|
50
|
|
|
|
291
|
if ( $class->include_method($member_name) ) { |
1292
|
132
|
|
|
|
|
146
|
$body = ''; |
1293
|
132
|
|
|
|
|
449
|
for my $param_form ( $self->member_forms($class) ) { |
1294
|
299
|
|
|
|
|
926
|
$body .= $self->$param_form($class, $element, $exists, $lvalue, $values); |
1295
|
|
|
|
|
|
|
} |
1296
|
132
|
50
|
|
|
|
306
|
$body .= ' ' . $self->param_count_error_form($class) . ";\n" if $class->check_params; |
1297
|
132
|
|
|
|
|
417
|
$form .= $class->sub_form($member_name, $member_name, $body); |
1298
|
|
|
|
|
|
|
} |
1299
|
132
|
|
|
|
|
404
|
for my $a ( grep $_ ne $member_name, $self->accessor_names($class, $member_name) ) { |
1300
|
268
|
100
|
|
|
|
4479
|
$a =~ s/^([a-z]+)_$member_name$/$1_form/ || $a =~ s/^${member_name}_([a-z]+)$/$1_form/; |
1301
|
268
|
|
|
|
|
993
|
$form .= $self->$a($class, $element, $member_name, $exists); |
1302
|
|
|
|
|
|
|
} |
1303
|
132
|
|
|
|
|
633
|
return $form; |
1304
|
|
|
|
|
|
|
} |
1305
|
|
|
|
|
|
|
|
1306
|
|
|
|
|
|
|
sub invalid_value_assignment_message { # Return a form that dies, reporting |
1307
|
78
|
|
|
78
|
|
71
|
my $self = shift; # a parameter that's not of the |
1308
|
78
|
|
|
|
|
77
|
my $class = $_[0]; # correct type for its element. |
1309
|
78
|
|
|
|
|
174
|
return 'croak \'' . $self->name_form($class) . 'Invalid parameter value (expected ' . $self->expected_type_form . ')\''; |
1310
|
|
|
|
|
|
|
} |
1311
|
|
|
|
|
|
|
sub valid_value_test_form { # Return a form that dies unless |
1312
|
63
|
|
|
63
|
|
77
|
my $self = shift; # a value is of the correct type |
1313
|
63
|
|
|
|
|
59
|
my $class = shift; # for the member. |
1314
|
63
|
|
|
|
|
185
|
return $self->invalid_value_assignment_message($class) . ' unless ' . $self->valid_value_form(@_) . ';'; |
1315
|
|
|
|
|
|
|
} |
1316
|
|
|
|
|
|
|
sub param_must_be_checked { |
1317
|
118
|
|
|
118
|
|
157
|
my $self = shift; |
1318
|
118
|
|
|
|
|
129
|
my $class = $_[0]; |
1319
|
118
|
|
100
|
|
|
191
|
return ($class->required($self->name) && ! defined $self->default) || $self->can_be_invalid; |
1320
|
|
|
|
|
|
|
} |
1321
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
sub maybe_guarded { # If parameter checking is enabled, guard a |
1323
|
106
|
|
|
106
|
|
127
|
my $self = shift; # form to check against a parameter |
1324
|
106
|
|
|
|
|
171
|
my ($form, $param_no, $class) = @_; # count. In any case, format the form |
1325
|
106
|
50
|
|
|
|
172
|
if ( $class->check_params ) { # a little. |
1326
|
106
|
|
|
|
|
665
|
$form =~ s/^/\t/mg; |
1327
|
106
|
|
|
|
|
579
|
return " \$#_ == $param_no\tand do {\n$form };\n"; |
1328
|
|
|
|
|
|
|
} |
1329
|
|
|
|
|
|
|
else { |
1330
|
0
|
|
|
|
|
0
|
$form =~ s/^/ /mg; |
1331
|
0
|
|
|
|
|
0
|
return $form; |
1332
|
|
|
|
|
|
|
} |
1333
|
|
|
|
|
|
|
} |
1334
|
|
|
|
|
|
|
|
1335
|
|
|
|
|
|
|
sub accessor_names { |
1336
|
315
|
|
|
315
|
|
315
|
my $self = shift; |
1337
|
315
|
|
|
|
|
326
|
my ($class, $name) = @_; |
1338
|
315
|
100
|
100
|
|
|
582
|
return ! ($class->readonly($name) || $class->required($name)) ? ("undef_$name") : (); |
1339
|
|
|
|
|
|
|
} |
1340
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
sub undef_form { # Return the form to undefine |
1342
|
88
|
|
|
88
|
|
100
|
my $self = shift; # a member. |
1343
|
88
|
|
|
|
|
205
|
my ($class, $element, $member_name) = @_[0..2]; |
1344
|
88
|
|
|
|
|
236
|
return $class->sub_form($member_name, 'undef_' . $member_name, ' ' . $class->undef_form . " $element;\n"); |
1345
|
|
|
|
|
|
|
} |
1346
|
|
|
|
|
|
|
|
1347
|
|
|
|
|
|
|
sub param_count_error_form { # Return a form that standardizes |
1348
|
132
|
|
|
132
|
|
150
|
my $self = shift; # the message for dieing because |
1349
|
132
|
|
|
|
|
146
|
my $class = $_[0]; # of an incorrect parameter count. |
1350
|
132
|
|
|
|
|
258
|
return q|croak '| . $self->name_form($class) . q|Invalid number of parameters (', ($#_+1), ')'|; |
1351
|
|
|
|
|
|
|
} |
1352
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
sub name_form { # Standardize a method name |
1354
|
310
|
|
|
310
|
|
296
|
my $self = shift; # for error messages. |
1355
|
310
|
|
|
|
|
271
|
my $class = $_[0]; |
1356
|
310
|
|
|
|
|
512
|
return $class->name . '::' . $self->name . ': '; |
1357
|
|
|
|
|
|
|
} |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
sub param_assignment_form { # Return a form that assigns a parameter |
1360
|
118
|
|
|
118
|
|
130
|
my $self = shift; # value to the member. |
1361
|
118
|
|
|
|
|
147
|
my ($class, $style) = @_; |
1362
|
118
|
|
|
|
|
104
|
my ($name, $element, $param, $default, $exists); |
1363
|
118
|
|
|
|
|
215
|
$name = $self->name; |
1364
|
118
|
|
|
|
|
225
|
$element = $class->instance_var . '->' . $class->index($name); |
1365
|
118
|
|
|
|
|
273
|
$param = $style->ref($name); |
1366
|
118
|
|
|
|
|
295
|
$default = $self->default; |
1367
|
118
|
|
|
|
|
212
|
$exists = $style->existence_test($name) . ' ' . $param; |
1368
|
118
|
|
|
|
|
281
|
my $form = " $element = "; |
1369
|
118
|
50
|
66
|
|
|
326
|
if ( defined $default ) { |
|
|
100
|
|
|
|
|
|
1370
|
0
|
|
|
|
|
0
|
$form .= "$exists ? $param : $default"; |
1371
|
|
|
|
|
|
|
} |
1372
|
|
|
|
|
|
|
elsif ( $class->check_params && $class->required($name) ) { |
1373
|
31
|
|
|
|
|
40
|
$form .= $param; |
1374
|
|
|
|
|
|
|
} |
1375
|
|
|
|
|
|
|
else { |
1376
|
87
|
|
|
|
|
165
|
$form .= "$param if $exists"; |
1377
|
|
|
|
|
|
|
} |
1378
|
118
|
|
|
|
|
403
|
return $form . ";\n"; |
1379
|
|
|
|
|
|
|
} |
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
sub default_assignment_form { # Return a form that assigns a default value |
1382
|
1
|
|
|
1
|
|
2
|
my $self = shift; # to a member. |
1383
|
1
|
|
|
|
|
1
|
my $class = $_[0]; |
1384
|
1
|
|
|
|
|
1
|
my $element; |
1385
|
1
|
|
|
|
|
2
|
$element = $class->instance_var . '->' . $class->index($self->name); |
1386
|
1
|
|
|
|
|
3
|
return " $element = " . $self->default . ";\n"; |
1387
|
|
|
|
|
|
|
} |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
package Class::Generate::Scalar_Member; # A Member subclass for |
1390
|
14
|
|
|
15
|
|
836
|
use strict; # scalar class members. |
|
14
|
|
|
|
|
28
|
|
|
14
|
|
|
|
|
548
|
|
1391
|
14
|
|
|
14
|
|
129
|
use vars qw(@ISA); # accessor accepts 0 or 1 parameters. |
|
14
|
|
|
|
|
25
|
|
|
14
|
|
|
|
|
8392
|
|
1392
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Member); |
1393
|
|
|
|
|
|
|
|
1394
|
|
|
|
|
|
|
sub member_forms { |
1395
|
71
|
|
|
71
|
|
94
|
my $self = shift; |
1396
|
71
|
|
|
|
|
96
|
my $class = $_[0]; |
1397
|
71
|
100
|
|
|
|
140
|
return $class->readonly($self->name) ? 'no_params' : ('no_params', 'one_param'); |
1398
|
|
|
|
|
|
|
} |
1399
|
|
|
|
|
|
|
sub no_params { |
1400
|
71
|
|
|
71
|
|
96
|
my $self = shift; |
1401
|
71
|
|
|
|
|
105
|
my ($class, $element) = @_; |
1402
|
71
|
50
|
66
|
|
|
160
|
if ( $class->readonly($self->name) && ! $class->check_params ) { |
1403
|
0
|
|
|
|
|
0
|
return " return $element;\n"; |
1404
|
|
|
|
|
|
|
} |
1405
|
71
|
|
|
|
|
266
|
return " \$#_ == -1\tand do { return $element };\n"; |
1406
|
|
|
|
|
|
|
} |
1407
|
|
|
|
|
|
|
sub one_param { |
1408
|
47
|
|
|
47
|
|
74
|
my $self = shift; |
1409
|
47
|
|
|
|
|
73
|
my ($class, $element) = @_; |
1410
|
47
|
|
|
|
|
80
|
my $form = ''; |
1411
|
47
|
50
|
|
|
|
148
|
$form .= Class::Generate::Member_Names::substituted($self->pre) if defined $self->pre; |
1412
|
47
|
100
|
66
|
|
|
115
|
$form .= $self->valid_value_test_form($class, '$_[0]') . "\n" if $class->check_params && defined $self->base; |
1413
|
47
|
|
|
|
|
131
|
$form .= "$element = \$_[0];\n"; |
1414
|
47
|
100
|
|
|
|
108
|
$form .= Class::Generate::Member_Names::substituted($self->post) if defined $self->post; |
1415
|
47
|
100
|
66
|
|
|
102
|
$form .= $self->assertion($class) . "\n" if defined $class->check_params && defined $self->assert; |
1416
|
47
|
|
|
|
|
77
|
$form .= "return;\n"; |
1417
|
47
|
|
|
|
|
176
|
return $self->maybe_guarded($form, 0, $class); |
1418
|
|
|
|
|
|
|
} |
1419
|
|
|
|
|
|
|
|
1420
|
|
|
|
|
|
|
sub valid_value_form { # Return a form that tests if |
1421
|
12
|
|
|
12
|
|
18
|
my $self = shift; # a ref is of the correct |
1422
|
12
|
|
|
|
|
14
|
my ($param) = @_; # base type. |
1423
|
12
|
|
|
|
|
39
|
return qq|UNIVERSAL::isa($param, '| . $self->base . qq|')|; |
1424
|
|
|
|
|
|
|
} |
1425
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
sub can_be_invalid { # Validity for a scalar member |
1427
|
102
|
|
|
102
|
|
115
|
my $self = shift; # is testable only if the member |
1428
|
102
|
|
|
|
|
182
|
return defined $self->base; # is supposed to be a class. |
1429
|
|
|
|
|
|
|
} |
1430
|
|
|
|
|
|
|
|
1431
|
|
|
|
|
|
|
sub as_var { |
1432
|
99
|
|
|
99
|
|
124
|
my $self = shift; |
1433
|
99
|
|
|
|
|
285
|
return '$' . $self->name; |
1434
|
|
|
|
|
|
|
} |
1435
|
|
|
|
|
|
|
|
1436
|
|
|
|
|
|
|
sub method_regexp { |
1437
|
99
|
|
|
99
|
|
139
|
my $self = shift; |
1438
|
99
|
|
|
|
|
119
|
my $class = $_[0]; |
1439
|
99
|
50
|
|
|
|
244
|
return $class->include_method($self->name) ? ('\$' . $self->name) : (); |
1440
|
|
|
|
|
|
|
} |
1441
|
|
|
|
|
|
|
sub accessor_names { |
1442
|
175
|
|
|
175
|
|
215
|
my $self = shift; |
1443
|
175
|
|
|
|
|
214
|
my ($class, $name) = @_; |
1444
|
175
|
|
|
|
|
488
|
return grep $class->include_method($_), ($name, $self->SUPER::accessor_names($class, $name)); |
1445
|
|
|
|
|
|
|
} |
1446
|
|
|
|
|
|
|
sub expected_type_form { |
1447
|
6
|
|
|
6
|
|
10
|
my $self = shift; |
1448
|
6
|
|
|
|
|
13
|
return $self->base; |
1449
|
|
|
|
|
|
|
} |
1450
|
|
|
|
|
|
|
|
1451
|
|
|
|
|
|
|
sub copy_form { |
1452
|
37
|
|
|
37
|
|
64
|
my $self = shift; |
1453
|
37
|
|
|
|
|
55
|
my ($from, $to) = @_; |
1454
|
37
|
|
|
|
|
96
|
my $form = " $to = $from"; |
1455
|
37
|
50
|
|
|
|
131
|
if ( ! $self->nocopy ) { |
1456
|
37
|
100
|
|
|
|
70
|
$form .= '->copy' if $self->base; |
1457
|
|
|
|
|
|
|
} |
1458
|
37
|
|
|
|
|
105
|
$form .= " if defined $from;\n"; |
1459
|
37
|
|
|
|
|
105
|
return $form; |
1460
|
|
|
|
|
|
|
} |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
sub equals { |
1463
|
70
|
|
|
70
|
|
87
|
my $self = shift; |
1464
|
70
|
|
|
|
|
102
|
my ($index, $existence_test) = @_; |
1465
|
70
|
|
|
|
|
183
|
my ($sr, $or) = ('$self->' . $index, '$o->' . $index); |
1466
|
70
|
|
|
|
|
374
|
my $form = " return undef if $existence_test $sr ^ $existence_test $or;\n" . |
1467
|
|
|
|
|
|
|
" if ( $existence_test $sr ) { return undef unless $sr"; |
1468
|
70
|
100
|
|
|
|
136
|
if ( $self->base ) { |
1469
|
5
|
|
|
|
|
19
|
$form .= "->equals($or)"; |
1470
|
|
|
|
|
|
|
} |
1471
|
|
|
|
|
|
|
else { |
1472
|
65
|
|
|
|
|
268
|
$form .= " eq $or"; |
1473
|
|
|
|
|
|
|
} |
1474
|
70
|
|
|
|
|
375
|
return $form . " }\n"; |
1475
|
|
|
|
|
|
|
} |
1476
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
package Class::Generate::List_Member; # A Member subclass for list |
1478
|
14
|
|
|
14
|
|
983
|
use strict; # (array and hash) members. |
|
14
|
|
|
|
|
28
|
|
|
14
|
|
|
|
|
352
|
|
1479
|
14
|
|
|
14
|
|
793
|
use vars qw(@ISA); # accessor accepts 0-2 parameters. |
|
14
|
|
|
|
|
26
|
|
|
14
|
|
|
|
|
9079
|
|
1480
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Member); |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
sub member_forms { |
1483
|
61
|
|
|
61
|
|
98
|
my $self = shift; |
1484
|
61
|
|
|
|
|
68
|
my $class = $_[0]; |
1485
|
61
|
100
|
|
|
|
110
|
return $class->readonly($self->name) ? ('no_params', 'one_param') : ('no_params', 'one_param', 'two_params'); |
1486
|
|
|
|
|
|
|
} |
1487
|
|
|
|
|
|
|
sub no_params { |
1488
|
61
|
|
|
61
|
|
73
|
my $self = shift; |
1489
|
61
|
|
|
|
|
108
|
my ($class, $element, $exists, $lvalue, $values) = @_; |
1490
|
61
|
|
|
|
|
206
|
return " \$#_ == -1\tand do { return $exists ? " . $self->whole_lvalue($element) . " : () };\n"; |
1491
|
|
|
|
|
|
|
} |
1492
|
|
|
|
|
|
|
sub one_param { |
1493
|
61
|
|
|
61
|
|
255
|
my $self = shift; |
1494
|
61
|
|
|
|
|
95
|
my ($class, $element, $exists, $lvalue, $values) = @_; |
1495
|
61
|
|
|
|
|
56
|
my $form; |
1496
|
61
|
100
|
|
|
|
171
|
if ( $class->accept_refs ) { |
1497
|
59
|
|
|
|
|
169
|
$form = " \$#_ == 0\tand do {\n" . |
1498
|
|
|
|
|
|
|
"\t" . "return ($exists ? ${element}->$lvalue : undef) if ! ref \$_[0];\n"; |
1499
|
59
|
100
|
66
|
|
|
114
|
if ( $class->check_params && $class->readonly($self->name) ) { |
1500
|
2
|
|
|
|
|
7
|
$form .= "croak '" . $self->name_form($class) . "Member is read-only';\n"; |
1501
|
|
|
|
|
|
|
} |
1502
|
|
|
|
|
|
|
else { |
1503
|
57
|
50
|
|
|
|
120
|
$form .= "\t" . Class::Generate::Member_Names::substituted($self->pre) if defined $self->pre; |
1504
|
57
|
50
|
|
|
|
113
|
$form .= "\t" . $self->valid_value_test_form($class, '$_[0]') . "\n" if $class->check_params; |
1505
|
57
|
|
|
|
|
157
|
$form .= "\t" . $self->whole_lvalue($element) . ' = ' . $self->whole_lvalue('$_[0]') . ";\n"; |
1506
|
57
|
50
|
|
|
|
131
|
$form .= "\t" . Class::Generate::Member_Names::substituted($self->post) if defined $self->post; |
1507
|
57
|
50
|
33
|
|
|
111
|
$form .= "\t" . $self->assertion($class) . "\n" if defined $class->check_params && defined $self->assert; |
1508
|
57
|
|
|
|
|
86
|
$form .= "\t" . "return;\n"; |
1509
|
|
|
|
|
|
|
} |
1510
|
59
|
|
|
|
|
81
|
$form .= " };\n"; |
1511
|
|
|
|
|
|
|
} |
1512
|
|
|
|
|
|
|
else { |
1513
|
2
|
|
|
|
|
9
|
$form = " \$#_ == 0\tand do { return $exists ? ${element}->$lvalue : undef };\n" |
1514
|
|
|
|
|
|
|
} |
1515
|
61
|
|
|
|
|
164
|
return $form; |
1516
|
|
|
|
|
|
|
} |
1517
|
|
|
|
|
|
|
sub two_params { |
1518
|
59
|
|
|
59
|
|
72
|
my $self = shift; |
1519
|
59
|
|
|
|
|
91
|
my ($class, $element, $exists, $lvalue, $values) = @_; |
1520
|
59
|
|
|
|
|
77
|
my $form = ''; |
1521
|
59
|
50
|
|
|
|
104
|
$form .= Class::Generate::Member_Names::substituted($self->pre) if defined $self->pre; |
1522
|
59
|
100
|
66
|
|
|
130
|
$form .= $self->valid_element_test($class, '$_[1]') . "\n" if $class->check_params && defined $self->base; |
1523
|
59
|
|
|
|
|
150
|
$form .= "${element}->$lvalue = \$_[1];\n"; |
1524
|
59
|
50
|
|
|
|
103
|
$form .= Class::Generate::Member_Names::substituted($self->post) if defined $self->post; |
1525
|
59
|
|
|
|
|
80
|
$form .= "return;\n"; |
1526
|
59
|
|
|
|
|
193
|
return $self->maybe_guarded($form, 1, $class); |
1527
|
|
|
|
|
|
|
} |
1528
|
|
|
|
|
|
|
|
1529
|
|
|
|
|
|
|
sub valid_value_form { # Return a form that tests if a |
1530
|
110
|
|
|
110
|
|
123
|
my $self = shift; # parameter is a correct list reference |
1531
|
110
|
|
|
|
|
117
|
my $param = $_[0]; # and (if relevant) if all of its |
1532
|
110
|
|
|
|
|
171
|
my $base = $self->base; # elements have the correct base type. |
1533
|
110
|
|
|
|
|
628
|
ref($self) =~ /::(\w+)_Member$/; |
1534
|
110
|
|
|
|
|
371
|
my $form = "UNIVERSAL::isa($param, '" . uc($1) . "')"; |
1535
|
110
|
100
|
|
|
|
213
|
if ( defined $base ) { |
1536
|
20
|
|
|
|
|
63
|
$form .= qq| && ! grep ! (defined \$_ && UNIVERSAL::isa(\$_, '$base')), | . $self->values($param); |
1537
|
|
|
|
|
|
|
} |
1538
|
110
|
|
|
|
|
306
|
return $form; |
1539
|
|
|
|
|
|
|
} |
1540
|
|
|
|
|
|
|
|
1541
|
|
|
|
|
|
|
sub valid_element_test { # Return a form that dies unless an |
1542
|
10
|
|
|
10
|
|
14
|
my $self = shift; # element has the correct base type. |
1543
|
10
|
|
|
|
|
12
|
my ($class, $param) = @_; |
1544
|
10
|
|
|
|
|
19
|
return $self->invalid_value_assignment_message($class) . |
1545
|
|
|
|
|
|
|
qq| unless UNIVERSAL::isa($param, '| . $self->base . q|');|; |
1546
|
|
|
|
|
|
|
} |
1547
|
|
|
|
|
|
|
|
1548
|
|
|
|
|
|
|
sub valid_elements_test { # Return a form that dies unless all |
1549
|
5
|
|
|
5
|
|
8
|
my $self = shift; # elements of a list are validly typed. |
1550
|
5
|
|
|
|
|
9
|
my ($class, $values) = @_; |
1551
|
5
|
|
|
|
|
12
|
my $base = $self->base; |
1552
|
5
|
|
|
|
|
12
|
return $self->invalid_value_assignment_message($class) . |
1553
|
|
|
|
|
|
|
q| unless ! grep ! UNIVERSAL::isa($_, '| . $self->base . qq|'), $values;|; |
1554
|
|
|
|
|
|
|
} |
1555
|
|
|
|
|
|
|
|
1556
|
|
|
|
|
|
|
sub can_be_invalid { # A value for a list member can |
1557
|
153
|
|
|
153
|
|
522
|
return 1; # always be invalid: the wrong |
1558
|
|
|
|
|
|
|
} # type of list can be given. |
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
package Class::Generate::Array_Member; # A List subclass for array |
1561
|
14
|
|
|
14
|
|
181
|
use strict; # members. Provides the |
|
14
|
|
|
|
|
32
|
|
|
14
|
|
|
|
|
408
|
|
1562
|
14
|
|
|
14
|
|
189
|
use vars qw(@ISA); # of accessing array members. |
|
14
|
|
|
|
|
29
|
|
|
14
|
|
|
|
|
9318
|
|
1563
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::List_Member); |
1564
|
|
|
|
|
|
|
|
1565
|
|
|
|
|
|
|
sub lvalue { |
1566
|
31
|
|
|
31
|
|
39
|
my $self = shift; |
1567
|
31
|
|
|
|
|
77
|
return '[' . $_[0] . ']'; |
1568
|
|
|
|
|
|
|
} |
1569
|
|
|
|
|
|
|
|
1570
|
|
|
|
|
|
|
sub whole_lvalue { |
1571
|
89
|
|
|
89
|
|
82
|
my $self = shift; |
1572
|
89
|
|
|
|
|
238
|
return '@{' . $_[0] . '}'; |
1573
|
|
|
|
|
|
|
} |
1574
|
|
|
|
|
|
|
|
1575
|
|
|
|
|
|
|
sub values { |
1576
|
41
|
|
|
41
|
|
52
|
my $self = shift; |
1577
|
41
|
|
|
|
|
110
|
return '@{' . $_[0] . '}'; |
1578
|
|
|
|
|
|
|
} |
1579
|
|
|
|
|
|
|
|
1580
|
|
|
|
|
|
|
sub size_form { |
1581
|
31
|
|
|
31
|
|
61
|
my $self = shift; |
1582
|
31
|
|
|
|
|
63
|
my ($class, $element, $member_name, $exists) = @_; |
1583
|
31
|
|
|
|
|
160
|
return $class->sub_form($member_name, $member_name . '_size', " return $exists ? \$#{$element} : -1;\n"); |
1584
|
|
|
|
|
|
|
} |
1585
|
|
|
|
|
|
|
|
1586
|
|
|
|
|
|
|
sub last_form { |
1587
|
31
|
|
|
31
|
|
49
|
my $self = shift; |
1588
|
31
|
|
|
|
|
54
|
my ($class, $element, $member_name, $exists) = @_; |
1589
|
31
|
|
|
|
|
175
|
return $class->sub_form($member_name, 'last_' . $member_name, " return $exists ? $element" . "[\$#{$element}] : undef;\n"); |
1590
|
|
|
|
|
|
|
} |
1591
|
|
|
|
|
|
|
|
1592
|
|
|
|
|
|
|
sub add_form { |
1593
|
30
|
|
|
30
|
|
47
|
my $self = shift; |
1594
|
30
|
|
|
|
|
51
|
my ($class, $element, $member_name, $exists) = @_; |
1595
|
30
|
|
|
|
|
42
|
my $body = ''; |
1596
|
30
|
100
|
66
|
|
|
72
|
$body .= ' ' . $self->valid_elements_test($class, '@_') . "\n" if $class->check_params && defined $self->base; |
1597
|
30
|
50
|
|
|
|
74
|
$body .= Class::Generate::Member_Names::substituted($self->pre) if defined $self->pre; |
1598
|
30
|
|
|
|
|
87
|
$body .= ' push @{' . $element . '}, @_;' . "\n"; |
1599
|
30
|
50
|
|
|
|
70
|
$body .= Class::Generate::Member_Names::substituted($self->post) if defined $self->post; |
1600
|
30
|
50
|
33
|
|
|
75
|
$body .= ' ' . $self->assertion($class) . "\n" if defined $class->check_params && defined $self->assert; |
1601
|
30
|
|
|
|
|
129
|
return $class->sub_form($member_name, 'add_' . $member_name, $body); |
1602
|
|
|
|
|
|
|
} |
1603
|
|
|
|
|
|
|
|
1604
|
|
|
|
|
|
|
sub as_var { |
1605
|
34
|
|
|
34
|
|
45
|
my $self = shift; |
1606
|
34
|
|
|
|
|
70
|
return '@' . $self->name; |
1607
|
|
|
|
|
|
|
} |
1608
|
|
|
|
|
|
|
|
1609
|
|
|
|
|
|
|
sub method_regexp { |
1610
|
34
|
|
|
34
|
|
48
|
my $self = shift; |
1611
|
34
|
|
|
|
|
51
|
my $class = $_[0]; |
1612
|
34
|
50
|
|
|
|
139
|
return $class->include_method($self->name) ? ('@' . $self->name, '\$#?' . $self->name) : (); |
1613
|
|
|
|
|
|
|
} |
1614
|
|
|
|
|
|
|
sub accessor_names { |
1615
|
72
|
|
|
72
|
|
101
|
my $self = shift; |
1616
|
72
|
|
|
|
|
135
|
my ($class, $name) = @_; |
1617
|
72
|
|
|
|
|
317
|
my @names = ($name, "${name}_size", "last_$name", $self->SUPER::accessor_names($class, $name)); |
1618
|
72
|
100
|
|
|
|
163
|
push @names, "add_$name" if ! $class->readonly($name); |
1619
|
72
|
|
|
|
|
247
|
return grep $class->include_method($_), @names; |
1620
|
|
|
|
|
|
|
} |
1621
|
|
|
|
|
|
|
sub expected_type_form { |
1622
|
39
|
|
|
39
|
|
53
|
my $self = shift; |
1623
|
39
|
100
|
|
|
|
84
|
if ( defined $self->base ) { |
1624
|
15
|
|
|
|
|
26
|
return 'reference to array of ' . $self->base; |
1625
|
|
|
|
|
|
|
} |
1626
|
|
|
|
|
|
|
else { |
1627
|
24
|
|
|
|
|
110
|
return 'array reference'; |
1628
|
|
|
|
|
|
|
} |
1629
|
|
|
|
|
|
|
} |
1630
|
|
|
|
|
|
|
|
1631
|
|
|
|
|
|
|
sub copy_form { |
1632
|
30
|
|
|
30
|
|
58
|
my $self = shift; |
1633
|
30
|
|
|
|
|
70
|
my ($from, $to) = @_; |
1634
|
30
|
|
|
|
|
69
|
my $form = " $to = "; |
1635
|
30
|
100
|
|
|
|
104
|
if ( ! $self->nocopy ) { |
1636
|
29
|
|
|
|
|
52
|
$form .= '[ '; |
1637
|
29
|
100
|
|
|
|
55
|
$form .= 'map defined $_ ? $_->copy : undef, ' if $self->base; |
1638
|
29
|
|
|
|
|
73
|
$form .= "\@{$from} ]"; |
1639
|
|
|
|
|
|
|
} |
1640
|
|
|
|
|
|
|
else { |
1641
|
1
|
|
|
|
|
3
|
$form .= $from; |
1642
|
|
|
|
|
|
|
} |
1643
|
30
|
|
|
|
|
71
|
$form .= " if defined $from;\n"; |
1644
|
30
|
|
|
|
|
79
|
return $form; |
1645
|
|
|
|
|
|
|
} |
1646
|
|
|
|
|
|
|
|
1647
|
|
|
|
|
|
|
sub equals { |
1648
|
27
|
|
|
27
|
|
36
|
my $self = shift; |
1649
|
27
|
|
|
|
|
46
|
my ($index, $existence_test) = @_; |
1650
|
27
|
|
|
|
|
82
|
my ($sr, $or) = ('$self->' . $index, '$o->' . $index); |
1651
|
27
|
|
|
|
|
248
|
my $form = " return undef if $existence_test($sr) ^ $existence_test($or);\n" . |
1652
|
|
|
|
|
|
|
" if ( $existence_test $sr ) {\n" . |
1653
|
|
|
|
|
|
|
" return undef unless (\$ub = \$#{$sr}) == \$#{$or};\n" . |
1654
|
|
|
|
|
|
|
" for ( my \$i = 0; \$i <= \$ub; \$i++ ) {\n" . |
1655
|
|
|
|
|
|
|
" return undef unless $sr" . '[$i]'; |
1656
|
27
|
100
|
|
|
|
58
|
if ( $self->base ) { |
1657
|
3
|
|
|
|
|
8
|
$form .= '->equals(' . $or . '[$i])'; |
1658
|
|
|
|
|
|
|
} |
1659
|
|
|
|
|
|
|
else { |
1660
|
24
|
|
|
|
|
59
|
$form .= ' eq ' . $or . '[$i]'; |
1661
|
|
|
|
|
|
|
} |
1662
|
27
|
|
|
|
|
153
|
return $form . ";\n\t}\n }\n"; |
1663
|
|
|
|
|
|
|
} |
1664
|
|
|
|
|
|
|
|
1665
|
|
|
|
|
|
|
package Class::Generate::Hash_Member; # A List subclass for Hash |
1666
|
14
|
|
|
14
|
|
129
|
use strict; # members. Provides the n_keys |
|
14
|
|
|
|
|
28
|
|
|
14
|
|
|
|
|
707
|
|
1667
|
14
|
|
|
14
|
|
176
|
use vars qw(@ISA); # specifics of accessing |
|
14
|
|
|
|
|
28
|
|
|
14
|
|
|
|
|
8821
|
|
1668
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::List_Member); # hash members. |
1669
|
|
|
|
|
|
|
|
1670
|
|
|
|
|
|
|
sub lvalue { |
1671
|
30
|
|
|
30
|
|
47
|
my $self = shift; |
1672
|
30
|
|
|
|
|
101
|
return '{' . $_[0] . '}'; |
1673
|
|
|
|
|
|
|
} |
1674
|
|
|
|
|
|
|
sub whole_lvalue { |
1675
|
86
|
|
|
86
|
|
83
|
my $self = shift; |
1676
|
86
|
|
|
|
|
298
|
return '%{' . $_[0] . '}'; |
1677
|
|
|
|
|
|
|
} |
1678
|
|
|
|
|
|
|
sub values { |
1679
|
40
|
|
|
40
|
|
58
|
my $self = shift; |
1680
|
40
|
|
|
|
|
104
|
return 'values %{' . $_[0] . '}'; |
1681
|
|
|
|
|
|
|
} |
1682
|
|
|
|
|
|
|
|
1683
|
|
|
|
|
|
|
sub delete_form { |
1684
|
29
|
|
|
29
|
|
46
|
my $self = shift; |
1685
|
29
|
|
|
|
|
56
|
my ($class, $element, $member_name, $exists) = @_; |
1686
|
29
|
|
|
|
|
128
|
return $class->sub_form($member_name, 'delete_' . $member_name, " delete \@{$element}{\@_} if $exists;\n"); |
1687
|
|
|
|
|
|
|
} |
1688
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
sub keys_form { |
1690
|
29
|
|
|
29
|
|
49
|
my $self = shift; |
1691
|
29
|
|
|
|
|
56
|
my ($class, $element, $member_name, $exists) = @_; |
1692
|
29
|
|
|
|
|
144
|
return $class->sub_form($member_name, $member_name . '_keys', " return $exists ? keys \%{$element} : ();\n"); |
1693
|
|
|
|
|
|
|
} |
1694
|
|
|
|
|
|
|
sub values_form { |
1695
|
30
|
|
|
30
|
|
708
|
my $self = shift; |
1696
|
30
|
|
|
|
|
59
|
my ($class, $element, $member_name, $exists) = @_; |
1697
|
30
|
|
|
|
|
135
|
return $class->sub_form($member_name, $member_name . '_values', " return $exists ? values \%{$element} : ();\n"); |
1698
|
|
|
|
|
|
|
} |
1699
|
|
|
|
|
|
|
|
1700
|
|
|
|
|
|
|
sub as_var { |
1701
|
32
|
|
|
32
|
|
49
|
my $self = shift; |
1702
|
32
|
|
|
|
|
75
|
return '%' . $self->name; |
1703
|
|
|
|
|
|
|
} |
1704
|
|
|
|
|
|
|
|
1705
|
|
|
|
|
|
|
sub method_regexp { |
1706
|
32
|
|
|
32
|
|
43
|
my $self = shift; |
1707
|
32
|
|
|
|
|
42
|
my $class = $_[0]; |
1708
|
32
|
50
|
|
|
|
126
|
return $class->include_method($self->name) ? ('[%$]' . $self->name) : (); |
1709
|
|
|
|
|
|
|
} |
1710
|
|
|
|
|
|
|
sub accessor_names { |
1711
|
68
|
|
|
68
|
|
93
|
my $self = shift; |
1712
|
68
|
|
|
|
|
99
|
my ($class, $name) = @_; |
1713
|
68
|
|
|
|
|
315
|
my @names = ($name, "${name}_keys", "${name}_values", $self->SUPER::accessor_names($class, $name)); |
1714
|
68
|
100
|
|
|
|
147
|
push @names, "delete_$name" if ! $class->readonly($name); |
1715
|
68
|
|
|
|
|
215
|
return grep $class->include_method($_), @names; |
1716
|
|
|
|
|
|
|
} |
1717
|
|
|
|
|
|
|
sub expected_type_form { |
1718
|
33
|
|
|
33
|
|
42
|
my $self = shift; |
1719
|
33
|
100
|
|
|
|
79
|
if ( defined $self->base ) { |
1720
|
10
|
|
|
|
|
18
|
return 'reference to hash of ' . $self->base; |
1721
|
|
|
|
|
|
|
} |
1722
|
|
|
|
|
|
|
else { |
1723
|
23
|
|
|
|
|
112
|
return 'hash reference'; |
1724
|
|
|
|
|
|
|
} |
1725
|
|
|
|
|
|
|
} |
1726
|
|
|
|
|
|
|
|
1727
|
|
|
|
|
|
|
sub copy_form { |
1728
|
29
|
|
|
29
|
|
50
|
my $self = shift; |
1729
|
29
|
|
|
|
|
51
|
my ($from, $to) = @_; |
1730
|
29
|
100
|
|
|
|
99
|
if ( ! $self->nocopy ) { |
1731
|
28
|
100
|
|
|
|
61
|
if ( $self->base ) { |
1732
|
5
|
|
|
|
|
45
|
return " if ( defined $from ) {\n" . |
1733
|
|
|
|
|
|
|
"\t$to = {};\n" . |
1734
|
|
|
|
|
|
|
"\twhile ( my (\$key, \$value) = each \%{$from} ) {\n" . |
1735
|
|
|
|
|
|
|
"\t $to" . '->{$key} = defined $value ? $value->copy : undef;' . "\n" . |
1736
|
|
|
|
|
|
|
"\t}\n" . |
1737
|
|
|
|
|
|
|
" }\n"; |
1738
|
|
|
|
|
|
|
} |
1739
|
|
|
|
|
|
|
else { |
1740
|
23
|
|
|
|
|
123
|
return " $to = { \%{$from} } if defined $from;\n"; |
1741
|
|
|
|
|
|
|
} |
1742
|
|
|
|
|
|
|
} |
1743
|
|
|
|
|
|
|
else { |
1744
|
1
|
|
|
|
|
7
|
return " $to = $from if defined $from;\n"; |
1745
|
|
|
|
|
|
|
} |
1746
|
|
|
|
|
|
|
} |
1747
|
|
|
|
|
|
|
|
1748
|
|
|
|
|
|
|
sub equals { |
1749
|
25
|
|
|
25
|
|
38
|
my $self = shift; |
1750
|
25
|
|
|
|
|
42
|
my ($index, $existence_test) = @_; |
1751
|
25
|
|
|
|
|
67
|
my ($sr, $or) = ('$self->' . $index, '$o->' . $index); |
1752
|
25
|
|
|
|
|
1209
|
my $form = " return undef if $existence_test $sr ^ $existence_test $or;\n" . |
1753
|
|
|
|
|
|
|
" if ( $existence_test $sr ) {\n" . |
1754
|
|
|
|
|
|
|
' @self_keys = keys %{' . $sr . '};' . "\n" . |
1755
|
|
|
|
|
|
|
' return undef unless $#self_keys == scalar(keys %{' . $or . '}) - 1;' . "\n" . |
1756
|
|
|
|
|
|
|
' for my $k ( @self_keys ) {' . "\n" . |
1757
|
|
|
|
|
|
|
" return undef unless exists $or" . '{$k};' . "\n" . |
1758
|
|
|
|
|
|
|
' return undef if ($self_value_defined = defined ' . $sr . '{$k}) ^ defined ' . $or . '{$k};' . "\n" . |
1759
|
|
|
|
|
|
|
' if ( $self_value_defined ) { return undef unless '; |
1760
|
25
|
100
|
|
|
|
60
|
if ( $self->base ) { |
1761
|
3
|
|
|
|
|
10
|
$form .= $sr . '{$k}->equals(' . $or . '{$k})'; |
1762
|
|
|
|
|
|
|
} |
1763
|
|
|
|
|
|
|
else { |
1764
|
22
|
|
|
|
|
81
|
$form .= $sr . '{$k} eq ' . $or . '{$k}'; |
1765
|
|
|
|
|
|
|
} |
1766
|
25
|
|
|
|
|
46
|
$form .= " }\n\t}\n }\n"; |
1767
|
25
|
|
|
|
|
209
|
return $form; |
1768
|
|
|
|
|
|
|
} |
1769
|
|
|
|
|
|
|
|
1770
|
|
|
|
|
|
|
package Class::Generate::Constructor; # The constructor is treated as a |
1771
|
14
|
|
|
14
|
|
773
|
use strict; # special type of member. It includes |
|
14
|
|
|
|
|
32
|
|
|
14
|
|
|
|
|
398
|
|
1772
|
14
|
|
|
14
|
|
142
|
use vars qw(@ISA); # constraints on required members. |
|
14
|
|
|
|
|
28
|
|
|
14
|
|
|
|
|
14697
|
|
1773
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Member); |
1774
|
|
|
|
|
|
|
|
1775
|
|
|
|
|
|
|
sub new { |
1776
|
62
|
|
|
62
|
|
109
|
my $class = shift; |
1777
|
62
|
|
|
|
|
344
|
my $self = $class->SUPER::new('new', @_); |
1778
|
62
|
|
|
|
|
300
|
return $self; |
1779
|
|
|
|
|
|
|
} |
1780
|
|
|
|
|
|
|
sub style { |
1781
|
358
|
|
|
358
|
|
374
|
my $self = shift; |
1782
|
358
|
100
|
|
|
|
1282
|
return $self->{'style'} if $#_ == -1; |
1783
|
61
|
|
|
|
|
275
|
$self->{'style'} = $_[0]; |
1784
|
|
|
|
|
|
|
} |
1785
|
|
|
|
|
|
|
sub constraints { |
1786
|
52
|
|
|
52
|
|
86
|
my $self = shift; |
1787
|
52
|
100
|
|
|
|
359
|
return exists $self->{'constraints'} ? @{$self->{'constraints'}} : () if $#_ == -1; |
|
1
|
50
|
|
|
|
3
|
|
1788
|
0
|
0
|
|
|
|
0
|
return exists $self->{'constraints'} ? $self->{'constraints'}->[$_[0]] : undef if $#_ == 0; |
|
|
0
|
|
|
|
|
|
1789
|
0
|
|
|
|
|
0
|
$self->{'constraints'}->[$_[0]] = $_[1]; |
1790
|
|
|
|
|
|
|
} |
1791
|
|
|
|
|
|
|
sub add_constraints { |
1792
|
1
|
|
|
1
|
|
2
|
my $self = shift; |
1793
|
1
|
|
|
|
|
1
|
push @{$self->{'constraints'}}, @_; |
|
1
|
|
|
|
|
5
|
|
1794
|
|
|
|
|
|
|
} |
1795
|
|
|
|
|
|
|
sub constraints_size { |
1796
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
1797
|
0
|
0
|
|
|
|
0
|
return exists $self->{'constraints'} ? $#{$self->{'constraints'}} : -1; |
|
0
|
|
|
|
|
0
|
|
1798
|
|
|
|
|
|
|
} |
1799
|
|
|
|
|
|
|
sub constraint_form { |
1800
|
1
|
|
|
1
|
|
2
|
my $self = shift; |
1801
|
1
|
|
|
|
|
2
|
my ($class, $style, $constraint) = @_; |
1802
|
1
|
|
|
|
|
2
|
my $param_given = $constraint; |
1803
|
1
|
|
|
|
|
6
|
$param_given =~ s/\w+/$style->existence_test($&) . ' ' . $style->ref($&)/eg; |
|
2
|
|
|
|
|
3
|
|
1804
|
1
|
|
|
|
|
3
|
$constraint =~ s/'/\\'/g; |
1805
|
1
|
|
|
|
|
4
|
return q|croak '| . $self->name_form($class) . qq|Parameter constraint "$constraint" failed' unless $param_given;|; |
1806
|
|
|
|
|
|
|
} |
1807
|
|
|
|
|
|
|
sub param_tests_form { |
1808
|
57
|
|
|
57
|
|
84
|
my $self = shift; |
1809
|
57
|
|
|
|
|
94
|
my ($class, $style) = @_; |
1810
|
57
|
|
|
|
|
102
|
my $form = ''; |
1811
|
57
|
100
|
100
|
|
|
126
|
if ( ! $class->parents && $style->can('params_check_form') ) { |
1812
|
45
|
|
|
|
|
142
|
$form .= $style->params_check_form($class, $self); |
1813
|
|
|
|
|
|
|
} |
1814
|
57
|
100
|
|
|
|
444
|
if ( ! $style->isa('Class::Generate::Own') ) { |
1815
|
52
|
|
|
|
|
158
|
my @public_members = map $class->members($_), $class->public_member_names; |
1816
|
52
|
100
|
|
|
|
324
|
for my $param_test ( map $_->param_must_be_checked($class) ? $_->param_test($class) : (), @public_members ) { |
1817
|
84
|
|
|
|
|
234
|
$form .= ' ' . $param_test . "\n"; |
1818
|
|
|
|
|
|
|
} |
1819
|
52
|
|
|
|
|
222
|
for my $constraint ( $self->constraints ) { |
1820
|
1
|
|
|
|
|
5
|
$form .= ' ' . $self->constraint_form($class, $style, $constraint) . "\n"; |
1821
|
|
|
|
|
|
|
} |
1822
|
|
|
|
|
|
|
} |
1823
|
57
|
|
|
|
|
179
|
return $form; |
1824
|
|
|
|
|
|
|
} |
1825
|
|
|
|
|
|
|
sub assertions_form { |
1826
|
57
|
|
|
57
|
|
85
|
my $self = shift; |
1827
|
57
|
|
|
|
|
88
|
my $class = $_[0]; |
1828
|
57
|
|
|
|
|
96
|
my $form = ''; |
1829
|
57
|
100
|
66
|
|
|
117
|
$form .= ' ' . $self->assertion($class) . "\n" if defined $class->check_params && defined $self->assert; |
1830
|
57
|
|
|
|
|
166
|
for my $member ( grep defined $_->assert, $class->members_values ) { |
1831
|
3
|
|
|
|
|
23
|
$form .= ' ' . $member->assertion($class) . "\n"; |
1832
|
|
|
|
|
|
|
} |
1833
|
57
|
|
|
|
|
156
|
return $form; |
1834
|
|
|
|
|
|
|
} |
1835
|
|
|
|
|
|
|
sub form { |
1836
|
57
|
|
|
57
|
|
88
|
my $self = shift; |
1837
|
57
|
|
|
|
|
83
|
my $class = $_[0]; |
1838
|
57
|
|
|
|
|
140
|
my $style = $self->style; |
1839
|
57
|
|
|
|
|
160
|
my ($iv, $cv) = ($class->instance_var, $class->class_var); |
1840
|
57
|
|
|
|
|
90
|
my $form; |
1841
|
57
|
100
|
|
|
|
293
|
$form = "sub new {\n" . |
1842
|
|
|
|
|
|
|
" my $cv = " . |
1843
|
|
|
|
|
|
|
($class->nfi ? 'do { my $proto = shift; ref $proto || $proto }' : 'shift') . |
1844
|
|
|
|
|
|
|
";\n"; |
1845
|
57
|
100
|
66
|
|
|
160
|
if ( $class->check_params && $class->virtual ) { |
1846
|
1
|
|
|
|
|
6
|
$form .= q| croak '| . $self->name_form($class) . q|Virtual class' unless $class ne '| . $class->name . qq|';\n|; |
1847
|
|
|
|
|
|
|
} |
1848
|
57
|
100
|
66
|
|
|
203
|
$form .= $style->init_form($class, $self) if ! $class->can_assign_all_params && |
1849
|
|
|
|
|
|
|
$style->can('init_form'); |
1850
|
57
|
50
|
|
|
|
167
|
$form .= $self->param_tests_form($class, $style) if $class->check_params; |
1851
|
57
|
100
|
|
|
|
153
|
if ( defined $class->parents ) { |
1852
|
11
|
|
|
|
|
56
|
$form .= $style->self_from_super_form($class); |
1853
|
|
|
|
|
|
|
} |
1854
|
|
|
|
|
|
|
else { |
1855
|
46
|
|
|
|
|
213
|
$form .= ' my ' . $iv . ' = ' . $class->base . ";\n" . |
1856
|
|
|
|
|
|
|
' bless ' . $iv . ', ' . $cv . ";\n"; |
1857
|
|
|
|
|
|
|
} |
1858
|
57
|
50
|
|
|
|
161
|
if ( ! $class->can_assign_all_params ) { |
1859
|
57
|
100
|
|
|
|
399
|
$form .= $class->size_establishment($iv) if $class->can('size_establishment'); |
1860
|
57
|
100
|
|
|
|
352
|
if ( ! $style->isa('Class::Generate::Own') ) { |
1861
|
52
|
|
|
|
|
158
|
for my $name ( $class->public_member_names ) { |
1862
|
118
|
|
|
|
|
261
|
$form .= $class->members($name)->param_assignment_form($class, $style); |
1863
|
|
|
|
|
|
|
} |
1864
|
|
|
|
|
|
|
} |
1865
|
|
|
|
|
|
|
} |
1866
|
57
|
|
|
|
|
299
|
$form .= $class->protected_members_info_form; |
1867
|
57
|
|
100
|
|
|
175
|
for my $member ( grep(($style->isa('Class::Generate::Own') || $class->protected($_->name) || $class->private($_->name)) && |
1868
|
|
|
|
|
|
|
defined $_->default, $class->members_values) ) { |
1869
|
1
|
|
|
|
|
7
|
$form .= $member->default_assignment_form($class); |
1870
|
|
|
|
|
|
|
} |
1871
|
57
|
100
|
|
|
|
194
|
$form .= Class::Generate::Member_Names::substituted($self->post) if defined $self->post; |
1872
|
57
|
50
|
|
|
|
144
|
$form .= $self->assertions_form($class) if $class->check_params; |
1873
|
57
|
|
|
|
|
180
|
$form .= ' return ' . $iv . ";\n" . |
1874
|
|
|
|
|
|
|
"}\n"; |
1875
|
57
|
|
|
|
|
244
|
return $form; |
1876
|
|
|
|
|
|
|
} |
1877
|
|
|
|
|
|
|
|
1878
|
|
|
|
|
|
|
package Class::Generate::Method; # A user-defined method, |
1879
|
|
|
|
|
|
|
# with a name and body. |
1880
|
|
|
|
|
|
|
sub new { |
1881
|
28
|
|
|
28
|
|
28
|
my $class = shift; |
1882
|
28
|
|
|
|
|
67
|
my $self = { name => $_[0], body => $_[1] }; |
1883
|
28
|
|
|
|
|
43
|
bless $self, $class; |
1884
|
28
|
|
|
|
|
43
|
return $self; |
1885
|
|
|
|
|
|
|
} |
1886
|
|
|
|
|
|
|
|
1887
|
|
|
|
|
|
|
sub name { |
1888
|
139
|
|
|
139
|
|
117
|
my $self = shift; |
1889
|
139
|
|
|
|
|
287
|
return $self->{'name'}; |
1890
|
|
|
|
|
|
|
} |
1891
|
|
|
|
|
|
|
|
1892
|
|
|
|
|
|
|
sub body { |
1893
|
77
|
|
|
77
|
|
72
|
my $self = shift; |
1894
|
77
|
|
|
|
|
234
|
return $self->{'body'}; |
1895
|
|
|
|
|
|
|
} |
1896
|
|
|
|
|
|
|
|
1897
|
|
|
|
|
|
|
sub comment { |
1898
|
26
|
|
|
26
|
|
21
|
my $self = shift; |
1899
|
26
|
50
|
|
|
|
97
|
return $self->{'comment'} if $#_ == -1; |
1900
|
0
|
|
|
|
|
0
|
$self->{'comment'} = $_[0]; |
1901
|
|
|
|
|
|
|
} |
1902
|
|
|
|
|
|
|
|
1903
|
|
|
|
|
|
|
sub form { |
1904
|
26
|
|
|
26
|
|
29
|
my $self = shift; |
1905
|
26
|
|
|
|
|
27
|
my $class = $_[0]; |
1906
|
26
|
|
|
|
|
30
|
my $form = ''; |
1907
|
26
|
50
|
|
|
|
52
|
$form .= Class::Generate::Support::comment_form($self->comment) if defined $self->comment; |
1908
|
26
|
|
|
|
|
49
|
$form .= $class->sub_form($self->name, $self->name, Class::Generate::Member_Names::substituted($self->body)); |
1909
|
26
|
|
|
|
|
89
|
return $form; |
1910
|
|
|
|
|
|
|
} |
1911
|
|
|
|
|
|
|
|
1912
|
|
|
|
|
|
|
package Class::Generate::Class_Method; # A user-defined class method, |
1913
|
14
|
|
|
14
|
|
1803
|
use strict; # which may specify objects |
|
14
|
|
|
|
|
33
|
|
|
14
|
|
|
|
|
426
|
|
1914
|
14
|
|
|
14
|
|
137
|
use vars qw(@ISA); # of the class used within its |
|
14
|
|
|
|
|
30
|
|
|
14
|
|
|
|
|
2499
|
|
1915
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Method); # body. |
1916
|
|
|
|
|
|
|
|
1917
|
|
|
|
|
|
|
sub objects { |
1918
|
1
|
|
|
1
|
|
1
|
my $self = shift; |
1919
|
1
|
50
|
|
|
|
7
|
return exists $self->{'objects'} ? @{$self->{'objects'}} : () if $#_ == -1; |
|
0
|
50
|
|
|
|
0
|
|
1920
|
0
|
0
|
|
|
|
0
|
return exists $self->{'objects'} ? $self->{'objects'}->[$_[0]] : undef if $#_ == 0; |
|
|
0
|
|
|
|
|
|
1921
|
0
|
|
|
|
|
0
|
$self->{'objects'}->[$_[0]] = $_[1]; |
1922
|
|
|
|
|
|
|
} |
1923
|
|
|
|
|
|
|
sub add_objects { |
1924
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
1925
|
0
|
|
|
|
|
0
|
push @{$self->{'objects'}}, @_; |
|
0
|
|
|
|
|
0
|
|
1926
|
|
|
|
|
|
|
} |
1927
|
|
|
|
|
|
|
|
1928
|
|
|
|
|
|
|
sub form { |
1929
|
2
|
|
|
2
|
|
5
|
my $self = shift; |
1930
|
2
|
|
|
|
|
4
|
my $class = $_[0]; |
1931
|
2
|
|
|
|
|
7
|
return $class->class_sub_form($self->name, Class::Generate::Member_Names::substituted_in_class_method($self)); |
1932
|
|
|
|
|
|
|
} |
1933
|
|
|
|
|
|
|
|
1934
|
|
|
|
|
|
|
package Class::Generate::Class; # A virtual class describing |
1935
|
14
|
|
|
14
|
|
207
|
use strict; # a user-specified class. |
|
14
|
|
|
|
|
32
|
|
|
14
|
|
|
|
|
43274
|
|
1936
|
|
|
|
|
|
|
|
1937
|
|
|
|
|
|
|
sub new { |
1938
|
62
|
|
|
62
|
|
140
|
my $class = shift; |
1939
|
62
|
|
|
|
|
425
|
my $self = { name => shift, @_ }; |
1940
|
62
|
|
|
|
|
203
|
bless $self, $class; |
1941
|
62
|
|
|
|
|
198
|
return $self; |
1942
|
|
|
|
|
|
|
} |
1943
|
|
|
|
|
|
|
|
1944
|
|
|
|
|
|
|
sub name { |
1945
|
684
|
|
|
684
|
|
647
|
my $self = shift; |
1946
|
684
|
|
|
|
|
3260
|
return $self->{'name'}; |
1947
|
|
|
|
|
|
|
} |
1948
|
|
|
|
|
|
|
sub parents { |
1949
|
815
|
|
|
815
|
|
787
|
my $self = shift; |
1950
|
815
|
100
|
|
|
|
3667
|
return exists $self->{'parents'} ? @{$self->{'parents'}} : () if $#_ == -1; |
|
213
|
50
|
|
|
|
919
|
|
1951
|
0
|
0
|
|
|
|
0
|
return exists $self->{'parents'} ? $self->{'parents'}->[$_[0]] : undef if $#_ == 0; |
|
|
0
|
|
|
|
|
|
1952
|
0
|
|
|
|
|
0
|
$self->{'parents'}->[$_[0]] = $_[1]; |
1953
|
|
|
|
|
|
|
} |
1954
|
|
|
|
|
|
|
sub add_parents { |
1955
|
15
|
|
|
15
|
|
26
|
my $self = shift; |
1956
|
15
|
|
|
|
|
26
|
push @{$self->{'parents'}}, @_; |
|
15
|
|
|
|
|
75
|
|
1957
|
|
|
|
|
|
|
} |
1958
|
|
|
|
|
|
|
sub members { |
1959
|
725
|
|
|
725
|
|
705
|
my $self = shift; |
1960
|
725
|
100
|
|
|
|
1767
|
return exists $self->{'members'} ? %{$self->{'members'}} : () if $#_ == -1; |
|
52
|
100
|
|
|
|
589
|
|
1961
|
664
|
100
|
|
|
|
3324
|
return exists $self->{'members'} ? $self->{'members'}->{$_[0]} : undef if $#_ == 0; |
|
|
100
|
|
|
|
|
|
1962
|
133
|
|
|
|
|
330
|
$self->{'members'}->{$_[0]} = $_[1]; |
1963
|
|
|
|
|
|
|
} |
1964
|
|
|
|
|
|
|
sub members_keys { |
1965
|
490
|
|
|
490
|
|
450
|
my $self = shift; |
1966
|
490
|
100
|
|
|
|
928
|
return exists $self->{'members'} ? keys %{$self->{'members'}} : (); |
|
434
|
|
|
|
|
1657
|
|
1967
|
|
|
|
|
|
|
} |
1968
|
|
|
|
|
|
|
sub members_values { |
1969
|
653
|
|
|
653
|
|
689
|
my $self = shift; |
1970
|
653
|
100
|
|
|
|
1278
|
return exists $self->{'members'} ? values %{$self->{'members'}} : (); |
|
574
|
|
|
|
|
2566
|
|
1971
|
|
|
|
|
|
|
} |
1972
|
|
|
|
|
|
|
sub user_defined_methods { |
1973
|
161
|
|
|
161
|
|
202
|
my $self = shift; |
1974
|
161
|
100
|
|
|
|
588
|
return exists $self->{'udm'} ? %{$self->{'udm'}} : () if $#_ == -1; |
|
13
|
100
|
|
|
|
213
|
|
1975
|
100
|
100
|
|
|
|
839
|
return exists $self->{'udm'} ? $self->{'udm'}->{$_[0]} : undef if $#_ == 0; |
|
|
100
|
|
|
|
|
|
1976
|
28
|
|
|
|
|
64
|
$self->{'udm'}->{$_[0]} = $_[1]; |
1977
|
|
|
|
|
|
|
} |
1978
|
|
|
|
|
|
|
sub user_defined_methods_keys { |
1979
|
200
|
|
|
200
|
|
222
|
my $self = shift; |
1980
|
200
|
100
|
|
|
|
680
|
return exists $self->{'udm'} ? keys %{$self->{'udm'}} : (); |
|
46
|
|
|
|
|
195
|
|
1981
|
|
|
|
|
|
|
} |
1982
|
|
|
|
|
|
|
sub user_defined_methods_values { |
1983
|
311
|
|
|
311
|
|
435
|
my $self = shift; |
1984
|
311
|
100
|
|
|
|
1024
|
return exists $self->{'udm'} ? values %{$self->{'udm'}} : (); |
|
70
|
|
|
|
|
376
|
|
1985
|
|
|
|
|
|
|
} |
1986
|
|
|
|
|
|
|
sub class_vars { |
1987
|
123
|
|
|
123
|
|
168
|
my $self = shift; |
1988
|
123
|
100
|
|
|
|
559
|
return exists $self->{'class_vars'} ? @{$self->{'class_vars'}} : () if $#_ == -1; |
|
3
|
50
|
|
|
|
9
|
|
1989
|
0
|
0
|
|
|
|
0
|
return exists $self->{'class_vars'} ? $self->{'class_vars'}->[$_[0]] : undef if $#_ == 0; |
|
|
0
|
|
|
|
|
|
1990
|
0
|
|
|
|
|
0
|
$self->{'class_vars'}->[$_[0]] = $_[1]; |
1991
|
|
|
|
|
|
|
} |
1992
|
|
|
|
|
|
|
sub add_class_vars { |
1993
|
1
|
|
|
1
|
|
10
|
my $self = shift; |
1994
|
1
|
|
|
|
|
1
|
push @{$self->{'class_vars'}}, @_; |
|
1
|
|
|
|
|
3
|
|
1995
|
|
|
|
|
|
|
} |
1996
|
|
|
|
|
|
|
sub use_packages { |
1997
|
126
|
|
|
126
|
|
152
|
my $self = shift; |
1998
|
126
|
100
|
|
|
|
603
|
return exists $self->{'use_packages'} ? @{$self->{'use_packages'}} : () if $#_ == -1; |
|
12
|
50
|
|
|
|
78
|
|
1999
|
0
|
0
|
|
|
|
0
|
return exists $self->{'use_packages'} ? $self->{'use_packages'}->[$_[0]] : undef if $#_ == 0; |
|
|
0
|
|
|
|
|
|
2000
|
0
|
|
|
|
|
0
|
$self->{'use_packages'}->[$_[0]] = $_[1]; |
2001
|
|
|
|
|
|
|
} |
2002
|
|
|
|
|
|
|
sub add_use_packages { |
2003
|
4
|
|
|
4
|
|
7
|
my $self = shift; |
2004
|
4
|
|
|
|
|
5
|
push @{$self->{'use_packages'}}, @_; |
|
4
|
|
|
|
|
18
|
|
2005
|
|
|
|
|
|
|
} |
2006
|
|
|
|
|
|
|
sub excluded_methods_regexp { |
2007
|
1843
|
|
|
1843
|
|
1393
|
my $self = shift; |
2008
|
1843
|
100
|
|
|
|
3940
|
return $self->{'em'} if $#_ == -1; |
2009
|
7
|
|
|
|
|
20
|
$self->{'em'} = $_[0]; |
2010
|
|
|
|
|
|
|
} |
2011
|
|
|
|
|
|
|
sub private { |
2012
|
2244
|
|
|
2244
|
|
1787
|
my $self = shift; |
2013
|
2244
|
100
|
|
|
|
3619
|
return exists $self->{'private'} ? %{$self->{'private'}} : () if $#_ == -1; |
|
4
|
100
|
|
|
|
14
|
|
2014
|
2183
|
100
|
|
|
|
9643
|
return exists $self->{'private'} ? $self->{'private'}->{$_[0]} : undef if $#_ == 0; |
|
|
100
|
|
|
|
|
|
2015
|
6
|
|
|
|
|
34
|
$self->{'private'}->{$_[0]} = $_[1]; |
2016
|
|
|
|
|
|
|
} |
2017
|
|
|
|
|
|
|
sub protected { |
2018
|
1675
|
|
|
1675
|
|
1397
|
my $self = shift; |
2019
|
1675
|
100
|
|
|
|
2655
|
return exists $self->{'protected'} ? %{$self->{'protected'}} : () if $#_ == -1; |
|
4
|
100
|
|
|
|
16
|
|
2020
|
1614
|
100
|
|
|
|
6624
|
return exists $self->{'protected'} ? $self->{'protected'}->{$_[0]} : undef if $#_ == 0; |
|
|
100
|
|
|
|
|
|
2021
|
9
|
|
|
|
|
37
|
$self->{'protected'}->{$_[0]} = $_[1]; |
2022
|
|
|
|
|
|
|
} |
2023
|
|
|
|
|
|
|
sub required { |
2024
|
681
|
|
|
681
|
|
716
|
my $self = shift; |
2025
|
681
|
0
|
|
|
|
1144
|
return exists $self->{'required'} ? %{$self->{'required'}} : () if $#_ == -1; |
|
0
|
50
|
|
|
|
0
|
|
2026
|
681
|
100
|
|
|
|
3720
|
return exists $self->{'required'} ? $self->{'required'}->{$_[0]} : undef if $#_ == 0; |
|
|
100
|
|
|
|
|
|
2027
|
34
|
|
|
|
|
171
|
$self->{'required'}->{$_[0]} = $_[1]; |
2028
|
|
|
|
|
|
|
} |
2029
|
|
|
|
|
|
|
sub readonly { |
2030
|
743
|
|
|
743
|
|
620
|
my $self = shift; |
2031
|
743
|
0
|
|
|
|
1251
|
return exists $self->{'readonly'} ? %{$self->{'readonly'}} : () if $#_ == -1; |
|
0
|
50
|
|
|
|
0
|
|
2032
|
743
|
100
|
|
|
|
3541
|
return exists $self->{'readonly'} ? $self->{'readonly'}->{$_[0]} : undef if $#_ == 0; |
|
|
100
|
|
|
|
|
|
2033
|
26
|
|
|
|
|
129
|
$self->{'readonly'}->{$_[0]} = $_[1]; |
2034
|
|
|
|
|
|
|
} |
2035
|
|
|
|
|
|
|
sub constructor { |
2036
|
491
|
|
|
491
|
|
487
|
my $self = shift; |
2037
|
491
|
100
|
|
|
|
1766
|
return $self->{'constructor'} if $#_ == -1; |
2038
|
62
|
|
|
|
|
216
|
$self->{'constructor'} = $_[0]; |
2039
|
|
|
|
|
|
|
} |
2040
|
|
|
|
|
|
|
sub virtual { |
2041
|
66
|
|
|
66
|
|
100
|
my $self = shift; |
2042
|
66
|
50
|
|
|
|
411
|
return $self->{'virtual'} if $#_ == -1; |
2043
|
0
|
|
|
|
|
0
|
$self->{'virtual'} = $_[0]; |
2044
|
|
|
|
|
|
|
} |
2045
|
|
|
|
|
|
|
sub comment { |
2046
|
62
|
|
|
62
|
|
492
|
my $self = shift; |
2047
|
62
|
50
|
|
|
|
328
|
return $self->{'comment'} if $#_ == -1; |
2048
|
0
|
|
|
|
|
0
|
$self->{'comment'} = $_[0]; |
2049
|
|
|
|
|
|
|
} |
2050
|
|
|
|
|
|
|
sub accept_refs { |
2051
|
61
|
|
|
61
|
|
70
|
my $self = shift; |
2052
|
61
|
|
|
|
|
159
|
return $self->{'accept_refs'}; |
2053
|
|
|
|
|
|
|
} |
2054
|
|
|
|
|
|
|
sub strict { |
2055
|
122
|
|
|
122
|
|
140
|
my $self = shift; |
2056
|
122
|
|
|
|
|
938
|
return $self->{'strict'}; |
2057
|
|
|
|
|
|
|
} |
2058
|
|
|
|
|
|
|
sub nfi { |
2059
|
57
|
|
|
57
|
|
87
|
my $self = shift; |
2060
|
57
|
|
|
|
|
241
|
return $self->{'nfi'}; |
2061
|
|
|
|
|
|
|
} |
2062
|
|
|
|
|
|
|
sub warnings { |
2063
|
61
|
|
|
61
|
|
156
|
my $self = shift; |
2064
|
61
|
50
|
|
|
|
221
|
return $self->{'warnings'} if $#_ == -1; |
2065
|
61
|
|
|
|
|
144
|
$self->{'warnings'} = $_[0]; |
2066
|
|
|
|
|
|
|
} |
2067
|
|
|
|
|
|
|
sub check_params { |
2068
|
1318
|
|
|
1318
|
|
1099
|
my $self = shift; |
2069
|
1318
|
100
|
|
|
|
6968
|
return $self->{'check_params'} if $#_ == -1; |
2070
|
61
|
|
|
|
|
129
|
$self->{'check_params'} = $_[0]; |
2071
|
|
|
|
|
|
|
} |
2072
|
|
|
|
|
|
|
sub instance_methods { |
2073
|
2
|
|
|
2
|
|
4
|
my $self = shift; |
2074
|
2
|
|
|
|
|
6
|
return grep ! $_->isa('Class::Generate::Class_Method'), $self->user_defined_methods_values; |
2075
|
|
|
|
|
|
|
} |
2076
|
|
|
|
|
|
|
sub class_methods { |
2077
|
61
|
|
|
61
|
|
104
|
my $self = shift; |
2078
|
61
|
|
|
|
|
220
|
return grep $_->isa('Class::Generate::Class_Method'), $self->user_defined_methods_values; |
2079
|
|
|
|
|
|
|
} |
2080
|
|
|
|
|
|
|
sub include_method { |
2081
|
1714
|
|
|
1714
|
|
1316
|
my $self = shift; |
2082
|
1714
|
|
|
|
|
1342
|
my $method_name = $_[0]; |
2083
|
1714
|
|
|
|
|
2008
|
my $r = $self->excluded_methods_regexp; |
2084
|
1714
|
|
100
|
|
|
5613
|
return ! defined $r || $method_name !~ m/$r/; |
2085
|
|
|
|
|
|
|
} |
2086
|
|
|
|
|
|
|
sub member_methods_form { # Return a form containing methods for all |
2087
|
61
|
|
|
61
|
|
102
|
my $self = shift; # non-private members in the class, plus |
2088
|
61
|
|
|
|
|
120
|
my $form = ''; # private members used in class methods. |
2089
|
61
|
|
|
|
|
152
|
for my $element ( $self->public_member_names, $self->protected_member_names, $self->private_members_used_in_user_defined_code ) { |
2090
|
132
|
|
|
|
|
307
|
$form .= $self->members($element)->form($self); |
2091
|
|
|
|
|
|
|
} |
2092
|
61
|
100
|
|
|
|
255
|
$form .= "\n" if $form ne ''; |
2093
|
61
|
|
|
|
|
330
|
return $form; |
2094
|
|
|
|
|
|
|
} |
2095
|
|
|
|
|
|
|
|
2096
|
|
|
|
|
|
|
sub user_defined_methods_form { # Return a form containing all |
2097
|
61
|
|
|
61
|
|
93
|
my $self = shift; # user-defined methods. |
2098
|
61
|
|
|
|
|
179
|
my $form = join('', map($_->form($self), $self->user_defined_methods_values)); |
2099
|
61
|
100
|
|
|
|
271
|
return length $form > 0 ? $form . "\n" : ''; |
2100
|
|
|
|
|
|
|
} |
2101
|
|
|
|
|
|
|
|
2102
|
|
|
|
|
|
|
sub warnings_pragmas { # Return an array containing the |
2103
|
122
|
|
|
122
|
|
180
|
my $self = shift; # warnings pragmas for the class. |
2104
|
122
|
|
|
|
|
190
|
my $w = $self->{'warnings'}; |
2105
|
122
|
50
|
|
|
|
318
|
return () if ! defined $w; |
2106
|
122
|
50
|
|
|
|
199
|
return ('no warnings;') if ! $w; |
2107
|
122
|
50
|
|
|
|
1010
|
return ('use warnings;') if $w =~ /^\d+$/; |
2108
|
0
|
0
|
|
|
|
0
|
return ("use warnings $w;") if ! ref $w; |
2109
|
|
|
|
|
|
|
|
2110
|
0
|
|
|
|
|
0
|
my @pragmas; |
2111
|
0
|
|
|
|
|
0
|
for ( my $i = 0; $i <= $#$w; $i += 2 ) { |
2112
|
0
|
|
|
|
|
0
|
my ($key, $value) = ($$w[$i], $$w[$i+1]); |
2113
|
0
|
0
|
0
|
|
|
0
|
if ( $key eq 'register' ) { |
|
|
0
|
|
|
|
|
|
2114
|
0
|
0
|
|
|
|
0
|
push @pragmas, 'use warnings::register;' if $value; |
2115
|
|
|
|
|
|
|
} |
2116
|
|
|
|
|
|
|
elsif ( defined $value && $value ) { |
2117
|
0
|
0
|
|
|
|
0
|
if ( $value =~ /^\d+$/ ) { |
2118
|
0
|
|
|
|
|
0
|
push @pragmas, $key . ' warnings;'; |
2119
|
|
|
|
|
|
|
} |
2120
|
|
|
|
|
|
|
else { |
2121
|
0
|
|
|
|
|
0
|
push @pragmas, $key . ' warnings ' . $value . ';'; |
2122
|
|
|
|
|
|
|
} |
2123
|
|
|
|
|
|
|
} |
2124
|
|
|
|
|
|
|
} |
2125
|
0
|
|
|
|
|
0
|
return @pragmas; |
2126
|
|
|
|
|
|
|
} |
2127
|
|
|
|
|
|
|
|
2128
|
|
|
|
|
|
|
sub warnings_form { # Return a form representing the |
2129
|
61
|
|
|
61
|
|
81
|
my $self = shift; # warnings pragmas for a class. |
2130
|
61
|
|
|
|
|
151
|
my @warnings_pragmas = $self->warnings_pragmas; |
2131
|
61
|
50
|
|
|
|
311
|
return @warnings_pragmas ? join("\n", @warnings_pragmas) . "\n" : ''; |
2132
|
|
|
|
|
|
|
} |
2133
|
|
|
|
|
|
|
|
2134
|
|
|
|
|
|
|
sub form { # Return a form representing |
2135
|
61
|
|
|
61
|
|
88
|
my $self = shift; # a class. |
2136
|
61
|
|
|
|
|
78
|
my $form; |
2137
|
61
|
|
|
|
|
159
|
$form = 'package ' . $self->name . ";\n"; |
2138
|
61
|
50
|
|
|
|
162
|
$form .= "use strict;\n" if $self->strict; |
2139
|
61
|
100
|
|
|
|
154
|
$form .= join("\n", map("use $_;", $self->use_packages)) . "\n" if $self->use_packages; |
2140
|
61
|
50
|
|
|
|
239
|
$form .= "use Carp;\n" if defined $self->{'check_params'}; |
2141
|
61
|
|
|
|
|
218
|
$form .= $self->warnings_form; |
2142
|
61
|
|
|
|
|
211
|
$form .= Class::Generate::Class_Holder::form($self); |
2143
|
61
|
|
|
|
|
128
|
$form .= "\n"; |
2144
|
61
|
100
|
|
|
|
597
|
$form .= Class::Generate::Support::comment_form($self->comment) if defined $self->comment; |
2145
|
61
|
100
|
|
|
|
156
|
$form .= $self->isa_decl_form if $self->parents; |
2146
|
61
|
100
|
|
|
|
184
|
$form .= $self->private_methods_decl_form if grep $self->private($_), $self->user_defined_methods_keys; |
2147
|
61
|
100
|
|
|
|
269
|
$form .= $self->private_members_decl_form if $self->private_members_used_in_user_defined_code; |
2148
|
61
|
100
|
|
|
|
147
|
$form .= $self->protected_methods_decl_form if grep $self->protected($_), $self->user_defined_methods_keys; |
2149
|
61
|
100
|
|
|
|
131
|
$form .= $self->protected_members_decl_form if grep $self->protected($_), $self->members_keys; |
2150
|
61
|
100
|
|
|
|
203
|
$form .= join("\n", map(class_var_form($_), $self->class_vars)) . "\n\n" if $self->class_vars; |
2151
|
61
|
100
|
|
|
|
238
|
$form .= $self->constructor->form($self) if $self->needs_constructor; |
2152
|
61
|
|
|
|
|
381
|
$form .= $self->member_methods_form; |
2153
|
61
|
|
|
|
|
294
|
$form .= $self->user_defined_methods_form; |
2154
|
61
|
|
|
|
|
153
|
my $emr = $self->excluded_methods_regexp; |
2155
|
61
|
100
|
66
|
|
|
496
|
$form .= $self->copy_form if ! defined $emr || 'copy' !~ m/$emr/; |
2156
|
61
|
50
|
66
|
|
|
501
|
$form .= $self->equals_form if (! defined $emr || 'equals' !~ m/$emr/) && |
|
|
|
66
|
|
|
|
|
2157
|
|
|
|
|
|
|
! defined $self->user_defined_methods('equals'); |
2158
|
61
|
|
|
|
|
238
|
return $form; |
2159
|
|
|
|
|
|
|
} |
2160
|
|
|
|
|
|
|
|
2161
|
|
|
|
|
|
|
sub class_var_form { # Return a form for declaring a class |
2162
|
1
|
|
|
1
|
|
1
|
my $var_spec = $_[0]; # variable. Account for an initial value. |
2163
|
1
|
50
|
|
|
|
6
|
return "my $var_spec;" if ! ref $var_spec; |
2164
|
0
|
|
|
|
|
0
|
return map { my $value = $$var_spec{$_}; |
|
0
|
|
|
|
|
0
|
|
2165
|
0
|
0
|
|
|
|
0
|
"my $_ = " . (ref $value ? substr($_, 0, 1) . "{$value}" : $value) . ';' |
2166
|
|
|
|
|
|
|
} keys %$var_spec; |
2167
|
|
|
|
|
|
|
} |
2168
|
|
|
|
|
|
|
|
2169
|
|
|
|
|
|
|
sub isa_decl_form { |
2170
|
15
|
|
|
15
|
|
26
|
my $self = shift; |
2171
|
15
|
50
|
|
|
|
39
|
my @parent_names = map ! ref $_ ? $_ : $_->name, $self->parents; |
2172
|
15
|
|
|
|
|
74
|
return "use vars qw(\@ISA);\n" . |
2173
|
|
|
|
|
|
|
'@ISA = qw(' . join(' ', @parent_names) . ");\n"; |
2174
|
|
|
|
|
|
|
} |
2175
|
|
|
|
|
|
|
|
2176
|
|
|
|
|
|
|
sub sub_form { # Return a declaration for a sub, as an |
2177
|
426
|
|
|
426
|
|
378
|
my $self = shift; # assignment to a variable if not public. |
2178
|
426
|
|
|
|
|
498
|
my ($element_name, $sub_name, $body) = @_; |
2179
|
426
|
|
|
|
|
337
|
my ($form, $not_public); |
2180
|
426
|
|
100
|
|
|
630
|
$not_public = $self->private($element_name) || $self->protected($element_name); |
2181
|
426
|
100
|
|
|
|
1149
|
$form = ($not_public ? "\$$sub_name = sub" : "sub $sub_name") . " {\n" . |
2182
|
|
|
|
|
|
|
' my ' . $self->instance_var . " = shift;\n" . |
2183
|
|
|
|
|
|
|
$body . |
2184
|
|
|
|
|
|
|
'}'; |
2185
|
426
|
100
|
|
|
|
771
|
$form .= ';' if $not_public; |
2186
|
426
|
|
|
|
|
1270
|
return $form . "\n"; |
2187
|
|
|
|
|
|
|
} |
2188
|
|
|
|
|
|
|
|
2189
|
|
|
|
|
|
|
sub class_sub_form { # Ditto, but for a class method. |
2190
|
2
|
|
|
2
|
|
2
|
my $self = shift; |
2191
|
2
|
|
|
|
|
4
|
my ($method_name, $body) = @_; |
2192
|
2
|
|
|
|
|
3
|
my ($form, $not_public); |
2193
|
2
|
|
33
|
|
|
5
|
$not_public = $self->private($method_name) || $self->protected($method_name); |
2194
|
2
|
50
|
|
|
|
14
|
$form = ($not_public ? "\$$method_name = sub" : "sub $method_name") . " {\n" . |
2195
|
|
|
|
|
|
|
' my ' . $self->class_var . " = shift;\n" . |
2196
|
|
|
|
|
|
|
$body . |
2197
|
|
|
|
|
|
|
'}'; |
2198
|
2
|
50
|
|
|
|
5
|
$form .= ';' if $not_public; |
2199
|
2
|
|
|
|
|
14
|
return $form . "\n"; |
2200
|
|
|
|
|
|
|
} |
2201
|
|
|
|
|
|
|
|
2202
|
|
|
|
|
|
|
sub private_methods_decl_form { # Private methods are implemented as CODE refs. |
2203
|
1
|
|
|
1
|
|
2
|
my $self = shift; # Return a form declaring the variables to hold them. |
2204
|
1
|
|
|
|
|
2
|
my @private_methods = grep $self->private($_), $self->user_defined_methods_keys; |
2205
|
1
|
|
|
|
|
5
|
return Class::Generate::Support::my_decl_form(map "\$$_", @private_methods); |
2206
|
|
|
|
|
|
|
} |
2207
|
|
|
|
|
|
|
|
2208
|
|
|
|
|
|
|
sub private_members_used_in_user_defined_code { # Return the names of all private |
2209
|
124
|
|
|
124
|
|
154
|
my $self = shift; # members that appear in user-defined code. |
2210
|
124
|
|
|
|
|
369
|
my @private_members = grep $self->private($_), $self->members_keys; |
2211
|
124
|
100
|
|
|
|
450
|
return () if ! @private_members; |
2212
|
8
|
|
|
|
|
17
|
my $member_regexp = join '|', @private_members; |
2213
|
8
|
|
|
|
|
8
|
my %private_members; |
2214
|
8
|
|
|
|
|
14
|
for my $code ( map($_->body, $self->user_defined_methods_values), |
2215
|
|
|
|
|
|
|
grep(defined $_, (map(($_->pre, $_->post, $_->assert), $self->members_values), |
2216
|
|
|
|
|
|
|
map(($_->post, $_->assert), $self->constructor))) ) { |
2217
|
21
|
|
|
|
|
137
|
while ( $code =~ /($member_regexp)/g ) { |
2218
|
66
|
|
|
|
|
192
|
$private_members{$1}++; |
2219
|
|
|
|
|
|
|
} |
2220
|
|
|
|
|
|
|
} |
2221
|
8
|
|
|
|
|
54
|
return keys %private_members; |
2222
|
|
|
|
|
|
|
} |
2223
|
|
|
|
|
|
|
|
2224
|
|
|
|
|
|
|
sub nonpublic_members_decl_form { |
2225
|
6
|
|
|
6
|
|
9
|
my $self = shift; |
2226
|
6
|
|
|
|
|
10
|
my @members = @_; |
2227
|
6
|
|
|
|
|
19
|
my @accessor_names = map($_->accessor_names($self, $_->name), @members); |
2228
|
6
|
|
|
|
|
40
|
return Class::Generate::Support::my_decl_form(map "\$$_", @accessor_names); |
2229
|
|
|
|
|
|
|
} |
2230
|
|
|
|
|
|
|
|
2231
|
|
|
|
|
|
|
sub private_members_decl_form { |
2232
|
2
|
|
|
2
|
|
4
|
my $self = shift; |
2233
|
2
|
|
|
|
|
8
|
return $self->nonpublic_members_decl_form(map $self->members($_), $self->private_members_used_in_user_defined_code); |
2234
|
|
|
|
|
|
|
} |
2235
|
|
|
|
|
|
|
|
2236
|
|
|
|
|
|
|
sub protected_methods_decl_form { |
2237
|
1
|
|
|
1
|
|
2
|
my $self = shift; |
2238
|
1
|
100
|
|
|
|
3
|
return Class::Generate::Support::my_decl_form(map $self->protected($_) ? "\$$_" : (), $self->user_defined_methods_keys); |
2239
|
|
|
|
|
|
|
} |
2240
|
|
|
|
|
|
|
sub protected_members_decl_form { |
2241
|
4
|
|
|
4
|
|
5
|
my $self = shift; |
2242
|
4
|
|
|
|
|
8
|
return $self->nonpublic_members_decl_form(grep $self->protected($_->name), $self->members_values); |
2243
|
|
|
|
|
|
|
} |
2244
|
|
|
|
|
|
|
sub protected_members_info_form { |
2245
|
57
|
|
|
57
|
|
92
|
my $self = shift; |
2246
|
57
|
|
|
|
|
155
|
my @protected_members = grep $self->protected($_->name), $self->members_values; |
2247
|
57
|
|
|
|
|
206
|
my @protected_methods = grep $self->protected($_->name), $self->user_defined_methods_values; |
2248
|
57
|
100
|
66
|
|
|
378
|
return '' if ! (@protected_members || @protected_methods); |
2249
|
4
|
|
|
|
|
8
|
my $info_index_lvalue = $self->instance_var . '->' . $self->protected_members_info_index; |
2250
|
4
|
|
|
|
|
9
|
my @protected_element_names = (map($_->accessor_names($class, $_->name), @protected_members), |
2251
|
|
|
|
|
|
|
map($_->name, @protected_methods)); |
2252
|
4
|
50
|
|
|
|
11
|
if ( $self->parents ) { |
2253
|
0
|
|
|
|
|
0
|
my $form = ''; |
2254
|
0
|
|
|
|
|
0
|
for my $element_name ( @protected_element_names ) { |
2255
|
0
|
|
|
|
|
0
|
$form .= " ${info_index_lvalue}->{'$element_name'} = \$$element_name;\n"; |
2256
|
|
|
|
|
|
|
} |
2257
|
0
|
|
|
|
|
0
|
return $form; |
2258
|
|
|
|
|
|
|
} |
2259
|
|
|
|
|
|
|
else { |
2260
|
4
|
|
|
|
|
43
|
return " $info_index_lvalue = { " . join(', ', map "$_ => \$$_", @protected_element_names) . " };\n"; |
2261
|
|
|
|
|
|
|
} |
2262
|
|
|
|
|
|
|
} |
2263
|
|
|
|
|
|
|
|
2264
|
|
|
|
|
|
|
sub copy_form { |
2265
|
59
|
|
|
59
|
|
89
|
my $self = shift; |
2266
|
59
|
|
|
|
|
79
|
my ($form, @members, $has_parents); |
2267
|
59
|
|
|
|
|
147
|
@members = $self->members_values; |
2268
|
59
|
|
|
|
|
171
|
$has_parents = defined $self->parents; |
2269
|
59
|
|
|
|
|
126
|
$form = "sub copy {\n" . |
2270
|
|
|
|
|
|
|
" my \$self = shift;\n" . |
2271
|
|
|
|
|
|
|
" my \$copy;\n"; |
2272
|
59
|
100
|
100
|
|
|
84
|
if ( ! (do { my $has_complex_mems; |
2273
|
|
|
|
|
|
|
for my $m ( @members ) { |
2274
|
|
|
|
|
|
|
if ( $m->isa('Class::Generate::List_Member') || defined $m->base ) { |
2275
|
|
|
|
|
|
|
$has_complex_mems = 1; |
2276
|
|
|
|
|
|
|
last; |
2277
|
|
|
|
|
|
|
} |
2278
|
|
|
|
|
|
|
} |
2279
|
|
|
|
|
|
|
$has_complex_mems |
2280
|
|
|
|
|
|
|
} || $has_parents) ) { |
2281
|
20
|
|
|
|
|
78
|
$form .= ' $copy = ' . $self->wholesale_copy . ";\n"; |
2282
|
|
|
|
|
|
|
} |
2283
|
|
|
|
|
|
|
else { |
2284
|
39
|
100
|
|
|
|
185
|
$form .= ' $copy = ' . ($has_parents ? '$self->SUPER::copy' : $self->empty_form) . ";\n"; |
2285
|
39
|
100
|
|
|
|
220
|
$form .= $self->size_establishment('$copy') if $self->can('size_establishment'); |
2286
|
39
|
|
|
|
|
74
|
for my $m ( @members ) { |
2287
|
96
|
|
|
|
|
168
|
my $index = $self->index($m->name); |
2288
|
96
|
|
|
|
|
335
|
$form .= $m->copy_form('$self->' . $index, '$copy->' . $index); |
2289
|
|
|
|
|
|
|
} |
2290
|
|
|
|
|
|
|
} |
2291
|
59
|
|
|
|
|
124
|
$form .= " bless \$copy, ref \$self;\n" . |
2292
|
|
|
|
|
|
|
" return \$copy;\n" . |
2293
|
|
|
|
|
|
|
"}\n"; |
2294
|
59
|
|
|
|
|
257
|
return $form; |
2295
|
|
|
|
|
|
|
} |
2296
|
|
|
|
|
|
|
|
2297
|
|
|
|
|
|
|
sub equals_form { |
2298
|
59
|
|
|
59
|
|
85
|
my $self = shift; |
2299
|
59
|
|
|
|
|
86
|
my ($form, @parents, @members, $existence_test, @local_vars, @key_members); |
2300
|
59
|
|
|
|
|
149
|
@parents = $self->parents; |
2301
|
59
|
|
|
|
|
145
|
@members = $self->members_values; |
2302
|
59
|
100
|
|
|
|
294
|
if ( @key_members = grep $_->key, @members ) { |
2303
|
2
|
|
|
|
|
5
|
@members = @key_members; |
2304
|
|
|
|
|
|
|
} |
2305
|
59
|
|
|
|
|
158
|
$existence_test = $self->existence_test; |
2306
|
59
|
|
|
|
|
120
|
$form = "sub equals {\n" . |
2307
|
|
|
|
|
|
|
" my \$self = shift;\n" . |
2308
|
|
|
|
|
|
|
" my \$o = \$_[0];\n"; |
2309
|
59
|
|
|
|
|
120
|
for my $m ( @members ) { |
2310
|
51
|
50
|
|
|
|
381
|
if ( $m->isa('Class::Generate::Hash_Member'), @members ) { |
2311
|
51
|
|
|
|
|
131
|
push @local_vars, qw($self_value_defined @self_keys); |
2312
|
51
|
|
|
|
|
93
|
last; |
2313
|
|
|
|
|
|
|
} |
2314
|
|
|
|
|
|
|
} |
2315
|
59
|
|
|
|
|
116
|
for my $m ( @members ) { |
2316
|
51
|
50
|
|
|
|
346
|
if ( $m->isa('Class::Generate::Array_Member'), @members ) { |
2317
|
51
|
|
|
|
|
80
|
push @local_vars, qw($ub); |
2318
|
51
|
|
|
|
|
72
|
last; |
2319
|
|
|
|
|
|
|
} |
2320
|
|
|
|
|
|
|
} |
2321
|
59
|
100
|
|
|
|
146
|
if ( @local_vars ) { |
2322
|
51
|
|
|
|
|
185
|
$form .= ' my (' . join(', ', @local_vars) . ");\n"; |
2323
|
|
|
|
|
|
|
} |
2324
|
59
|
100
|
|
|
|
286
|
if ( @parents ) { |
2325
|
14
|
|
|
|
|
30
|
$form .= " return undef unless \$self->SUPER::equals(\$o);\n"; |
2326
|
|
|
|
|
|
|
} |
2327
|
59
|
|
|
|
|
216
|
$form .= join("\n", map $_->equals($self->index($_->name), $existence_test), @members) . |
2328
|
|
|
|
|
|
|
" return 1;\n" . |
2329
|
|
|
|
|
|
|
"}\n"; |
2330
|
59
|
|
|
|
|
355
|
return $form; |
2331
|
|
|
|
|
|
|
} |
2332
|
|
|
|
|
|
|
|
2333
|
|
|
|
|
|
|
sub all_members_required { |
2334
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
2335
|
0
|
|
|
|
|
0
|
for my $m ( $self->members_keys ) { |
2336
|
0
|
0
|
0
|
|
|
0
|
return 0 if ! ($self->private($m) || $self->required($m)); |
2337
|
|
|
|
|
|
|
} |
2338
|
0
|
|
|
|
|
0
|
return 1; |
2339
|
|
|
|
|
|
|
} |
2340
|
|
|
|
|
|
|
sub private_member_names { |
2341
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
2342
|
0
|
|
|
|
|
0
|
return grep $self->private($_), $self->members_keys; |
2343
|
|
|
|
|
|
|
} |
2344
|
|
|
|
|
|
|
sub protected_member_names { |
2345
|
61
|
|
|
61
|
|
85
|
my $self = shift; |
2346
|
61
|
|
|
|
|
196
|
return grep $self->protected($_), $self->members_keys; |
2347
|
|
|
|
|
|
|
} |
2348
|
|
|
|
|
|
|
sub public_member_names { |
2349
|
244
|
|
|
244
|
|
288
|
my $self = shift; |
2350
|
244
|
|
100
|
|
|
470
|
return grep ! ($self->private($_) || $self->protected($_)), $self->members_keys; |
2351
|
|
|
|
|
|
|
} |
2352
|
|
|
|
|
|
|
|
2353
|
|
|
|
|
|
|
sub class_var { |
2354
|
72
|
|
|
72
|
|
104
|
my $self = shift; |
2355
|
72
|
|
|
|
|
273
|
return '$' . $self->{'class_var'}; |
2356
|
|
|
|
|
|
|
} |
2357
|
|
|
|
|
|
|
sub instance_var { |
2358
|
940
|
|
|
940
|
|
813
|
my $self = shift; |
2359
|
940
|
|
|
|
|
2790
|
return '$' . $self->{'instance_var'}; |
2360
|
|
|
|
|
|
|
} |
2361
|
|
|
|
|
|
|
sub needs_constructor { |
2362
|
61
|
|
|
61
|
|
96
|
my $self = shift; |
2363
|
|
|
|
|
|
|
return (defined $self->members || |
2364
|
|
|
|
|
|
|
($self->virtual && $self->check_params) || |
2365
|
|
|
|
|
|
|
! $self->parents || |
2366
|
61
|
|
66
|
|
|
151
|
do { |
2367
|
|
|
|
|
|
|
my $c = $self->constructor; |
2368
|
|
|
|
|
|
|
(defined $c->post || |
2369
|
|
|
|
|
|
|
defined $c->assert || |
2370
|
|
|
|
|
|
|
$c->style->isa('Class::Generate::Own')) |
2371
|
|
|
|
|
|
|
}); |
2372
|
|
|
|
|
|
|
} |
2373
|
|
|
|
|
|
|
|
2374
|
|
|
|
|
|
|
package Class::Generate::Array_Class; # A subclass of Class defining |
2375
|
14
|
|
|
14
|
|
188
|
use strict; # array-based classes. |
|
14
|
|
|
|
|
34
|
|
|
14
|
|
|
|
|
504
|
|
2376
|
14
|
|
|
14
|
|
157
|
use vars qw(@ISA); |
|
14
|
|
|
|
|
30
|
|
|
14
|
|
|
|
|
7451
|
|
2377
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Class); |
2378
|
|
|
|
|
|
|
|
2379
|
|
|
|
|
|
|
sub new { |
2380
|
20
|
|
|
20
|
|
33
|
my $class = shift; |
2381
|
20
|
|
|
|
|
31
|
my $name = shift; |
2382
|
20
|
|
|
|
|
117
|
my %params = @_; |
2383
|
20
|
|
|
|
|
95
|
my %super_params = %params; |
2384
|
20
|
|
|
|
|
58
|
delete @super_params{qw(base_index member_index)}; |
2385
|
20
|
|
|
|
|
137
|
my $self = $class->SUPER::new($name, %super_params); |
2386
|
20
|
100
|
|
|
|
123
|
$self->{'base_index'} = defined $params{'base_index'} ? $params{'base_index'} : 1; |
2387
|
20
|
|
|
|
|
59
|
$self->{'next_index'} = $self->base_index - 1; |
2388
|
20
|
|
|
|
|
90
|
return $self; |
2389
|
|
|
|
|
|
|
} |
2390
|
|
|
|
|
|
|
|
2391
|
|
|
|
|
|
|
sub base_index { |
2392
|
20
|
|
|
20
|
|
25
|
my $self = shift; |
2393
|
20
|
|
|
|
|
65
|
return $self->{'base_index'}; |
2394
|
|
|
|
|
|
|
} |
2395
|
|
|
|
|
|
|
sub base { |
2396
|
17
|
|
|
17
|
|
21
|
my $self = shift; |
2397
|
17
|
50
|
|
|
|
45
|
return '[]' if ! $self->can_assign_all_params; |
2398
|
0
|
|
|
|
|
0
|
my @sorted_members = sort { $$self{member_index}{$a} <=> $$self{member_index}{$b} } $self->members_keys; |
|
0
|
|
|
|
|
0
|
|
2399
|
0
|
|
|
|
|
0
|
my %param_indices = map(($_, $self->constructor->style->order($_)), $self->members_keys); |
2400
|
0
|
|
|
|
|
0
|
for ( my $i = 0; $i <= $#sorted_members; $i++ ) { |
2401
|
0
|
0
|
|
|
|
0
|
next if $param_indices{$sorted_members[$i]} == $i; |
2402
|
0
|
|
|
|
|
0
|
return '[ undef, ' . join(', ', map { '$_[' . $param_indices{$_} . ']' } @sorted_members) . ' ]'; |
|
0
|
|
|
|
|
0
|
|
2403
|
|
|
|
|
|
|
} |
2404
|
0
|
|
|
|
|
0
|
return '[ undef, @_ ]'; |
2405
|
|
|
|
|
|
|
} |
2406
|
|
|
|
|
|
|
sub base_type { |
2407
|
0
|
|
|
0
|
|
0
|
return 'ARRAY'; |
2408
|
|
|
|
|
|
|
} |
2409
|
|
|
|
|
|
|
sub members { |
2410
|
158
|
|
|
158
|
|
122
|
my $self = shift; |
2411
|
158
|
100
|
|
|
|
416
|
return $self->SUPER::members(@_) if $#_ != 1; |
2412
|
31
|
|
|
|
|
100
|
$self->SUPER::members(@_); |
2413
|
31
|
|
|
|
|
25
|
my $overridden_class; |
2414
|
31
|
50
|
|
|
|
68
|
if ( defined ($overridden_class = Class::Generate::Support::class_containing_method($_[0], $self)) ) { |
2415
|
0
|
|
|
|
|
0
|
$self->{'member_index'}{$_[0]} = $overridden_class->{'member_index'}->{$_[0]}; |
2416
|
|
|
|
|
|
|
} |
2417
|
|
|
|
|
|
|
else { |
2418
|
31
|
|
|
|
|
79
|
$self->{'member_index'}{$_[0]} = ++$self->{'next_index'}; |
2419
|
|
|
|
|
|
|
} |
2420
|
|
|
|
|
|
|
} |
2421
|
|
|
|
|
|
|
sub index { |
2422
|
122
|
|
|
122
|
|
88
|
my $self = shift; |
2423
|
122
|
|
|
|
|
285
|
return '[' . $self->{'member_index'}{$_[0]} . ']'; |
2424
|
|
|
|
|
|
|
} |
2425
|
|
|
|
|
|
|
sub last { |
2426
|
47
|
|
|
47
|
|
53
|
my $self = shift; |
2427
|
47
|
|
|
|
|
138
|
return $self->{'next_index'}; |
2428
|
|
|
|
|
|
|
} |
2429
|
|
|
|
|
|
|
sub existence_test { |
2430
|
47
|
|
|
47
|
|
45
|
my $self = shift; |
2431
|
47
|
|
|
|
|
82
|
return 'defined'; |
2432
|
|
|
|
|
|
|
} |
2433
|
|
|
|
|
|
|
|
2434
|
|
|
|
|
|
|
sub size_establishment { |
2435
|
26
|
|
|
26
|
|
40
|
my $self = shift; |
2436
|
26
|
|
|
|
|
41
|
my $instance_var = $_[0]; |
2437
|
26
|
|
|
|
|
78
|
return ' $#' . $instance_var . ' = ' . $self->last . ";\n"; |
2438
|
|
|
|
|
|
|
} |
2439
|
|
|
|
|
|
|
sub can_assign_all_params { |
2440
|
51
|
|
|
51
|
|
49
|
my $self = shift; |
2441
|
51
|
|
0
|
|
|
75
|
return ! $self->check_params && |
2442
|
|
|
|
|
|
|
$self->all_members_required && |
2443
|
|
|
|
|
|
|
$self->constructor->style->isa('Class::Generate::Positional') && |
2444
|
|
|
|
|
|
|
! defined $self->parents; |
2445
|
|
|
|
|
|
|
} |
2446
|
|
|
|
|
|
|
sub undef_form { |
2447
|
15
|
|
|
15
|
|
50
|
return 'undef'; |
2448
|
|
|
|
|
|
|
} |
2449
|
|
|
|
|
|
|
sub wholesale_copy { |
2450
|
8
|
|
|
8
|
|
27
|
return '[ @$self ]'; |
2451
|
|
|
|
|
|
|
} |
2452
|
|
|
|
|
|
|
sub empty_form { |
2453
|
8
|
|
|
8
|
|
23
|
return '[]'; |
2454
|
|
|
|
|
|
|
} |
2455
|
|
|
|
|
|
|
sub protected_members_info_index { |
2456
|
1
|
|
|
1
|
|
2
|
return q|[0]|; |
2457
|
|
|
|
|
|
|
} |
2458
|
|
|
|
|
|
|
|
2459
|
|
|
|
|
|
|
package Class::Generate::Hash_Class; # A subclass of Class defining |
2460
|
14
|
|
|
14
|
|
238
|
use vars qw(@ISA); # hash-based classes. |
|
14
|
|
|
|
|
29
|
|
|
14
|
|
|
|
|
4195
|
|
2461
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Class); |
2462
|
|
|
|
|
|
|
|
2463
|
|
|
|
|
|
|
sub index { |
2464
|
438
|
|
|
438
|
|
393
|
my $self = shift; |
2465
|
438
|
100
|
|
|
|
736
|
return "{'" . ($self->private($_[0]) ? '*' . $self->name . '_' . $_[0] : $_[0]) . "'}"; |
2466
|
|
|
|
|
|
|
} |
2467
|
|
|
|
|
|
|
sub base { |
2468
|
29
|
|
|
29
|
|
50
|
my $self = shift; |
2469
|
29
|
50
|
|
|
|
73
|
return '{}' if ! $self->can_assign_all_params; |
2470
|
0
|
|
|
|
|
0
|
my $style = $self->constructor->style; |
2471
|
0
|
0
|
|
|
|
0
|
return '{ @_ }' if $style->isa('Class::Generate::Key_Value'); |
2472
|
0
|
|
|
|
|
0
|
my %order = $style->order; |
2473
|
0
|
|
|
|
|
0
|
my $form = '{ ' . join(', ', map("$_ => \$_[$order{$_}]", keys %order)); |
2474
|
0
|
0
|
|
|
|
0
|
if ( $style->isa('Class::Generate::Mix') ) { |
2475
|
0
|
|
|
|
|
0
|
$form .= ', @_[' . $style->pcount . '..$#_]'; |
2476
|
|
|
|
|
|
|
} |
2477
|
0
|
|
|
|
|
0
|
return $form . ' }'; |
2478
|
|
|
|
|
|
|
} |
2479
|
|
|
|
|
|
|
sub base_type { |
2480
|
0
|
|
|
0
|
|
0
|
return 'HASH'; |
2481
|
|
|
|
|
|
|
} |
2482
|
|
|
|
|
|
|
sub existence_test { |
2483
|
144
|
|
|
144
|
|
272
|
return 'exists'; |
2484
|
|
|
|
|
|
|
} |
2485
|
|
|
|
|
|
|
sub can_assign_all_params { |
2486
|
109
|
|
|
109
|
|
120
|
my $self = shift; |
2487
|
109
|
|
0
|
|
|
186
|
return ! $self->check_params && |
2488
|
|
|
|
|
|
|
$self->all_members_required && |
2489
|
|
|
|
|
|
|
! $self->constructor->style->isa('Class::Generate::Own') && |
2490
|
|
|
|
|
|
|
! defined $self->parents; |
2491
|
|
|
|
|
|
|
} |
2492
|
|
|
|
|
|
|
sub undef_form { |
2493
|
73
|
|
|
73
|
|
254
|
return 'delete'; |
2494
|
|
|
|
|
|
|
} |
2495
|
|
|
|
|
|
|
sub wholesale_copy { |
2496
|
12
|
|
|
12
|
|
40
|
return '{ %$self }'; |
2497
|
|
|
|
|
|
|
} |
2498
|
|
|
|
|
|
|
sub empty_form { |
2499
|
17
|
|
|
17
|
|
56
|
return '{}'; |
2500
|
|
|
|
|
|
|
} |
2501
|
|
|
|
|
|
|
sub protected_members_info_index { |
2502
|
9
|
|
|
9
|
|
27
|
return q|{'*protected*'}|; |
2503
|
|
|
|
|
|
|
} |
2504
|
|
|
|
|
|
|
|
2505
|
|
|
|
|
|
|
package Class::Generate::Param_Style; # A virtual class encompassing |
2506
|
14
|
|
|
14
|
|
562
|
use strict; # parameter-passing styles for |
|
15
|
|
|
|
|
37
|
|
|
15
|
|
|
|
|
2804
|
|
2507
|
|
|
|
|
|
|
|
2508
|
|
|
|
|
|
|
sub new { |
2509
|
71
|
|
|
71
|
|
124
|
my $class = shift; |
2510
|
71
|
|
|
|
|
234
|
return bless {}, $class; |
2511
|
|
|
|
|
|
|
} |
2512
|
|
|
|
|
|
|
sub keyed_param_names { |
2513
|
0
|
|
|
0
|
|
0
|
return (); |
2514
|
|
|
|
|
|
|
} |
2515
|
|
|
|
|
|
|
|
2516
|
|
|
|
|
|
|
sub delete_self_members_form { |
2517
|
1
|
|
|
1
|
|
3
|
shift; |
2518
|
1
|
|
|
|
|
3
|
my @self_members = @_; |
2519
|
1
|
50
|
|
|
|
4
|
if ( $#self_members == 0 ) { |
|
|
0
|
|
|
|
|
|
2520
|
1
|
|
|
|
|
13
|
return q|delete $super_params{'| . $self_members[0] . q|'};|; |
2521
|
|
|
|
|
|
|
} |
2522
|
|
|
|
|
|
|
elsif ( $#self_members > 0 ) { |
2523
|
0
|
|
|
|
|
0
|
return q|delete @super_params{qw(| . join(' ', @self_members) . q|)};|; |
2524
|
|
|
|
|
|
|
} |
2525
|
|
|
|
|
|
|
} |
2526
|
|
|
|
|
|
|
|
2527
|
|
|
|
|
|
|
sub odd_params_check_form { |
2528
|
42
|
|
|
42
|
|
61
|
my $self = shift; |
2529
|
42
|
|
|
|
|
63
|
my ($class, $constructor) = @_; |
2530
|
42
|
|
|
|
|
178
|
return q| croak '| . $constructor->name_form($class) . q|Odd number of parameters' if | . |
2531
|
|
|
|
|
|
|
$self->odd_params_test($class) . ";\n"; |
2532
|
|
|
|
|
|
|
} |
2533
|
|
|
|
|
|
|
|
2534
|
|
|
|
|
|
|
sub my_decl_form { |
2535
|
11
|
|
|
11
|
|
22
|
my $self = shift; |
2536
|
11
|
|
|
|
|
20
|
my $class = $_[0]; |
2537
|
11
|
|
|
|
|
31
|
return ' my ' . $class->instance_var . ' = ' . $class->class_var . '->SUPER::new'; |
2538
|
|
|
|
|
|
|
} |
2539
|
|
|
|
|
|
|
|
2540
|
|
|
|
|
|
|
package Class::Generate::Key_Value; # The key/value parameter- |
2541
|
15
|
|
|
14
|
|
1860
|
use strict; # passing style. It adds |
|
14
|
|
|
|
|
27
|
|
|
14
|
|
|
|
|
366
|
|
2542
|
14
|
|
|
14
|
|
197
|
use vars qw(@ISA); # the name of the variable |
|
14
|
|
|
|
|
36
|
|
|
14
|
|
|
|
|
6280
|
|
2543
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Param_Style); # that holds the parameters. |
2544
|
|
|
|
|
|
|
|
2545
|
|
|
|
|
|
|
sub new { |
2546
|
46
|
|
|
46
|
|
75
|
my $class = shift; |
2547
|
46
|
|
|
|
|
216
|
my $self = $class->SUPER::new; |
2548
|
46
|
|
|
|
|
176
|
$self->{'holder'} = $_[0]; |
2549
|
46
|
|
|
|
|
207
|
$self->{'keyed_param_names'} = [@_[1..$#_]]; |
2550
|
46
|
|
|
|
|
197
|
return $self; |
2551
|
|
|
|
|
|
|
} |
2552
|
|
|
|
|
|
|
|
2553
|
|
|
|
|
|
|
sub holder { |
2554
|
176
|
|
|
176
|
|
153
|
my $self = shift; |
2555
|
176
|
|
|
|
|
462
|
return $self->{'holder'}; |
2556
|
|
|
|
|
|
|
} |
2557
|
|
|
|
|
|
|
sub ref { |
2558
|
176
|
|
|
176
|
|
177
|
my $self = shift; |
2559
|
176
|
|
|
|
|
311
|
return '$' . $self->holder . "{'" . $_[0] . "'}"; |
2560
|
|
|
|
|
|
|
} |
2561
|
|
|
|
|
|
|
sub keyed_param_names { |
2562
|
118
|
|
|
118
|
|
150
|
my $self = shift; |
2563
|
118
|
|
|
|
|
104
|
return @{$self->{'keyed_param_names'}}; |
|
118
|
|
|
|
|
373
|
|
2564
|
|
|
|
|
|
|
} |
2565
|
|
|
|
|
|
|
sub existence_test { |
2566
|
176
|
|
|
176
|
|
316
|
return 'exists'; |
2567
|
|
|
|
|
|
|
} |
2568
|
|
|
|
|
|
|
sub init_form { |
2569
|
38
|
|
|
38
|
|
66
|
my $self = shift; |
2570
|
38
|
|
|
|
|
94
|
my ($class, $constructor) = @_; |
2571
|
38
|
|
|
|
|
44
|
my ($form, $cn); |
2572
|
38
|
|
|
|
|
71
|
$form = ''; |
2573
|
38
|
50
|
|
|
|
96
|
$form .= $self->odd_params_check_form($class, $constructor) if $class->check_params; |
2574
|
38
|
|
|
|
|
91
|
$form .= " my \%params = \@_;\n"; |
2575
|
38
|
|
|
|
|
112
|
return $form; |
2576
|
|
|
|
|
|
|
} |
2577
|
|
|
|
|
|
|
sub odd_params_test { |
2578
|
38
|
|
|
38
|
|
131
|
return '$#_%2 == 0'; |
2579
|
|
|
|
|
|
|
} |
2580
|
|
|
|
|
|
|
sub self_from_super_form { |
2581
|
1
|
|
|
1
|
|
2
|
my $self = shift; |
2582
|
1
|
|
|
|
|
2
|
my $class = $_[0]; |
2583
|
1
|
|
|
|
|
4
|
return ' my %super_params = %params;' . "\n" . |
2584
|
|
|
|
|
|
|
' ' . $self->delete_self_members_form($class->public_member_names) . "\n" . |
2585
|
|
|
|
|
|
|
$self->my_decl_form($class) . "(\%super_params);\n"; |
2586
|
|
|
|
|
|
|
} |
2587
|
|
|
|
|
|
|
sub params_check_form { |
2588
|
39
|
|
|
39
|
|
61
|
my $self = shift; |
2589
|
39
|
|
|
|
|
60
|
my ($class, $constructor) = @_; |
2590
|
39
|
|
|
|
|
47
|
my ($cn, @valid_names, $form); |
2591
|
39
|
|
|
|
|
102
|
@valid_names = $self->keyed_param_names; |
2592
|
39
|
|
|
|
|
113
|
$cn = $constructor->name_form($class); |
2593
|
39
|
100
|
|
|
|
110
|
if ( ! @valid_names ) { |
2594
|
5
|
|
|
|
|
10
|
$form = " croak '$cn', join(', ', keys %params), ': Not a member' if keys \%params;\n"; |
2595
|
|
|
|
|
|
|
} |
2596
|
|
|
|
|
|
|
else { |
2597
|
34
|
|
|
|
|
64
|
$form = " {\n"; |
2598
|
34
|
100
|
|
|
|
107
|
if ( $#valid_names == 0 ) { |
2599
|
8
|
|
|
|
|
26
|
$form .= "\tmy \@unknown_params = grep \$_ ne '$valid_names[0]', keys \%params;\n"; |
2600
|
|
|
|
|
|
|
} |
2601
|
|
|
|
|
|
|
else { |
2602
|
26
|
|
|
|
|
218
|
$form .= "\tmy %valid_param = (" . join(', ', map("'$_' => 1", @valid_names)) . ");\n" . |
2603
|
|
|
|
|
|
|
"\tmy \@unknown_params = grep ! defined \$valid_param{\$_}, keys \%params;\n"; |
2604
|
|
|
|
|
|
|
} |
2605
|
34
|
|
|
|
|
144
|
$form .= "\tcroak '$cn', join(', ', \@unknown_params), ': Not a member' if \@unknown_params;\n" . |
2606
|
|
|
|
|
|
|
" }\n"; |
2607
|
|
|
|
|
|
|
} |
2608
|
39
|
|
|
|
|
103
|
return $form; |
2609
|
|
|
|
|
|
|
} |
2610
|
|
|
|
|
|
|
|
2611
|
|
|
|
|
|
|
package Class::Generate::Positional; # The positional parameter- |
2612
|
14
|
|
|
14
|
|
128
|
use strict; # passing style. It adds |
|
13
|
|
|
|
|
25
|
|
|
13
|
|
|
|
|
374
|
|
2613
|
13
|
|
|
15
|
|
405
|
use vars qw(@ISA); # an ordering of parameters. |
|
13
|
|
|
|
|
22
|
|
|
13
|
|
|
|
|
4396
|
|
2614
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Param_Style); |
2615
|
|
|
|
|
|
|
|
2616
|
|
|
|
|
|
|
sub new { |
2617
|
15
|
|
|
15
|
|
27
|
my $class = shift; |
2618
|
15
|
|
|
|
|
79
|
my $self = $class->SUPER::new; |
2619
|
15
|
|
|
|
|
94
|
for ( my $i = 0; $i <= $#_; $i++ ) { |
2620
|
17
|
|
|
|
|
104
|
$self->{'order'}->{$_[$i]} = $i; |
2621
|
|
|
|
|
|
|
} |
2622
|
15
|
|
|
|
|
76
|
return $self; |
2623
|
|
|
|
|
|
|
} |
2624
|
|
|
|
|
|
|
sub order { |
2625
|
27
|
|
|
27
|
|
36
|
my $self = shift; |
2626
|
27
|
100
|
|
|
|
114
|
return exists $self->{'order'} ? %{$self->{'order'}} : () if $#_ == -1; |
|
12
|
100
|
|
|
|
70
|
|
2627
|
12
|
50
|
|
|
|
61
|
return exists $self->{'order'} ? $self->{'order'}->{$_[0]} : undef if $#_ == 0; |
|
|
50
|
|
|
|
|
|
2628
|
0
|
|
|
|
|
0
|
$self->{'order'}->{$_[0]} = $_[1]; |
2629
|
|
|
|
|
|
|
} |
2630
|
|
|
|
|
|
|
sub ref { |
2631
|
28
|
|
|
28
|
|
41
|
my $self = shift; |
2632
|
28
|
|
|
|
|
84
|
return '$_[' . $self->{'order'}->{$_[0]} . ']'; |
2633
|
|
|
|
|
|
|
} |
2634
|
|
|
|
|
|
|
sub existence_test { |
2635
|
28
|
|
|
28
|
|
66
|
return 'defined'; |
2636
|
|
|
|
|
|
|
} |
2637
|
|
|
|
|
|
|
sub self_from_super_form { |
2638
|
4
|
|
|
4
|
|
8
|
my $self = shift; |
2639
|
4
|
|
|
|
|
8
|
my $class = $_[0]; |
2640
|
4
|
|
100
|
|
|
13
|
my $lb = scalar($class->public_member_names) || 0; |
2641
|
4
|
|
|
|
|
46
|
return ' my @super_params = @_[' . $lb . '..$#_];' . "\n" . |
2642
|
|
|
|
|
|
|
$self->my_decl_form($class) . "(\@super_params);\n"; |
2643
|
|
|
|
|
|
|
} |
2644
|
|
|
|
|
|
|
sub params_check_form { |
2645
|
6
|
|
|
6
|
|
18
|
my $self = shift; |
2646
|
6
|
|
|
|
|
11
|
my ($class, $constructor) = @_; |
2647
|
6
|
|
|
|
|
41
|
my $cn = $constructor->name_form($class); |
2648
|
6
|
|
50
|
|
|
23
|
my $max_params = scalar($class->public_member_names) || 0; |
2649
|
6
|
|
|
|
|
44
|
return qq| croak '$cn| . qq|Only $max_params parameter(s) allowed (', \$#_+1, ' given)'| . |
2650
|
|
|
|
|
|
|
" unless \$#_ < $max_params;\n"; |
2651
|
|
|
|
|
|
|
} |
2652
|
|
|
|
|
|
|
|
2653
|
|
|
|
|
|
|
package Class::Generate::Mix; # The mix parameter-passing |
2654
|
13
|
|
|
14
|
|
127
|
use strict; # style. It combines key/value |
|
13
|
|
|
|
|
21
|
|
|
13
|
|
|
|
|
416
|
|
2655
|
13
|
|
|
14
|
|
118
|
use vars qw(@ISA); # and positional. |
|
13
|
|
|
|
|
23
|
|
|
13
|
|
|
|
|
9150
|
|
2656
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Param_Style); |
2657
|
|
|
|
|
|
|
|
2658
|
|
|
|
|
|
|
sub new { |
2659
|
5
|
|
|
5
|
|
10
|
my $class = shift; |
2660
|
5
|
|
|
|
|
27
|
my $self = $class->SUPER::new; |
2661
|
5
|
|
|
|
|
9
|
$self->{'pp'} = Class::Generate::Positional->new(@{$_[1]}); |
|
5
|
|
|
|
|
30
|
|
2662
|
5
|
|
|
|
|
36
|
$self->{'kv'} = Class::Generate::Key_Value->new($_[0], @_[2..$#_]); |
2663
|
5
|
|
|
|
|
15
|
$self->{'pnames'} = { map( ($_ => 1), @{$_[1]}) }; |
|
5
|
|
|
|
|
26
|
|
2664
|
5
|
|
|
|
|
28
|
return $self; |
2665
|
|
|
|
|
|
|
} |
2666
|
|
|
|
|
|
|
|
2667
|
|
|
|
|
|
|
sub keyed_param_names { |
2668
|
5
|
|
|
5
|
|
10
|
my $self = shift; |
2669
|
5
|
|
|
|
|
24
|
return $self->{'kv'}->keyed_param_names; |
2670
|
|
|
|
|
|
|
} |
2671
|
|
|
|
|
|
|
sub order { |
2672
|
7
|
|
|
7
|
|
13
|
my $self = shift; |
2673
|
7
|
50
|
|
|
|
37
|
return $self->{'pp'}->order(@_) if $#_ <= 0; |
2674
|
0
|
|
|
|
|
0
|
$self->{'pp'}->order(@_); |
2675
|
0
|
|
|
|
|
0
|
$self->{'pnames'}{$_[0]} = 1; |
2676
|
|
|
|
|
|
|
} |
2677
|
|
|
|
|
|
|
sub ref { |
2678
|
20
|
|
|
20
|
|
21
|
my $self = shift; |
2679
|
20
|
100
|
|
|
|
82
|
return $self->{'pnames'}->{$_[0]} ? $self->{'pp'}->ref($_[0]) : $self->{'kv'}->ref($_[0]); |
2680
|
|
|
|
|
|
|
} |
2681
|
|
|
|
|
|
|
sub existence_test { |
2682
|
20
|
|
|
20
|
|
48
|
my $self = shift; |
2683
|
20
|
100
|
|
|
|
66
|
return $self->{'pnames'}->{$_[0]} ? $self->{'pp'}->existence_test : $self->{'kv'}->existence_test; |
2684
|
|
|
|
|
|
|
} |
2685
|
|
|
|
|
|
|
sub pcount { |
2686
|
22
|
|
|
22
|
|
17
|
my $self = shift; |
2687
|
22
|
50
|
|
|
|
69
|
return exists $self->{'pnames'} ? scalar(keys %{$self->{'pnames'}}) : 0; |
|
22
|
|
|
|
|
85
|
|
2688
|
|
|
|
|
|
|
} |
2689
|
|
|
|
|
|
|
sub init_form { |
2690
|
4
|
|
|
4
|
|
8
|
my $self = shift; |
2691
|
4
|
|
|
|
|
16
|
my ($class, $constructor) = @_; |
2692
|
4
|
|
|
|
|
19
|
my ($form, $m) = ('', $self->max_possible_params($class)); |
2693
|
4
|
50
|
|
|
|
13
|
$form .= $self->odd_params_check_form($class, $constructor, $self->pcount, $m) if $class->check_params; |
2694
|
4
|
|
|
|
|
18
|
$form .= ' my %params = ' . $self->kv_params_form($m) . ";\n"; |
2695
|
4
|
|
|
|
|
12
|
return $form; |
2696
|
|
|
|
|
|
|
} |
2697
|
|
|
|
|
|
|
sub odd_params_test { |
2698
|
4
|
|
|
4
|
|
8
|
my $self = shift; |
2699
|
4
|
|
|
|
|
8
|
my $class = $_[0]; |
2700
|
4
|
|
|
|
|
5
|
my ($p, $test); |
2701
|
4
|
|
|
|
|
9
|
$p = $self->pcount; |
2702
|
4
|
|
|
|
|
9
|
$test = '$#_>=' . $p; |
2703
|
4
|
100
|
|
|
|
9
|
$test .= ' && $#_<=' . $self->max_possible_params($class) if $class->parents; |
2704
|
4
|
100
|
|
|
|
18
|
$test .= ' && $#_%2 == ' . ($p%2 == 0 ? '0' : '1'); |
2705
|
4
|
|
|
|
|
16
|
return $test; |
2706
|
|
|
|
|
|
|
} |
2707
|
|
|
|
|
|
|
sub self_from_super_form { |
2708
|
2
|
|
|
2
|
|
4
|
my $self = shift; |
2709
|
2
|
|
|
|
|
4
|
my $class = $_[0]; |
2710
|
2
|
|
|
|
|
5
|
my @positional_members = keys %{$self->{'pnames'}}; |
|
2
|
|
|
|
|
7
|
|
2711
|
2
|
|
|
|
|
8
|
my %self_members = map { ($_ => 1) } $class->public_member_names; |
|
3
|
|
|
|
|
10
|
|
2712
|
2
|
|
|
|
|
5
|
delete @self_members{@positional_members}; |
2713
|
2
|
|
|
|
|
8
|
my $m = $self->max_possible_params($class); |
2714
|
2
|
|
|
|
|
14
|
return $self->my_decl_form($class) . '(@_[' . ($m+1) . '..$#_]);' . "\n"; |
2715
|
|
|
|
|
|
|
} |
2716
|
|
|
|
|
|
|
sub max_possible_params { |
2717
|
10
|
|
|
10
|
|
13
|
my $self = shift; |
2718
|
10
|
|
|
|
|
14
|
my $class = $_[0]; |
2719
|
10
|
|
|
|
|
24
|
my $p = $self->pcount; |
2720
|
10
|
|
|
|
|
21
|
return $p + 2*(scalar($class->public_member_names) - $p) - 1; |
2721
|
|
|
|
|
|
|
} |
2722
|
|
|
|
|
|
|
sub params_check_form { |
2723
|
2
|
|
|
2
|
|
3
|
my $self = shift; |
2724
|
2
|
|
|
|
|
3
|
my ($class, $constructor) = @_; |
2725
|
2
|
|
|
|
|
3
|
my ($form, $cn); |
2726
|
2
|
|
|
|
|
6
|
$cn = $constructor->name_form($class); |
2727
|
2
|
|
|
|
|
10
|
$form = $self->{'kv'}->params_check_form(@_); |
2728
|
2
|
|
|
|
|
7
|
my $max_params = $self->max_possible_params($class) + 1; |
2729
|
2
|
|
|
|
|
15
|
$form .= qq| croak '$cn| . qq|Only $max_params parameter(s) allowed (', \$#_+1, ' given)'| . |
2730
|
|
|
|
|
|
|
" unless \$#_ < $max_params;\n"; |
2731
|
2
|
|
|
|
|
8
|
return $form; |
2732
|
|
|
|
|
|
|
} |
2733
|
|
|
|
|
|
|
|
2734
|
|
|
|
|
|
|
sub kv_params_form { |
2735
|
4
|
|
|
4
|
|
8
|
my $self = shift; |
2736
|
4
|
|
|
|
|
8
|
my $max_params = $_[0]; |
2737
|
4
|
|
|
|
|
10
|
return '@_[' . $self->pcount . "..(\$#_ < $max_params ? \$#_ : $max_params)]"; |
2738
|
|
|
|
|
|
|
} |
2739
|
|
|
|
|
|
|
|
2740
|
|
|
|
|
|
|
package Class::Generate::Own; # The "own" parameter-passing |
2741
|
13
|
|
|
13
|
|
89
|
use strict; # style. |
|
13
|
|
|
|
|
33
|
|
|
13
|
|
|
|
|
522
|
|
2742
|
13
|
|
|
13
|
|
88
|
use vars qw(@ISA); |
|
13
|
|
|
|
|
20
|
|
|
13
|
|
|
|
|
2991
|
|
2743
|
|
|
|
|
|
|
@ISA = qw(Class::Generate::Param_Style); |
2744
|
|
|
|
|
|
|
|
2745
|
|
|
|
|
|
|
sub new { |
2746
|
5
|
|
|
5
|
|
11
|
my $class = shift; |
2747
|
5
|
|
|
|
|
28
|
my $self = $class->SUPER::new; |
2748
|
5
|
50
|
|
|
|
29
|
$self->{'super_values'} = $_[0] if defined $_[0]; |
2749
|
5
|
|
|
|
|
22
|
return $self; |
2750
|
|
|
|
|
|
|
} |
2751
|
|
|
|
|
|
|
|
2752
|
|
|
|
|
|
|
sub super_values { |
2753
|
9
|
|
|
9
|
|
12
|
my $self = shift; |
2754
|
9
|
50
|
|
|
|
26
|
return defined $self->{'super_values'} ? @{$self->{'super_values'}} : (); |
|
9
|
|
|
|
|
33
|
|
2755
|
|
|
|
|
|
|
} |
2756
|
|
|
|
|
|
|
|
2757
|
|
|
|
|
|
|
sub can_assign_all_params { |
2758
|
0
|
|
|
0
|
|
0
|
return 0; |
2759
|
|
|
|
|
|
|
} |
2760
|
|
|
|
|
|
|
|
2761
|
|
|
|
|
|
|
sub self_from_super_form { |
2762
|
4
|
|
|
4
|
|
8
|
my $self = shift; |
2763
|
4
|
|
|
|
|
5
|
my $class = $_[0]; |
2764
|
4
|
|
|
|
|
5
|
my ($form, @sv); |
2765
|
4
|
|
|
|
|
23
|
$form = $self->my_decl_form($class); |
2766
|
4
|
100
|
|
|
|
12
|
if ( @sv = $self->super_values ) { |
2767
|
3
|
|
|
|
|
17
|
$form .= '(' . join(',', @sv) . ')'; |
2768
|
|
|
|
|
|
|
} |
2769
|
4
|
|
|
|
|
10
|
$form .= ";\n"; |
2770
|
4
|
|
|
|
|
11
|
return $form; |
2771
|
|
|
|
|
|
|
} |
2772
|
|
|
|
|
|
|
|
2773
|
|
|
|
|
|
|
1; |
2774
|
|
|
|
|
|
|
|
2775
|
|
|
|
|
|
|
# Copyright (c) 1999-2007 Steven Wartik. All rights reserved. This program is free |
2776
|
|
|
|
|
|
|
# software; you can redistribute it and/or modify it under the same terms as |
2777
|
|
|
|
|
|
|
# Perl itself. |