File Coverage

blib/lib/YATT/Lite/CGen.pm
Criterion Covered Total %
statement 104 117 88.8
branch 37 52 71.1
condition 16 29 55.1
subroutine 24 29 82.7
pod 0 16 0.0
total 181 243 74.4


line stmt bran cond sub pod time code
1             package YATT::Lite::CGen; sub MY () {__PACKAGE__}
2 15     15   19502 use strict;
  15         33  
  15         425  
3 15     15   67 use warnings qw(FATAL all NONFATAL misc);
  15         33  
  15         452  
4 15     15   79 use Carp;
  15         40  
  15         1140  
5              
6 15     15   88 use constant DEBUG_REBUILD => $ENV{DEBUG_YATT_REBUILD};
  15         39  
  15         776  
7              
8 15     15   89 use base qw(YATT::Lite::VarMaker);
  15         39  
  15         1343  
9 15         127 use YATT::Lite::MFields qw/curtmpl curwidget curtoks
10             altgen needs_escaping depth
11             cf_cgen_loader
12             cf_only_parse
13             cf_no_lineinfo cf_check_lineno
14             no_last_newline
15             cf_vfs cf_parser cf_sink scope
16             cf_lcmsg_sink
17 15     15   96 /;
  15         38  
18              
19 15     15   128 use YATT::Lite::Core qw(Template Part Folder);
  15         38  
  15         763  
20 15     15   91 use YATT::Lite::Constants;
  15         51  
  15         1983  
21 15     15   90 use YATT::Lite::Util qw(callerinfo numLines);
  15         31  
  15         18133  
22              
23             sub ensure_generated_for_folders {
24 220     220 0 753 (my MY $self, my $spec) = splice @_, 0, 2;
25 220         515 foreach my Folder $folder (@_) {
26 226 100       1194 if ($folder->can_generate_code) {
27 5         16 $self->ensure_generated($spec, $folder);
28             }
29             }
30             }
31              
32             sub ensure_generated {
33 363     363 0 1044 (my MY $self, my $spec, my Template $tmpl) = @_;
34 363 50       1217 my ($type, $kind) = ref $spec ? @$spec : $spec;
35 363 50       1148 $self->{cf_vfs}->error(q{sink is empty}) unless $self->{cf_sink};
36 363 100       1316 return if defined $tmpl->{product}{$type};
37 227   100     1258 local $self->{depth} = 1 + ($self->{depth} // 0);
38 227         740 my $pkg = $tmpl->{product}{$type} = $tmpl->{cf_entns};
39 227 50       720 if (not defined $tmpl->{product}{$type}) {
40 0         0 croak "package for product $type of $tmpl->{cf_path} is not defined!";
41             } else {
42 227         438 print STDERR "# generating $pkg for $type code of $tmpl->{cf_path}\n"
43             if DEBUG_REBUILD;
44             }
45             $self->{cf_parser}->parse_body($tmpl)
46             if not $kind or not $self->{cf_only_parse}
47 227 50 33     1714 or $self->{cf_only_parse}{$kind};
      33        
48 220         1649 $self->setup_inheritance_for($spec, $tmpl);
49 220         1434 my @res = $self->generate($tmpl, $kind);
50 201 50       923 if (my $sub = $self->{cf_sink}) {
51             $sub->({folder => $tmpl, package => $pkg, kind => 'body'
52             , depth => $self->{depth}}
53 201         1566 , @res);
54             }
55 200         4968 $pkg;
56             }
57              
58             sub generate {
59 220     220 0 719 (my MY $self, my Template $tmpl) = splice @_, 0, 2;
60             # XXX: localize した方がいいかも。 というか、 curtmpl との区別が紛らわしいか。
61 220 50       737 my $kind = shift if @_;
62 220         670 local $self->{curtmpl} = $tmpl;
63 220         491 local $self->{curline} = 1;
64             ($self->generate_preamble($self->{curtmpl})
65             , map {
66 349         703 my Part $part = $_;
67 349 50 33     1547 if (not $kind or not $self->{cf_only_parse}
      33        
68             or $kind eq $part->{cf_kind}) {
69             my $sub = $self->can("generate_$part->{cf_kind}")
70             or die $self->generror("Can't generate part type: '%s'"
71 349 50       2039 , $part->{cf_kind});
72 349         1531 $sub->($self, $part, $part->{cf_name}, $tmpl->{cf_path});
73             } else {
74 0         0 ();
75             }
76 220         1115 } @{$tmpl->{partlist}});
  220         572  
77             }
78              
79             sub setup_inheritance_for {
80 0     0 0 0 (my MY $self, my $spec, my Template $tmpl) = @_;
81 0         0 $self->ensure_generated_for_folders($spec, $tmpl->list_base);
82             }
83              
84             #========================================
85             sub altgen {
86 206     206 0 494 (my MY $self, my $ns) = @_;
87             # ns 一つに付き 高々 1回しか、can しないで済むように... と言っても、cgen 自体が複数個作られたら..
88 206 100       736 unless (exists $self->{altgen}{$ns}) {
89 128         221 $self->{altgen}{$ns} = do {
90 128 50       1175 if (my $sub = $self->can("create_altgen_$ns")) {
91             sub {
92             # 毎回, new し直す。
93 0     0   0 $sub->($self)->generate_node(@_);
94 0         0 };
95             }
96             };
97             }
98 206         3704 $self->{altgen}{$ns};
99             }
100             sub create_altgen_js {
101 0     0 0 0 require YATT::Lite::CGen::JS;
102 0         0 my MY $self = shift;
103 0         0 new YATT::Lite::CGen::JS
104             ($self->cf_delegate(qw(vfs parser no_lineinfo check_lineno)));
105             }
106             #========================================
107             sub find_var {
108 619     619 0 1351 (my MY $self, my $varName, my $check) = @_;
109 619 50       1449 confess "Undefined varName for find_var!" unless defined $varName;
110 619         2054 for (my $scope = $self->{scope}; $scope; $scope = $scope->[1]) {
111 2135 100       8632 if (defined (my $var = $scope->[0]{$varName})) {
112 298 50 66     877 next if $check and not $check->($var);
113 298         1133 return $var;
114             }
115             }
116             }
117             sub find_callable_var {
118 317     317 0 751 (my MY $self, my $varName) = @_;
119 317     34   1726 $self->find_var($varName, sub {shift->callable});
  34         173  
120             }
121             sub lookup_widget {
122 147     147 0 451 (my MY $self, my ($ns, @path)) = @_;
123             # ns 抜きと、有りで一回ずつ検索する
124             $self->{cf_vfs}->find_part_from($self->{curtmpl}, @path)
125 147 100       743 || $self->{cf_vfs}->find_part_from($self->{curtmpl}, $ns, @path);
126             }
127              
128             sub generror {
129 19     19 0 40 my MY $self = shift;
130 19         46 my Template $tmpl = $self->{curtmpl};
131 19         84 my ($pkg, $file, $line) = caller;
132 19         110 my %opts = ($self->_tmpl_file_line($self->{curline}), callerinfo());
133 19         102 $self->_error(\%opts, @_);
134             }
135             sub _error {
136 19     19   37 my MY $self = shift;
137 19         88 $self->{cf_vfs}->error(@_);
138             }
139             sub _tmpl_file_line {
140 19     19   59 (my MY $self, my $ln) = @_;
141 19         44 my Template $tmpl = $self->{curtmpl};
142             (tmpl_file => $tmpl->{cf_path} // $tmpl->{cf_name}
143 19 50 33     216 , defined $ln ? (tmpl_line => $ln) : ());
144             }
145              
146             sub add_curline {
147 87     87 0 229 (my MY $self, my $text) = @_;
148 87         305 $self->{curline} += numLines($text);
149 87         396 $text;
150             }
151              
152             sub sync_curline {
153 1657     1657 0 3180 (my MY $self, my $lineno) = @_;
154 1657 100       3921 return unless defined $lineno;
155 1510         2736 my $diff = $lineno - $self->{curline};
156 1510 50 33     3980 die "curline exceeds expected lineno! expect $lineno, curline=$self->{curline}\n" if $self->{cf_check_lineno} and $diff < 0;
157 1510         2520 $self->{curline} = $lineno;
158 1510 100       7142 $diff > 0 ? "\n" x $diff : ();
159             }
160             # の直後の改行を,
161             # ソース上のみの(出力しない)改行に変換する。
162             sub cut_next_nl {
163 634     634 0 1123 my MY $self = shift;
164             # undef は返したくないので。
165             return wantarray ? () : ''
166             unless $self->{curtoks}
167 634 100 100     1792 and @{$self->{curtoks}} and $self->{curtoks}[0] =~ /^\r?\n$/;
  633 100 100     6332  
168             return wantarray ? () : ''
169 206 50       401 if @{$self->{curtoks}} == 1; # 最後の一個の改行は、残す。これは "}\n" のため
  206 100       958  
170 84         174 $self->{curline}++;
171 84         134 shift @{$self->{curtoks}};
  84         398  
172             }
173              
174             sub mkscope {
175 395     395 0 766 my MY $self = shift;
176 395 50       1037 return unless @_;
177 395 100       1422 my $scope = ref $_[-1] eq 'ARRAY' ? pop : [pop];
178 395         1150 while (@_) {
179 1115         3165 $scope = [pop, $scope];
180             }
181 395         1232 $scope;
182             }
183              
184             sub terse_dump {
185 0     0 0   my MY $self = shift;
186 0           YATT::Lite::Util::terse_dump(@_);
187             }
188              
189             sub node_sync_curline {
190 0     0 0   (my MY $self, my $node) = @_;
191 0           $self->sync_curline($node->[NODE_LNO]);
192             }
193              
194             1;