File Coverage

web/cgi-bin/yatt.lib/YATT/Types.pm
Criterion Covered Total %
statement 196 204 96.0
branch 29 44 65.9
condition 3 6 50.0
subroutine 49 49 100.0
pod 0 14 0.0
total 277 317 87.3


line stmt bran cond sub pod time code
1             # -*- mode: perl; coding: utf-8 -*-
2             package YATT::Types;
3 10     10   54 use strict;
  10         20  
  10         330  
4 10     10   52 use warnings qw(FATAL all NONFATAL misc);
  10         20  
  10         431  
5 10     10   56 use Carp;
  10         18  
  10         646  
6 10     10   58 use YATT::Util::Symbol;
  10         16  
  10         1051  
7 10     10   53 use YATT::Util qw(terse_dump);
  10         19  
  10         829  
8             require YATT::Inc;
9              
10             sub Base () { 'YATT::Class::Configurable' }
11 10     10   50 use base Base;
  10         19  
  10         942  
12 10         88 use YATT::Fields qw(
13             classes
14             aliases
15             default_methods
16             cf_rules
17             )
18             , [cf_base => Base]
19             , qw(cf_callpack
20             cf_export_alias
21             cf_type_name
22             cf_debug
23 10     10   52 );
  10         19  
24              
25             #========================================
26              
27             sub import {
28 38     38   1006 my $pack = shift;
29 38         127 my ($callpack) = caller;
30 38         237 my %rules = (struct => [], inheritance => []);
31 38         177 $pack->parse_args(\@_, \my @conf, \%rules, 'struct');
32             # use Data::Dumper; print Dumper(\%rules), "\n";
33 38         302 $pack->new(callpack => $callpack, @conf, rules => \%rules)
34             ->export;
35             }
36              
37             # XXX: 交互でも行けるようになったはず。テストを。
38             # XXX: -constant も欲しい ← @EXPORT に入れない。
39             # XXX: \inheritance も。
40              
41             sub parse_args {
42 38     38 0 94 my ($pack, $arglist, $conflist, $taskqueue, $default_task) = @_;
43 38         165 while (@$arglist) {
44 116 100       559 if (ref $arglist->[0]) {
    50          
45 55         78 my ($task_name, $task_arg) = do {
46 55 50       147 if (ref $arglist->[0] eq 'ARRAY') {
    0          
47 55         137 ($default_task, shift @$arglist);
48             } elsif (ref $arglist->[0] eq 'SCALAR') {
49 0         0 (${shift @$arglist}, shift @$arglist);
  0         0  
50             } else {
51 0         0 croak "Invalid option '$arglist->[0]'";
52             }
53             };
54 55 50       185 unless (defined $taskqueue->{$task_name}) {
55 0         0 croak "Invalid task: $task_name";
56             }
57 55         133 push @{$taskqueue->{$task_name}}, $task_arg;
  55         252  
58             } elsif (my ($flag, $key) = $arglist->[0] =~ /^([\-:])(\w+)/) {
59 61         89 shift @$arglist;
60 61 100       154 my $value = $flag eq ':' ? 1 : shift @$arglist;
61 61         247 push @$conflist, $key, $value;
62             } else {
63 0         0 croak "Invalid option '$arglist->[0]'";
64             }
65             }
66             }
67              
68             sub export {
69 38     38 0 59 my MY $opts = shift;
70 38         131 my $script = $opts->make;
71 38 50       119 print STDERR $script if $opts->{cf_debug};
72 10     10 0 60 eval $script;
  10     10   25  
  10     10   1077  
  10     10   52  
  10     10   17  
  10     4   76  
  10     4   52  
  10     4   20  
  10     4   806  
  10     4   50  
  10     4   17  
  10     4   59  
  10     3   57  
  10     3   20  
  10     3   1969  
  4     3   23  
  4     3   8  
  4     3   407  
  4     3   21  
  4     2   11  
  4     2   89  
  4     1   21  
  4     1   7  
  4     1   359  
  4     1   20  
  4     1   8  
  4     1   123  
  4     20   20  
  4         7  
  4         1225  
  4         22  
  4         14  
  4         124  
  4         21  
  4         8  
  4         913  
  3         16  
  3         6  
  3         95  
  3         15  
  3         7  
  3         161  
  3         15  
  3         5  
  3         78  
  3         15  
  3         6  
  3         165  
  3         18  
  3         6  
  3         101  
  3         16  
  3         10  
  3         161  
  3         15  
  3         5  
  3         84  
  2         12  
  2         5  
  2         85  
  2         10  
  2         4  
  2         130  
  1         6  
  1         2  
  1         92  
  1         8  
  1         3  
  1         9  
  1         5  
  1         2  
  1         79  
  1         5  
  1         2  
  1         6  
  1         5  
  1         2  
  1         142  
  1         7  
  1         2  
  1         19  
  38         3495  
  20         340  
73 38 50       34391 die $@ if $@;
74             }
75              
76             #----------------------------------------
77              
78             sub configure_base {
79 22     22 0 46 (my MY $opts, my ($value)) = @_;
80 22 100       60 if (ref $value) {
81 4         7 push @{$$opts{aliases}}, $value;
  4         29  
82 4         28 $opts->{cf_base} = $value->[1];
83             } else {
84 18         50 $opts->{cf_base} = $value;
85             }
86 22         75 $opts;
87             }
88              
89             sub configure_alias {
90 14     14 0 27 (my MY $opts, my ($value)) = @_;
91 14         21 push @{$opts->{aliases}}, chunklist($value);
  14         54  
92 14         47 $opts;
93             }
94              
95             sub configure_default {
96 4     4 0 10 (my MY $opts, my ($value)) = @_;
97 4         6 push @{$opts->{default_methods}}, chunklist($value);
  4         19  
98 4         19 $opts;
99             }
100              
101             #========================================
102              
103             sub make {
104 38     38 0 63 my MY $opts = shift;
105 38         55 my $script;
106             # 順番が有る。
107 38         73 foreach my $rule (qw(struct inheritance)) {
108 76 50       246 next unless my $descs = $opts->{cf_rules}{$rule};
109 76 100       215 next unless @$descs;
110 32         162 $script .= $opts->can("make_$rule")->($opts, @$descs);
111             }
112 38         114 $script .= $opts->make_class_aliases;
113 38         129 $script .= $opts->make_default_methods;
114 38         130 $script;
115             }
116              
117             sub make_struct {
118 32     32 0 55 my MY $opts = shift;
119 32         44 my @result;
120 32         65 foreach my $desc (@_) {
121             push @result, $opts->make_class_nesting
122             ($desc, $$opts{cf_callpack} . '::'
123 55   33     299 , $$opts{cf_base} || $opts->Base);
124             }
125 32         176 join "", @result;
126             }
127              
128             sub list_aliases {
129 38     38 0 62 my MY $opts = shift;
130 38         52 map {$$_[0]} @{$$opts{classes}}, @{$$opts{aliases}};
  92         221  
  38         87  
  38         91  
131             }
132              
133             sub make_class_aliases {
134 38     38 0 69 my MY $opts = shift;
135 38         107 my $aliases = join "\n ", $opts->list_aliases;
136 38         135 my $script = <
137             package $$opts{cf_callpack};
138             push our \@EXPORT_OK, qw($aliases);
139             END
140              
141 38 100       151 $script .= <
142             push our \@EXPORT, qw($aliases);
143             END
144              
145 38         64 my $stash = *{globref($$opts{cf_callpack}, '')}{HASH};
  38         141  
146             print STDERR "# [$$opts{cf_callpack} has] "
147             , join(" ", sort keys %$stash), "\n"
148 38 50       163 if $opts->{cf_debug};
149 38         57 foreach my $classdef (@{$$opts{classes}}, @{$$opts{aliases}}) {
  38         84  
  38         98  
150             # Ignore if alias is already defined.
151 92         181 my $entry = $stash->{$classdef->[0]};
152 92 50 66     209 next if defined $entry and $entry->{CODE};
153              
154 92         293 $script .= qq{sub $classdef->[0] () {'$classdef->[1]'}\n};
155             }
156              
157 38         125 $script;
158             }
159              
160             sub make_class_nesting {
161 60     60 0 159 (my MY $opts, my ($desc, $prefix, $super)) = @_;
162 60         149 my ($class, $slots) = splice @$desc, 0, 2;
163 60         95 push @{$$opts{classes}}, [$class, $prefix.$class];
  60         246  
164             my $script = $opts->make_class($prefix.$class, $super
165             , terse_dump(@$slots
166 60 100       283 , map {ref $_ ? $$_[0] : $_}
  9         46  
167             @$desc));
168              
169 60 100       260 $script .= <{cf_type_name};
170             sub $prefix${class}::type_name () {'$class'}
171             END
172              
173 60         133 foreach my $child (@$desc) {
174 9 100       34 next unless ref $child;
175 5         28 $script .= $opts->make_class_nesting($child, $prefix, $super);
176             }
177 60         213 $script;
178             }
179              
180             sub make_class {
181 60     60 0 2428 my ($self, $class, $super, $slots) = @_;
182 60         258 YATT::Inc->add_inc($class);
183 60 50       404 <
    100          
184             package $class;
185             END
186             use base qw($super);
187             END
188             use YATT::Fields $slots;
189             END
190             }
191              
192             sub make_default_methods {
193 38     38 0 60 my MY $opts = shift;
194 38         61 join "", map {<
  4         27  
  38         123  
195             sub default_$$_[0] {'$$_[1]'}
196             END
197              
198             }
199              
200             #----------------------------------------
201              
202             sub chunklist {
203 18     18 0 33 my ($arg) = @_;
204 18         24 my @list;
205 18 50       53 if (ref $arg eq 'ARRAY') {
    0          
206 18         136 push @list, [splice @$arg, 0, 2] while @$arg;
207             } elsif (ref $arg eq 'HASH') {
208 0         0 while (my ($k, $v) = each %$arg) {
209 0         0 push @list, [$k, $v];
210             }
211             } else {
212 0         0 croak "Invalid arg for -alias";
213             }
214 18 50       65 wantarray ? @list : \@list;
215             }
216              
217             1;