File Coverage

blib/lib/Class/Generate.pm
Criterion Covered Total %
statement 1737 1931 89.9
branch 642 890 72.1
condition 114 187 60.9
subroutine 352 374 94.1
pod 3 3 100.0
total 2848 3385 84.1


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.