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   32 use strict;
  10         577  
  10         745  
4 10     10   30 use warnings FATAL => qw(all);
  10         10  
  10         263  
5 10     10   30 use Carp;
  10         9  
  10         420  
6 10     10   36 use YATT::Util::Symbol;
  10         10  
  10         520  
7 10     10   34 use YATT::Util qw(terse_dump);
  10         8  
  10         487  
8             require YATT::Inc;
9              
10             sub Base () { 'YATT::Class::Configurable' }
11 10     10   32 use base Base;
  10         10  
  10         753  
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   37 );
  10         10  
24              
25             #========================================
26              
27             sub import {
28 38     38   317 my $pack = shift;
29 38         89 my ($callpack) = caller;
30 38         127 my %rules = (struct => [], inheritance => []);
31 38         139 $pack->parse_args(\@_, \my @conf, \%rules, 'struct');
32             # use Data::Dumper; print Dumper(\%rules), "\n";
33 38         194 $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 56 my ($pack, $arglist, $conflist, $taskqueue, $default_task) = @_;
43 38         115 while (@$arglist) {
44 116 100       380 if (ref $arglist->[0]) {
    50          
45 55         51 my ($task_name, $task_arg) = do {
46 55 50       99 if (ref $arglist->[0] eq 'ARRAY') {
    0          
47 55         134 ($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       117 unless (defined $taskqueue->{$task_name}) {
55 0         0 croak "Invalid task: $task_name";
56             }
57 55         95 push @{$taskqueue->{$task_name}}, $task_arg;
  55         131  
58             } elsif (my ($flag, $key) = $arglist->[0] =~ /^([\-:])(\w+)/) {
59 61         57 shift @$arglist;
60 61 100       104 my $value = $flag eq ':' ? 1 : shift @$arglist;
61 61         146 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 45 my MY $opts = shift;
70 38         79 my $script = $opts->make;
71 38 50       87 print STDERR $script if $opts->{cf_debug};
72 10     10 0 36 eval $script;
  10     10   9  
  10     10   737  
  10     10   34  
  10     10   11  
  10     4   46  
  10     4   38  
  10     4   10  
  10     4   600  
  10     4   36  
  10     4   9  
  10     4   29  
  10     3   38  
  10     3   10  
  10     3   1184  
  4     3   16  
  4     3   6  
  4     3   296  
  4     3   16  
  4     2   5  
  4     2   64  
  4     1   14  
  4     1   24  
  4     1   279  
  4     1   20  
  4     1   5  
  4     1   101  
  4     20   14  
  4         5  
  4         653  
  4         15  
  4         4  
  4         84  
  4         15  
  4         4  
  4         537  
  3         12  
  3         4  
  3         74  
  3         12  
  3         3  
  3         148  
  3         12  
  3         3  
  3         104  
  3         12  
  3         4  
  3         150  
  3         11  
  3         6  
  3         71  
  3         12  
  3         4  
  3         130  
  3         10  
  3         4  
  3         63  
  2         7  
  2         3  
  2         64  
  2         7  
  2         2  
  2         96  
  1         4  
  1         1  
  1         77  
  1         4  
  1         1  
  1         5  
  1         4  
  1         1  
  1         58  
  1         4  
  1         2  
  1         3  
  1         5  
  1         2  
  1         78  
  1         5  
  1         1  
  1         9  
  38         2535  
  20         267  
73 38 50       21390 die $@ if $@;
74             }
75              
76             #----------------------------------------
77              
78             sub configure_base {
79 22     22 0 31 (my MY $opts, my ($value)) = @_;
80 22 100       43 if (ref $value) {
81 4         4 push @{$$opts{aliases}}, $value;
  4         9  
82 4         8 $opts->{cf_base} = $value->[1];
83             } else {
84 18         31 $opts->{cf_base} = $value;
85             }
86 22         52 $opts;
87             }
88              
89             sub configure_alias {
90 14     14 0 20 (my MY $opts, my ($value)) = @_;
91 14         16 push @{$opts->{aliases}}, chunklist($value);
  14         47  
92 14         32 $opts;
93             }
94              
95             sub configure_default {
96 4     4 0 6 (my MY $opts, my ($value)) = @_;
97 4         5 push @{$opts->{default_methods}}, chunklist($value);
  4         9  
98 4         11 $opts;
99             }
100              
101             #========================================
102              
103             sub make {
104 38     38 0 36 my MY $opts = shift;
105 38         38 my $script;
106             # 順番が有る。
107 38         61 foreach my $rule (qw(struct inheritance)) {
108 76 50       168 next unless my $descs = $opts->{cf_rules}{$rule};
109 76 100       148 next unless @$descs;
110 32         108 $script .= $opts->can("make_$rule")->($opts, @$descs);
111             }
112 38         96 $script .= $opts->make_class_aliases;
113 38         84 $script .= $opts->make_default_methods;
114 38         79 $script;
115             }
116              
117             sub make_struct {
118 32     32 0 44 my MY $opts = shift;
119 32         32 my @result;
120 32         41 foreach my $desc (@_) {
121 55   33     193 push @result, $opts->make_class_nesting
122             ($desc, $$opts{cf_callpack} . '::'
123             , $$opts{cf_base} || $opts->Base);
124             }
125 32         108 join "", @result;
126             }
127              
128             sub list_aliases {
129 38     38 0 44 my MY $opts = shift;
130 38         39 map {$$_[0]} @{$$opts{classes}}, @{$$opts{aliases}};
  92         201  
  38         63  
  38         64  
131             }
132              
133             sub make_class_aliases {
134 38     38 0 51 my MY $opts = shift;
135 38         108 my $aliases = join "\n ", $opts->list_aliases;
136 38         107 my $script = <
137             package $$opts{cf_callpack};
138             push our \@EXPORT_OK, qw($aliases);
139             END
140              
141 38 100       92 $script .= <
142             push our \@EXPORT, qw($aliases);
143             END
144              
145 38         41 my $stash = *{globref($$opts{cf_callpack}, '')}{HASH};
  38         99  
146 38 50       106 print STDERR "# [$$opts{cf_callpack} has] "
147             , join(" ", sort keys %$stash), "\n"
148             if $opts->{cf_debug};
149 38         36 foreach my $classdef (@{$$opts{classes}}, @{$$opts{aliases}}) {
  38         56  
  38         67  
150             # Ignore if alias is already defined.
151 92         109 my $entry = $stash->{$classdef->[0]};
152 92 50 66     158 next if defined $entry and $entry->{CODE};
153              
154 92         188 $script .= qq{sub $classdef->[0] () {'$classdef->[1]'}\n};
155             }
156              
157 38         82 $script;
158             }
159              
160             sub make_class_nesting {
161 60     60 0 101 (my MY $opts, my ($desc, $prefix, $super)) = @_;
162 60         108 my ($class, $slots) = splice @$desc, 0, 2;
163 60         61 push @{$$opts{classes}}, [$class, $prefix.$class];
  60         141  
164 9 100       39 my $script = $opts->make_class($prefix.$class, $super
165             , terse_dump(@$slots
166 60         189 , map {ref $_ ? $$_[0] : $_}
167             @$desc));
168              
169 60 100       165 $script .= <{cf_type_name};
170             sub $prefix${class}::type_name () {'$class'}
171             END
172              
173 60         89 foreach my $child (@$desc) {
174 9 100       22 next unless ref $child;
175 5         21 $script .= $opts->make_class_nesting($child, $prefix, $super);
176             }
177 60         133 $script;
178             }
179              
180             sub make_class {
181 60     60 0 1367 my ($self, $class, $super, $slots) = @_;
182 60         188 YATT::Inc->add_inc($class);
183 60 50       281 <
    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 44 my MY $opts = shift;
194 38         44 join "", map {<
  4         17  
  38         84  
195             sub default_$$_[0] {'$$_[1]'}
196             END
197              
198             }
199              
200             #----------------------------------------
201              
202             sub chunklist {
203 18     18 0 20 my ($arg) = @_;
204 18         14 my @list;
205 18 50       33 if (ref $arg eq 'ARRAY') {
    0          
206 18         91 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       41 wantarray ? @list : \@list;
215             }
216              
217             1;