line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package YATT::Lite::CGen::Perl; |
2
|
9
|
|
|
9
|
|
5995
|
use strict; |
|
9
|
|
|
|
|
19
|
|
|
9
|
|
|
|
|
315
|
|
3
|
9
|
|
|
9
|
|
45
|
use warnings qw(FATAL all NONFATAL misc); |
|
9
|
|
|
|
|
20
|
|
|
9
|
|
|
|
|
434
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
require 5.010; # For named capture. |
6
|
|
|
|
|
|
|
|
7
|
9
|
|
|
9
|
|
48
|
use YATT::Lite::Core qw(Folder Template Part Widget Action); |
|
9
|
|
|
|
|
16
|
|
|
9
|
|
|
|
|
762
|
|
8
|
9
|
|
|
9
|
|
50
|
use YATT::Lite::Constants; |
|
9
|
|
|
|
|
17
|
|
|
9
|
|
|
|
|
2399
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# Naming convention: |
11
|
|
|
|
|
|
|
# generate_SRC -- Public Interface. |
12
|
|
|
|
|
|
|
# gen_DETAIL -- Internal higher/large tasks. |
13
|
|
|
|
|
|
|
# from_NODETYPE -- Node Type specific dispatch entry. |
14
|
|
|
|
|
|
|
# as_WHATHOW_FROM -- Miscellaneous dispatching (for var type and others) |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
{ |
17
|
|
|
|
|
|
|
#======================================== |
18
|
|
|
|
|
|
|
package YATT::Lite::CGen::Perl; sub MY () {__PACKAGE__} |
19
|
9
|
|
|
9
|
|
51
|
use base qw(YATT::Lite::CGen); |
|
9
|
|
|
|
|
17
|
|
|
9
|
|
|
|
|
5512
|
|
20
|
9
|
|
|
9
|
|
55
|
use YATT::Lite::Util qw(lexpand numLines globref terse_dump); |
|
9
|
|
|
|
|
17
|
|
|
9
|
|
|
|
|
588
|
|
21
|
9
|
|
|
9
|
|
47
|
use Carp; |
|
9
|
|
|
|
|
17
|
|
|
9
|
|
|
|
|
87833
|
|
22
|
|
|
|
|
|
|
#======================================== |
23
|
|
|
|
|
|
|
sub list_inheritance { |
24
|
312
|
|
|
312
|
0
|
464
|
(my MY $self, my Template $tmpl) = @_; |
25
|
|
|
|
|
|
|
# XXX: Duplicate detection should be handled higer layer. |
26
|
312
|
|
|
|
|
390
|
my %dup; |
27
|
|
|
|
|
|
|
map { |
28
|
312
|
|
|
|
|
1006
|
my Folder $f = $_; |
|
314
|
|
|
|
|
414
|
|
29
|
314
|
50
|
|
|
|
817
|
unless (defined $f->{cf_entns}) { |
30
|
0
|
|
|
|
|
0
|
die "BUG: EntNS is empty for ".terse_dump($f->{cf_name})."!"; |
31
|
|
|
|
|
|
|
} |
32
|
314
|
50
|
|
|
|
995
|
if ($dup{$f->{cf_entns}}++) { |
33
|
|
|
|
|
|
|
() |
34
|
0
|
|
|
|
|
0
|
} else { |
35
|
|
|
|
|
|
|
$f->{cf_entns} |
36
|
314
|
|
|
|
|
1496
|
} |
37
|
|
|
|
|
|
|
} $tmpl->list_base |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
sub setup_inheritance { |
40
|
156
|
|
|
156
|
0
|
299
|
(my MY $self, my Template $tmpl) = @_; |
41
|
156
|
50
|
|
|
|
450
|
unless (defined $tmpl->{cf_entns}) { |
42
|
0
|
|
|
|
|
0
|
die "BUG: EntNS is empty for '$tmpl->{cf_name}'!"; |
43
|
|
|
|
|
|
|
} |
44
|
156
|
|
|
|
|
485
|
my $glob = globref($$tmpl{cf_entns}, 'ISA'); |
45
|
|
|
|
|
|
|
# XXX: base change should be reflected when reloaded, but... |
46
|
156
|
50
|
|
|
|
454
|
unless (defined $glob) { |
47
|
0
|
|
|
|
|
0
|
die "BUG: ISA glob for '$tmpl->{cf_name}' is empty!"; |
48
|
|
|
|
|
|
|
} |
49
|
156
|
|
|
|
|
491
|
my @isa = $self->list_inheritance($tmpl); |
50
|
156
|
50
|
|
|
|
324
|
if (grep {not defined} @isa) { |
|
157
|
|
|
|
|
557
|
|
51
|
0
|
|
|
|
|
0
|
die "BUG: ISA for '$tmpl->{cf_name}' contains undef!"; |
52
|
|
|
|
|
|
|
} |
53
|
156
|
|
|
|
|
1996
|
*$glob = \@isa; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
sub generate_inheritance { |
56
|
156
|
|
|
156
|
0
|
236
|
(my MY $self, my Template $tmpl) = @_; |
57
|
156
|
|
|
|
|
376
|
sprintf q{our @ISA = qw(%s); }, join " ", $self->list_inheritance($tmpl); |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
#======================================== |
60
|
|
|
|
|
|
|
sub generate_preamble { |
61
|
156
|
|
|
156
|
0
|
240
|
(my MY $self, my Template $tmpl) = @_; |
62
|
156
|
|
33
|
|
|
371
|
$tmpl ||= $self->{curtmpl}; |
63
|
156
|
|
|
|
|
223
|
my @stats; |
64
|
156
|
50
|
|
|
|
459
|
unless ($self->{cf_no_lineinfo}) { |
65
|
156
|
|
|
|
|
445
|
my $line = qq{#line }. $self->{curline}; |
66
|
156
|
100
|
|
|
|
604
|
if (defined(my $fn = $tmpl->fake_filename)) { |
67
|
|
|
|
|
|
|
# cf_name is dummy filename. |
68
|
155
|
|
|
|
|
427
|
$line .= qq{ "$fn"}; |
69
|
|
|
|
|
|
|
} |
70
|
156
|
|
|
|
|
341
|
push @stats, $line .= "\n"; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
push @stats, sprintf q{package %s; use strict; use warnings; use 5.010; } |
73
|
156
|
|
|
|
|
578
|
, $$tmpl{cf_entns}; |
74
|
156
|
|
|
|
|
411
|
push @stats, $self->generate_inheritance($tmpl); |
75
|
156
|
100
|
|
|
|
512
|
push @stats, "use utf8; " if $$tmpl{cf_utf8}; |
76
|
156
|
100
|
|
|
|
493
|
push @stats, q|no warnings qw(redefine); | if $$tmpl{cf_age}++; |
77
|
156
|
|
|
|
|
284
|
push @stats, sprintf q|sub filename {__FILE__}; |; |
78
|
|
|
|
|
|
|
@stats |
79
|
156
|
|
|
|
|
511
|
} |
80
|
|
|
|
|
|
|
sub generate_page { |
81
|
|
|
|
|
|
|
# XXX: 本物へ。 public フラグ? |
82
|
158
|
|
|
158
|
0
|
475
|
shift->generate_widget(@_); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
sub generate_widget { |
85
|
226
|
|
|
226
|
0
|
778
|
(my MY $self, my Widget $widget, my ($widget_name, $tmpl_path)) = @_; |
86
|
226
|
100
|
|
|
|
682
|
if ($widget->{cf_suppressed}) { |
87
|
1
|
|
|
|
|
7
|
return "\n" x ($widget->{cf_endln} - $widget->{cf_startln}); |
88
|
|
|
|
|
|
|
} |
89
|
225
|
|
|
|
|
750
|
break_cgen(); |
90
|
225
|
|
|
|
|
535
|
local $self->{curwidget} = $widget; |
91
|
|
|
|
|
|
|
# XXX: calling convention 周り, body の code 型 |
92
|
|
|
|
|
|
|
local $self->{scope} = $self->mkscope |
93
|
|
|
|
|
|
|
({}, $widget->{var_dict}, $widget->{arg_dict} ||= {} |
94
|
225
|
|
50
|
|
|
1427
|
, {this => $self->mkvar_at(undef, text => 'this') |
95
|
|
|
|
|
|
|
, 'CON' => $self->mkvar_at(undef, text => 'CON') |
96
|
|
|
|
|
|
|
, '_' => $self->mkvar_at(undef, text => '_')} |
97
|
|
|
|
|
|
|
); |
98
|
225
|
|
|
|
|
486
|
local $self->{curtoks} = [@{$widget->{tree}}]; |
|
225
|
|
|
|
|
886
|
|
99
|
|
|
|
|
|
|
($self->sync_curline($widget->{cf_startln}) |
100
|
|
|
|
|
|
|
, "sub render_$$widget{cf_name} {" |
101
|
|
|
|
|
|
|
, $self->gen_preamble($widget) |
102
|
|
|
|
|
|
|
, $self->gen_getargs($widget, not $widget->{cf_implicit}) |
103
|
225
|
|
|
|
|
853
|
, $self->as_print("}") |
104
|
|
|
|
|
|
|
); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
sub generate_action { |
107
|
2
|
|
|
2
|
0
|
5
|
(my MY $self, my Action $action) = @_; |
108
|
|
|
|
|
|
|
# XXX: 改行の調整が必要。 |
109
|
|
|
|
|
|
|
my $src = $self->{curtmpl}->source_substr |
110
|
2
|
|
|
|
|
11
|
($action->{cf_bodypos}, $action->{cf_bodylen}); |
111
|
2
|
|
|
|
|
10
|
my $has_nl = $src =~ s/\r?\n\Z//; |
112
|
2
|
50
|
|
|
|
103
|
$self->{curline} = $action->{cf_bodyln} + numLines($src) |
113
|
|
|
|
|
|
|
+ ($has_nl ? 1 : 0); |
114
|
|
|
|
|
|
|
sprintf "sub %s {%s}\n" |
115
|
2
|
|
|
|
|
21
|
, $action->{cf_name}, $src; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
#======================================== |
118
|
225
|
|
|
225
|
0
|
760
|
sub gen_preamble {q{ my ($this, $CON) = splice @_, 0, 2;}} |
119
|
|
|
|
|
|
|
sub gen_getargs { |
120
|
257
|
|
|
257
|
0
|
475
|
(my MY $self, my Widget $widget, my $for_decl) = @_; |
121
|
257
|
|
|
|
|
313
|
my @res; |
122
|
257
|
|
|
|
|
821
|
foreach my $argName (lexpand($widget->{arg_order})) { |
123
|
|
|
|
|
|
|
# デフォルト値と、型と。 |
124
|
448
|
|
|
|
|
906
|
my $var = $widget->{arg_dict}{$argName}; |
125
|
448
|
100
|
|
|
|
1580
|
push @res, $for_decl ? $self->sync_curline($var->lineno) : () |
126
|
|
|
|
|
|
|
, sprintf q{ my %s = %s;}, $self->as_lvalue($var) |
127
|
|
|
|
|
|
|
, $self->as_getarg($var); |
128
|
|
|
|
|
|
|
# shift しない方が、debug 時に stack trace に引数値が見えて嬉しい。 |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
# 末尾の改行 |
131
|
257
|
100
|
33
|
|
|
851
|
push @res, "\n" and $self->{curline}++ if $for_decl; |
132
|
|
|
|
|
|
|
(@res, $self->sync_curline($widget->{cf_bodyln}) |
133
|
257
|
|
|
|
|
884
|
, $self->cut_next_nl); |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
sub as_getarg { |
136
|
448
|
|
|
448
|
0
|
663
|
(my MY $self, my $var) = @_; |
137
|
448
|
|
|
|
|
1188
|
my $actual = '$_['.$var->argno.']'; |
138
|
448
|
100
|
66
|
|
|
1499
|
return $actual unless defined (my $default = $var->default) |
139
|
|
|
|
|
|
|
and defined (my $mode = $var->dflag); |
140
|
22
|
|
|
|
|
57
|
my $varname = $self->as_lvalue($var); |
141
|
22
|
100
|
|
|
|
72
|
if ($mode eq "!") { |
142
|
3
|
|
|
|
|
10
|
return qq{defined $actual ? $actual : } |
143
|
3
|
|
|
|
|
9
|
. qq{die q|Argument '@{[$var->varname]}' is undef!|}; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
# XXX: do given/when は値を返さないから、ここでは使えない! void context 扱いになっちまう。 |
146
|
19
|
|
|
|
|
30
|
my ($cond) = do { |
147
|
19
|
100
|
|
|
|
90
|
if ($mode eq "|") { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
148
|
2
|
|
|
|
|
6
|
qq{$actual} |
149
|
|
|
|
|
|
|
} elsif ($mode eq "?") { |
150
|
15
|
|
|
|
|
44
|
qq{defined $actual && $actual ne ""} |
151
|
|
|
|
|
|
|
} elsif ($mode eq "/") { |
152
|
2
|
|
|
|
|
5
|
qq{defined $actual} |
153
|
|
|
|
|
|
|
} else { |
154
|
0
|
|
|
|
|
0
|
die "Unknown defaulting mode: $mode" |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
}; |
157
|
19
|
|
|
|
|
61
|
sprintf q{(%s ? %s : %s)}, $cond, $actual |
158
|
|
|
|
|
|
|
, $self->as_cast_to($var, $default); |
159
|
|
|
|
|
|
|
# XXX: html 型変数へ text 型変数の混じったデフォルト値を入れるときには、 as_text じゃだめ |
160
|
|
|
|
|
|
|
# as_text に、やはり escape flag を渡せるようにするのが筋か? |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
#======================================== |
163
|
|
|
|
|
|
|
our @DISPATCH; |
164
|
|
|
|
|
|
|
$DISPATCH[TYPE_LINEINFO] = \&from_lineinfo; |
165
|
|
|
|
|
|
|
$DISPATCH[TYPE_COMMENT] = \&from_comment; |
166
|
|
|
|
|
|
|
$DISPATCH[TYPE_LCMSG] = \&from_lcmsg; |
167
|
|
|
|
|
|
|
$DISPATCH[TYPE_ENTITY] = \&from_entity; |
168
|
|
|
|
|
|
|
$DISPATCH[TYPE_PI] = \&from_pi; |
169
|
|
|
|
|
|
|
$DISPATCH[TYPE_ELEMENT] = \&from_element; |
170
|
|
|
|
|
|
|
$DISPATCH[TYPE_ATT_NESTED] = \&from_elematt; |
171
|
|
|
|
|
|
|
sub as_print { |
172
|
283
|
|
|
283
|
0
|
555
|
(my MY $self, my ($last, $localtoks)) = @_; |
173
|
283
|
50
|
|
|
|
667
|
push @{$self->{curtoks}}, @$localtoks if $localtoks; |
|
0
|
|
|
|
|
0
|
|
174
|
283
|
|
|
|
|
645
|
local $self->{needs_escaping} = 1; |
175
|
283
|
|
|
|
|
588
|
my (@result, @queue) = ''; |
176
|
|
|
|
|
|
|
# curline は queue 詰めの外側で操作する。 |
177
|
|
|
|
|
|
|
# $last は一回だけ出力するように、undef が必要。 |
178
|
|
|
|
|
|
|
my $flush = sub { |
179
|
805
|
|
|
805
|
|
1351
|
my ($has_nl, $task, $pad) = @_; |
180
|
805
|
100
|
|
|
|
1792
|
push @result, $pad if defined $pad; |
181
|
805
|
100
|
|
|
|
2603
|
push @result, q{print $CON (}.join(", ", @queue).");" if @queue; |
182
|
|
|
|
|
|
|
# もう token が残っていなくて、かつ $last が与えられていたら、 $last を足す。 |
183
|
805
|
100
|
|
|
|
1944
|
push @result, $task->() if $task; |
184
|
805
|
100
|
50
|
|
|
1989
|
$result[-1] .= $last and undef $last if $last and not @{$self->{curtoks}}; |
|
560
|
|
100
|
|
|
2606
|
|
185
|
|
|
|
|
|
|
# 明示 "\n" が来ていた場合は、 ";" と同時に改行する。 |
186
|
805
|
100
|
|
|
|
1879
|
$result[-1] .= "\n" if $has_nl; |
187
|
805
|
|
|
|
|
1905
|
undef @queue; |
188
|
283
|
|
|
|
|
1378
|
}; |
189
|
283
|
|
|
|
|
424
|
while (@{$self->{curtoks}}) { |
|
1274
|
|
|
|
|
3417
|
|
190
|
1012
|
|
|
|
|
1332
|
my $node = shift @{$self->{curtoks}}; |
|
1012
|
|
|
|
|
2034
|
|
191
|
1012
|
100
|
|
|
|
2416
|
unless (ref $node) { |
192
|
|
|
|
|
|
|
# text node の末尾が改行で終わっている場合、 明示的に "\n" を生成する |
193
|
633
|
|
|
|
|
2013
|
my $has_nl = $node =~ s/\r?\n\Z//s; |
194
|
633
|
100
|
|
|
|
2175
|
push @queue, qtext($node) if $node ne ''; # 削ったら空になるかも。 |
195
|
633
|
|
|
|
|
1907
|
$self->{curline} += numLines($node); |
196
|
633
|
100
|
|
|
|
1575
|
$self->{curline}++ if $has_nl; |
197
|
|
|
|
|
|
|
push @queue, q{"\n"} if $has_nl |
198
|
633
|
100
|
100
|
|
|
1479
|
and @{$self->{curtoks}} || not $self->{no_last_newline}; |
|
|
|
66
|
|
|
|
|
199
|
633
|
100
|
100
|
|
|
2489
|
$flush->($has_nl) if $has_nl || $node =~ /\n/; |
200
|
633
|
|
|
|
|
960
|
next; |
201
|
|
|
|
|
|
|
} |
202
|
379
|
|
100
|
|
|
1162
|
my $pad = $self->sync_curline($node->[NODE_LNO]) // ''; |
203
|
379
|
50
|
|
|
|
1154
|
my $sub = $DISPATCH[$node->[0]] |
204
|
|
|
|
|
|
|
or die $self->generror("Unknown node type: %d", $node->[0]); |
205
|
379
|
|
|
|
|
801
|
my $expr = $sub->($self, $node); |
206
|
358
|
50
|
|
|
|
1093
|
unless (defined $expr) { |
207
|
0
|
|
|
|
|
0
|
push @result, $self->cut_next_nl; |
208
|
0
|
|
|
|
|
0
|
next; |
209
|
|
|
|
|
|
|
} |
210
|
358
|
100
|
|
|
|
732
|
if (ref $expr) { |
211
|
167
|
|
|
167
|
|
743
|
$flush->(undef, sub { ("$$expr;", $self->cut_next_nl) }, $pad); |
|
167
|
|
|
|
|
666
|
|
212
|
|
|
|
|
|
|
} else { |
213
|
191
|
100
|
|
|
|
488
|
$flush->(undef, undef, $pad) if length $pad; |
214
|
191
|
|
|
|
|
323
|
push @queue, $expr; |
215
|
191
|
50
|
|
|
|
657
|
$flush->() if $expr =~ /\n/; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
262
|
|
|
|
|
525
|
$flush->(); |
219
|
262
|
|
|
|
|
4885
|
join " ", @result; |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
sub gen_as { |
222
|
76
|
|
|
76
|
0
|
222
|
(my MY $self, my ($type, $dispatch, $escape, $text_quote)) |
223
|
|
|
|
|
|
|
= splice @_, 0, 5; |
224
|
76
|
|
|
|
|
220
|
local $self->{needs_escaping} = $escape; |
225
|
76
|
|
|
|
|
83
|
my (@result); |
226
|
|
|
|
|
|
|
# Empty expr (ie <:yatt:arg>) should generate q|| as code. |
227
|
76
|
100
|
66
|
|
|
249
|
if (not @_ and $text_quote) { |
228
|
1
|
|
|
|
|
4
|
push @result, qtext(''); |
229
|
|
|
|
|
|
|
} |
230
|
76
|
|
|
|
|
187
|
while (@_) { |
231
|
129
|
|
|
|
|
204
|
my $node = shift; |
232
|
129
|
100
|
|
|
|
312
|
unless (ref $node) { |
233
|
98
|
100
|
|
|
|
282
|
push @result, ($text_quote ? qtext($node) : $node); |
234
|
98
|
|
|
|
|
318
|
$self->{curline} += numLines($node); |
235
|
98
|
|
|
|
|
282
|
next; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
# 許されるのは entity だけでは? でもないか。 element 引数の時は、capture したいはず。 |
238
|
31
|
50
|
|
|
|
101
|
my $sub = $dispatch->[$node->[0]] |
239
|
|
|
|
|
|
|
or die $self->generror("gen_as %s: Unknown node type: %d" |
240
|
|
|
|
|
|
|
, $type, $node->[0]); |
241
|
31
|
|
|
|
|
76
|
my $expr = $sub->($self, $node); |
242
|
31
|
50
|
|
|
|
78
|
next unless defined $expr; |
243
|
31
|
50
|
|
|
|
67
|
if (ref $expr) { |
244
|
0
|
|
|
|
|
0
|
die $self->generror("Syntax error, not allowed here: %s", $$expr); |
245
|
|
|
|
|
|
|
} |
246
|
31
|
|
|
|
|
95
|
push @result, $expr; |
247
|
|
|
|
|
|
|
} |
248
|
76
|
100
|
|
|
|
505
|
wantarray ? @result : join("", @result); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# as_list と対になる。 |
252
|
|
|
|
|
|
|
our @AS_TEXT; |
253
|
|
|
|
|
|
|
$AS_TEXT[TYPE_LCMSG] = \&from_lcmsg; |
254
|
|
|
|
|
|
|
$AS_TEXT[TYPE_ENTITY] = \&from_entity; |
255
|
|
|
|
|
|
|
$AS_TEXT[TYPE_PI] = \&text_from_pi; |
256
|
|
|
|
|
|
|
$AS_TEXT[TYPE_ELEMENT] = \&text_from_element; # XXX: ?? Used?? |
257
|
|
|
|
|
|
|
$AS_TEXT[TYPE_ATT_NESTED] = sub {undef}; # gen_as が scalar 受けゆえ |
258
|
|
|
|
|
|
|
# as_text は、escape 不要。なぜなら、 print 時に escape されるから。 |
259
|
|
|
|
|
|
|
# でも、 escape 有無を flag で渡せた方が、 html 型にも使えて便利では? |
260
|
|
|
|
|
|
|
# というか、 html 型には capture が必要か。 capture は buffering したいよね? |
261
|
|
|
|
|
|
|
sub as_text { |
262
|
14
|
|
|
14
|
0
|
49
|
join '.', shift->gen_as(text => \@AS_TEXT, 0, 1, @_); |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
our @AS_LIST; |
266
|
|
|
|
|
|
|
$AS_LIST[TYPE_ENTITY] = \&from_entity; |
267
|
|
|
|
|
|
|
$AS_LIST[TYPE_PI] = \&list_from_pi; |
268
|
|
|
|
|
|
|
$AS_LIST[TYPE_ELEMENT] = \&list_from_element; |
269
|
|
|
|
|
|
|
$AS_LIST[TYPE_ATT_NESTED] = sub {undef}; # XXX: 微妙 |
270
|
|
|
|
|
|
|
sub as_list { |
271
|
51
|
|
|
51
|
0
|
173
|
shift->gen_as(list => \@AS_LIST, 0, 0, @_); |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
#======================================== |
274
|
|
|
|
|
|
|
sub from_element { |
275
|
|
|
|
|
|
|
# XXX: macro (if, foreach, my, format) (error if は?) |
276
|
141
|
|
|
141
|
0
|
224
|
(my MY $self, my $node) = @_; |
277
|
141
|
|
|
|
|
241
|
my $path = $node->[NODE_PATH]; |
278
|
141
|
50
|
66
|
|
|
496
|
if (my $alt = $self->altgen($path->[0])) { |
|
|
100
|
100
|
|
|
|
|
279
|
0
|
|
|
|
|
0
|
qtext($alt->($node)); |
280
|
|
|
|
|
|
|
} elsif (@$path == 2 |
281
|
|
|
|
|
|
|
and my $macro = $self->can("macro_" . join "_", @$path) |
282
|
|
|
|
|
|
|
|| $self->can("macro_$path->[-1]")) { |
283
|
34
|
|
|
|
|
105
|
$macro->($self, $node); |
284
|
|
|
|
|
|
|
} else { |
285
|
|
|
|
|
|
|
# stack trace に現れるように, 敢えて展開。 |
286
|
107
|
|
|
|
|
185
|
$self->gen_call($node, @{$node->[NODE_PATH]}); |
|
107
|
|
|
|
|
370
|
|
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
sub text_from_element { |
290
|
1
|
|
|
1
|
0
|
3
|
(my MY $self, my $node) = @_; |
291
|
1
|
|
|
|
|
6
|
&YATT::Lite::Breakpoint::breakpoint(); |
292
|
1
|
|
|
|
|
10
|
my $call_ref = $self->from_element($node); |
293
|
1
|
|
|
|
|
5
|
sprintf q{YATT::Lite::Util::captured {my ($CON) = @_; %s}}, $$call_ref; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
sub gen_call { |
297
|
107
|
|
|
107
|
0
|
344
|
(my MY $self, my ($node, @path)) = @_; |
298
|
107
|
|
|
|
|
256
|
my $wname = join ":", @path; |
299
|
107
|
100
|
100
|
|
|
574
|
if (@path == 2 and my $var = $self->find_callable_var($path[-1])) { |
300
|
|
|
|
|
|
|
# code 引数の中の引数のデフォルト値の中に、改行が有ったら?? |
301
|
|
|
|
|
|
|
# XXX: body の引数宣言が無い場合に は、ちゃんと呼び出せるか? |
302
|
22
|
|
|
|
|
80
|
return $self->can("as_varcall_" . $var->type->[0]) |
303
|
|
|
|
|
|
|
->($self, $var, $node); |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
85
|
100
|
|
|
|
506
|
my Widget $widget = $self->lookup_widget(@path) or do { |
307
|
2
|
|
|
|
|
7
|
my $err = $self->generror(q{No such widget <%s>}, $wname); |
308
|
2
|
|
|
|
|
116
|
die $err; |
309
|
|
|
|
|
|
|
}; |
310
|
|
|
|
|
|
|
|
311
|
83
|
|
|
|
|
365
|
$self->ensure_generated(perl => my Template $tmpl = $widget->{cf_folder}); |
312
|
83
|
|
|
|
|
209
|
my $use_this = $tmpl == $self->{curtmpl}; |
313
|
83
|
100
|
|
|
|
258
|
unless ($use_this) { |
314
|
15
|
|
|
|
|
104
|
$self->{curtmpl}->add_dependency($wname, $tmpl); |
315
|
|
|
|
|
|
|
} |
316
|
83
|
100
|
|
|
|
182
|
my $that = $use_this ? '$this' : $tmpl->{cf_entns}; |
317
|
|
|
|
|
|
|
\ sprintf(q{%s->render_%s($CON, %s)} |
318
|
|
|
|
|
|
|
, $that, $widget->{cf_name} |
319
|
83
|
|
|
|
|
363
|
, $self->gen_putargs($widget, $node) |
320
|
|
|
|
|
|
|
); |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
sub gen_putargs { |
323
|
105
|
|
|
105
|
0
|
194
|
(my MY $self, my Widget $widget, my $node, my $delegate_vars) = @_; |
324
|
105
|
|
|
|
|
345
|
my ($path, $body, $primary, $head, $foot) = nx($node); |
325
|
|
|
|
|
|
|
return '' if not $delegate_vars and not $widget->{has_required_arg} |
326
|
105
|
100
|
66
|
|
|
1014
|
and not $primary and not $body; |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
327
|
72
|
|
|
|
|
190
|
my $wname = join ":", @$path; |
328
|
72
|
|
|
|
|
96
|
my ($posArgs, $actualNo, @argOrder); |
329
|
|
|
|
|
|
|
my $add_arg = sub { |
330
|
124
|
|
|
124
|
|
209
|
my ($name) = @_; |
331
|
124
|
100
|
|
|
|
387
|
my $formal = $widget->{arg_dict}{$name} or do { |
332
|
2
|
|
|
|
|
8
|
die $self->generror(q{Unknown arg '%s' in widget %s}, $name, $wname); |
333
|
|
|
|
|
|
|
}; |
334
|
122
|
50
|
|
|
|
351
|
if (defined $argOrder[my $argno = $formal->argno]) { |
335
|
0
|
|
|
|
|
0
|
die $self->generror(q{Duplicate arg '%s'}, $name); |
336
|
|
|
|
|
|
|
} else { |
337
|
122
|
|
|
|
|
213
|
$argOrder[$argno] = ++$actualNo; |
338
|
|
|
|
|
|
|
} |
339
|
122
|
|
|
|
|
237
|
$formal; |
340
|
72
|
|
|
|
|
313
|
}; |
341
|
|
|
|
|
|
|
# primary 引数 |
342
|
|
|
|
|
|
|
my @argExpr = map { |
343
|
72
|
|
|
|
|
160
|
$self->sync_curline($_->[NODE_LNO]), ", ", $self->add_curline(do { |
|
83
|
|
|
|
|
274
|
|
344
|
83
|
|
|
|
|
220
|
my $name = argName($_); |
345
|
83
|
100
|
|
|
|
224
|
unless (defined $name) { |
346
|
8
|
50
|
|
|
|
30
|
defined($name = $widget->{arg_order}[$posArgs++]) |
347
|
|
|
|
|
|
|
or die $self->generror("Too many args"); |
348
|
|
|
|
|
|
|
} |
349
|
83
|
|
|
|
|
187
|
my $formal = $add_arg->($name); |
350
|
81
|
100
|
66
|
|
|
188
|
unless (my $passThruVar = passThruVar($_)) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
351
|
46
|
|
|
|
|
106
|
$self->as_cast_to($formal, argValue($_)); |
352
|
|
|
|
|
|
|
} elsif (my $actual = $self->find_var($passThruVar)) { |
353
|
30
|
100
|
100
|
|
|
138
|
if ($formal->already_escaped and not $actual->already_escaped) { |
354
|
|
|
|
|
|
|
# 受け手が escape 済みを期待しているのに、送り手がまだ escape されてないケース |
355
|
2
|
|
|
|
|
18
|
$self->as_escaped($actual); |
356
|
|
|
|
|
|
|
} else { |
357
|
28
|
|
|
|
|
66
|
$self->as_lvalue($actual); |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
} elsif (not defined argValue($_) and defined(my $v = $formal->flag)) { |
360
|
|
|
|
|
|
|
# フラグ立てとして扱って良い型の場合。 |
361
|
2
|
|
|
|
|
8
|
$v; |
362
|
|
|
|
|
|
|
} else { |
363
|
3
|
|
|
|
|
11
|
die $self->generror(q{valueless arg '%s'}, $passThruVar); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
}); |
366
|
|
|
|
|
|
|
} @$primary; |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
# element 引数 |
369
|
67
|
100
|
|
|
|
218
|
foreach my $arg (lexpand($head), $body ? $body : (), lexpand($foot)) { |
370
|
41
|
|
|
|
|
98
|
my ($name, $expr) = @$arg[NODE_PATH, NODE_VALUE]; |
371
|
41
|
100
|
|
|
|
142
|
my $formal = $add_arg->(ref $name ? $name->[-1] : $name); |
372
|
41
|
|
|
|
|
120
|
push @argExpr, ", ", $self->as_cast_to($formal, $expr); |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# delegate の補間と、必須引数検査 |
376
|
65
|
|
|
|
|
111
|
foreach my $i (0 .. $#{$widget->{arg_order}}) { |
|
65
|
|
|
|
|
233
|
|
377
|
166
|
100
|
|
|
|
405
|
next if defined $argOrder[$i]; |
378
|
50
|
|
|
|
|
110
|
my $argName = $widget->{arg_order}[$i]; |
379
|
50
|
100
|
|
|
|
255
|
if (my $inherit = $delegate_vars->{$argName}) { |
|
|
100
|
|
|
|
|
|
380
|
4
|
|
|
|
|
10
|
push @argExpr, ', '. $self->as_lvalue($inherit); |
381
|
4
|
|
|
|
|
14
|
$argOrder[$inherit->argno] = ++$actualNo; |
382
|
|
|
|
|
|
|
} elsif ($widget->{arg_dict}{$argName}->is_required) { |
383
|
1
|
|
|
|
|
6
|
die $self->generror("Argument '%s' is missing", $argName); |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
sprintf q{(undef%s)[%s]} |
387
|
165
|
100
|
|
|
|
1134
|
, join("", @argExpr), join(", ", map {defined $_ ? $_ : 0} |
388
|
64
|
|
|
|
|
215
|
@argOrder[0 .. $#{$widget->{arg_order}}]); |
|
64
|
|
|
|
|
174
|
|
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
sub as_lvalue { |
391
|
711
|
|
|
711
|
0
|
1073
|
(my MY $self, my $var) = @_; |
392
|
711
|
|
|
|
|
1945
|
my $type = $var->type; |
393
|
711
|
50
|
|
|
|
3496
|
unless (defined $type) { |
|
|
100
|
|
|
|
|
|
394
|
0
|
|
|
|
|
0
|
die $self->generror("undefined var type"); |
395
|
|
|
|
|
|
|
} elsif (my $sub = $self->can("as_lvalue_" . $type->[0])) { |
396
|
27
|
|
|
|
|
99
|
$sub->($self, $var); |
397
|
|
|
|
|
|
|
} else { |
398
|
684
|
|
|
|
|
1809
|
'$'.$var->varname; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
sub as_lvalue_html { |
402
|
47
|
|
|
47
|
0
|
74
|
(my MY $self, my $var) = @_; |
403
|
47
|
|
|
|
|
131
|
'$html_'.$var->varname; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
sub as_varcall_code { |
406
|
20
|
|
|
20
|
0
|
48
|
(my MY $self, my ($codeVar, $node)) = @_; |
407
|
20
|
|
|
|
|
74
|
return \ sprintf q{$%1$s && $%1$s->(%2$s)}, $codeVar->varname |
408
|
|
|
|
|
|
|
, $self->gen_putargs($codeVar->widget, $node); |
409
|
|
|
|
|
|
|
# XXX: デフォルト body のように、引数宣言が無いケースも考慮せよ。 |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
sub as_varcall_delegate { |
412
|
2
|
|
|
2
|
0
|
5
|
(my MY $self, my ($var, $node)) = @_; |
413
|
2
|
|
|
|
|
8
|
my Widget $delegate = $var->widget; |
414
|
2
|
|
|
|
|
15
|
$self->ensure_generated(perl => my Template $tmpl = $delegate->{cf_folder}); |
415
|
2
|
50
|
|
|
|
8
|
my $that = $tmpl == $self->{curtmpl} ? '$this' : $tmpl->{cf_entns}; |
416
|
|
|
|
|
|
|
\ sprintf(q{%s->render_%s($CON, %s)} |
417
|
|
|
|
|
|
|
, $that, $delegate->{cf_name} |
418
|
2
|
|
|
|
|
8
|
, $self->gen_putargs($delegate, $node, $var->delegate_vars)); |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
sub as_escaped { |
421
|
6
|
|
|
6
|
0
|
9
|
(my MY $self, my $var) = @_; |
422
|
6
|
50
|
|
|
|
21
|
if (my $sub = $self->can("as_escaped_" . $var->type->[0])) { |
423
|
0
|
|
|
|
|
0
|
$sub->($self, $var); |
424
|
|
|
|
|
|
|
} else { |
425
|
6
|
|
|
|
|
22
|
'YATT::Lite::Util::escape($'.$var->varname.')'; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
#======================================== |
430
|
|
|
|
|
|
|
sub as_cast_to { |
431
|
124
|
|
|
124
|
0
|
232
|
(my MY $self, my $var, my $value) = @_; |
432
|
124
|
|
|
|
|
334
|
my $type = $var->type->[0]; |
433
|
124
|
50
|
|
|
|
647
|
my $sub = $self->can("as_cast_to_$type") |
434
|
|
|
|
|
|
|
or die $self->generror(q{Can't cast to type: %s}, $type); |
435
|
124
|
|
|
|
|
309
|
$sub->($self, $var, $value); |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
sub as_cast_to_text { |
438
|
68
|
|
|
68
|
0
|
161
|
(my MY $self, my ($var, $value)) = @_; |
439
|
68
|
100
|
|
|
|
309
|
return qtext($value) unless ref $value; |
440
|
14
|
|
|
|
|
48
|
$self->as_text(@$value); |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
sub as_cast_to_attr { |
443
|
2
|
|
|
2
|
0
|
8
|
shift->as_cast_to_text(@_); |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
sub as_cast_to_html { |
446
|
15
|
|
|
15
|
0
|
34
|
(my MY $self, my ($var, $value)) = @_; |
447
|
15
|
100
|
|
|
|
41
|
unless (ref $value) { |
448
|
4
|
|
|
|
|
15
|
$self->{curline} += numLines($value); |
449
|
4
|
|
|
|
|
15
|
return qtext($value); |
450
|
|
|
|
|
|
|
} |
451
|
11
|
|
|
|
|
40
|
join '.', shift->gen_as(text => \@AS_TEXT, 1, 1, @$value); |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
sub as_cast_to_scalar { |
454
|
6
|
|
|
6
|
0
|
16
|
(my MY $self, my ($var, $value)) = @_; |
455
|
6
|
100
|
|
|
|
49
|
'scalar(do {'.(ref $value ? $self->as_list(@$value) : $value).'})'; |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
sub as_cast_to_bool { |
458
|
0
|
|
|
0
|
0
|
0
|
shift->as_cast_to_scalar(@_); |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
sub as_cast_to_list { |
461
|
3
|
|
|
3
|
0
|
9
|
(my MY $self, my ($var, $value)) = @_; |
462
|
3
|
100
|
|
|
|
24
|
'['.(ref $value ? $self->as_list(@$value) : $value).']'; |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
sub as_cast_to_code { |
465
|
32
|
|
|
32
|
0
|
66
|
(my MY $self, my ($var, $value)) = @_; |
466
|
32
|
|
|
|
|
136
|
local $self->{curtoks} = [@$value]; |
467
|
32
|
|
|
|
|
105
|
my Widget $virtual = $var->widget; |
468
|
|
|
|
|
|
|
local $self->{scope} = $self->mkscope |
469
|
32
|
|
100
|
|
|
261
|
({}, $virtual->{arg_dict} ||= {}, $self->{scope}); |
470
|
32
|
|
|
|
|
81
|
local $self->{no_last_newline} = 1; |
471
|
32
|
|
|
|
|
78
|
q|sub {|. join('', $self->gen_getargs($virtual) |
472
|
|
|
|
|
|
|
, $self->as_print("}")); |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
#---------------------------------------- |
475
|
|
|
|
|
|
|
sub argName { |
476
|
133
|
|
|
133
|
0
|
220
|
my ($arg, $skip) = @_; |
477
|
133
|
|
|
|
|
238
|
my $name = $$arg[NODE_PATH]; |
478
|
133
|
100
|
100
|
|
|
509
|
unless (wantarray and ref $name) { |
|
|
100
|
|
|
|
|
|
479
|
125
|
|
|
|
|
332
|
$name; |
480
|
|
|
|
|
|
|
} elsif (defined $skip) { |
481
|
2
|
|
|
|
|
5
|
@{$name}[$skip .. $#$name]; |
|
2
|
|
|
|
|
7
|
|
482
|
|
|
|
|
|
|
} else { |
483
|
6
|
|
|
|
|
23
|
@$name; |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
} |
486
|
83
|
|
|
83
|
0
|
118
|
sub argValue { my $arg = shift; $$arg[NODE_VALUE] } |
|
83
|
|
|
|
|
302
|
|
487
|
|
|
|
|
|
|
sub passThruVar { |
488
|
88
|
|
|
88
|
0
|
126
|
my $arg = shift; |
489
|
88
|
100
|
|
|
|
384
|
if ($arg->[NODE_TYPE] == TYPE_ATT_NAMEONLY) { |
|
|
100
|
|
|
|
|
|
490
|
33
|
|
|
|
|
173
|
$$arg[NODE_PATH] |
491
|
|
|
|
|
|
|
} elsif ($arg->[NODE_TYPE] == TYPE_ATT_BARENAME) { |
492
|
8
|
|
|
|
|
49
|
$$arg[NODE_VALUE] |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
#======================================== |
496
|
|
|
|
|
|
|
sub from_pi { |
497
|
37
|
|
|
37
|
0
|
60
|
(my MY $self, my $node) = @_; |
498
|
|
|
|
|
|
|
# pi の ns 毎の役割を拡張可能に |
499
|
37
|
50
|
|
|
|
226
|
if (my $sub = $self->can("pi_of_" . $node->[NODE_PATH][0])) { |
500
|
0
|
|
|
|
|
0
|
return $sub->($self, $node); |
501
|
|
|
|
|
|
|
} |
502
|
37
|
|
|
|
|
121
|
$self->sync_curline($node->[NODE_LNO]); |
503
|
37
|
|
|
|
|
117
|
my @body = nx($node, 1); |
504
|
37
|
|
|
|
|
65
|
my ($fmt, $is_statement) = do { |
505
|
37
|
100
|
|
|
|
153
|
unless ($body[0] =~ s/^=+//) { |
|
|
100
|
|
|
|
|
|
506
|
25
|
|
|
|
|
81
|
(q{%s}, 1); |
507
|
|
|
|
|
|
|
} elsif (length $& >= 3) { |
508
|
6
|
|
|
|
|
17
|
q{do {%s}}; |
509
|
|
|
|
|
|
|
} else { |
510
|
6
|
|
|
|
|
20
|
q{YATT::Lite::Util::escape(do {%s})}; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
}; |
513
|
37
|
|
|
|
|
116
|
my $expr = join '', $self->as_list(@body); |
514
|
37
|
100
|
|
|
|
204
|
return \ "" unless $expr =~ /\S/; |
515
|
36
|
|
|
|
|
95
|
my $script = sprintf $fmt, $expr; |
516
|
36
|
100
|
|
|
|
122
|
$is_statement ? \ $script : $script; |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
#======================================== |
519
|
|
|
|
0
|
0
|
|
sub from_lineinfo { } |
520
|
|
|
|
|
|
|
sub from_comment { |
521
|
2
|
|
|
2
|
0
|
3
|
(my MY $self, my $node) = @_; |
522
|
2
|
|
|
|
|
8
|
(undef, my ($nlines, $body)) = nx($node); # XXX: ok? |
523
|
2
|
|
|
|
|
326
|
$self->{curline} += $nlines; |
524
|
2
|
|
|
|
|
8
|
return \ ("\n" x $nlines); |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
sub from_lcmsg { |
527
|
3
|
|
|
3
|
0
|
11
|
(my MY $self, my $node) = @_; |
528
|
3
|
|
|
|
|
9
|
my ($path, $body) = nx($node); |
529
|
|
|
|
|
|
|
# $body is list of tokenlist. |
530
|
3
|
|
|
|
|
13
|
my $place = $self->{curtmpl}->fake_filename . ":" . $node->[NODE_LNO]; |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
# XXX: builtin xgettext |
533
|
3
|
100
|
66
|
|
|
17
|
if (@$body >= 2 or @$path >= 2) { |
534
|
|
|
|
|
|
|
# ngettext |
535
|
1
|
|
|
|
|
3
|
my ($uniq, $args, $numexpr) = ({}, []); |
536
|
|
|
|
|
|
|
my ($msgid, @plural) = map { |
537
|
1
|
|
|
|
|
3
|
scalar $self->gen_lcmsg($node, $_, $uniq, $args, \$numexpr); |
|
2
|
|
|
|
|
6
|
|
538
|
|
|
|
|
|
|
} @$body; |
539
|
1
|
50
|
|
|
|
6
|
if (my $sub = $self->{cf_lcmsg_sink}) { |
540
|
1
|
|
|
|
|
10
|
$sub->($place, $msgid, \@plural, $args); |
541
|
|
|
|
|
|
|
} |
542
|
|
|
|
|
|
|
sprintf q{sprintf($CON->ngettext(%s, %s), %s)} |
543
|
1
|
|
|
|
|
9
|
, join(", ", map {qtext($_)} ($msgid, @plural)) |
|
2
|
|
|
|
|
6
|
|
544
|
|
|
|
|
|
|
, $numexpr, join(", ", @$args); |
545
|
|
|
|
|
|
|
} else { |
546
|
2
|
|
|
|
|
9
|
my ($msgid, @args) = $self->gen_lcmsg($node, $body->[0]); |
547
|
2
|
50
|
|
|
|
10
|
if (my $sub = $self->{cf_lcmsg_sink}) { |
548
|
2
|
|
|
|
|
7
|
$sub->($place, $msgid, undef, \@args); |
549
|
|
|
|
|
|
|
} |
550
|
2
|
|
|
|
|
18
|
sprintf q{sprintf($CON->gettext(%s), %s)} |
551
|
|
|
|
|
|
|
, qtext($msgid), join(", ", @args); |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
} |
554
|
|
|
|
|
|
|
sub gen_lcmsg { |
555
|
4
|
|
|
4
|
0
|
11
|
(my MY $self, my ($node, $list, $uniq, $args, $ref_numeric)) = @_; |
556
|
4
|
|
|
|
|
7
|
my ($msgid, $vspec) = (""); |
557
|
4
|
100
|
33
|
|
|
62
|
if (@$list >= 2 and not ref $list->[0] and not ref $list->[-1] |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
558
|
|
|
|
|
|
|
and $list->[0] =~ /^\n+$/ and $list->[-1] =~ /^\n+$/) { |
559
|
2
|
|
|
|
|
4
|
shift @$list; pop @$list; |
|
2
|
|
|
|
|
3
|
|
560
|
2
|
50
|
33
|
|
|
12
|
if (@$list and not ref $list->[0]) { |
561
|
2
|
|
|
|
|
8
|
$list->[0] =~ s/^\s+//; |
562
|
|
|
|
|
|
|
} |
563
|
|
|
|
|
|
|
} |
564
|
4
|
|
|
|
|
9
|
foreach my $item (@$list) { |
565
|
12
|
100
|
33
|
|
|
51
|
unless (ref $item) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
566
|
|
|
|
|
|
|
# XXX: How about backslash? |
567
|
7
|
|
|
|
|
18
|
(my $cp = $item) =~ s/%/%%/g; |
568
|
7
|
|
|
|
|
15
|
$msgid .= $cp; |
569
|
|
|
|
|
|
|
} elsif ($item->[NODE_TYPE] != TYPE_ENTITY) { |
570
|
0
|
|
|
|
|
0
|
die "SYNERR"; |
571
|
|
|
|
|
|
|
} elsif (ref ($vspec = $item->[NODE_BODY]) ne 'ARRAY' |
572
|
|
|
|
|
|
|
|| $vspec->[0] ne 'var') { |
573
|
|
|
|
|
|
|
# || @$vspec != 2 |
574
|
0
|
|
|
|
|
0
|
die "SYNERR"; |
575
|
|
|
|
|
|
|
} else { |
576
|
5
|
|
|
|
|
8
|
my $name = $vspec->[1]; |
577
|
5
|
50
|
|
|
|
17
|
my $var = $self->find_var($name) |
578
|
|
|
|
|
|
|
or die $self->generror(q{No such variable '%s'}, $name); |
579
|
5
|
100
|
|
|
|
19
|
unless ($uniq->{$name}) { |
580
|
4
|
|
|
|
|
18
|
push @$args, $self->as_escaped($var); |
581
|
4
|
|
|
|
|
14
|
$uniq->{$name} = 1 + keys %$uniq; |
582
|
|
|
|
|
|
|
} |
583
|
5
|
100
|
|
|
|
14
|
my $argno = $ref_numeric ? $uniq->{$name} . '$' : ''; |
584
|
|
|
|
|
|
|
# XXX: type==value is alias of scalar. |
585
|
5
|
100
|
100
|
|
|
20
|
if ($ref_numeric and $var->type->[0] eq 'scalar') { |
586
|
1
|
|
|
|
|
4
|
$msgid .= "%${argno}d"; # XXX: format selection... but how? from entity? |
587
|
1
|
50
|
|
|
|
4
|
if ($$ref_numeric) { |
588
|
0
|
|
|
|
|
0
|
die "SYNERR"; |
589
|
|
|
|
|
|
|
} |
590
|
1
|
|
|
|
|
4
|
$$ref_numeric = $self->as_lvalue($var); |
591
|
|
|
|
|
|
|
} else { |
592
|
4
|
|
|
|
|
18
|
$msgid .= "%${argno}s"; |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
} |
596
|
4
|
|
|
|
|
7
|
$msgid =~ s/\r//g; |
597
|
|
|
|
|
|
|
# XXX: Unfortunately, this is not good for multiline message. |
598
|
4
|
100
|
|
|
|
18
|
wantarray ? ($msgid, lexpand($args)) : $msgid; |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
sub from_elematt { |
602
|
0
|
|
|
0
|
0
|
0
|
(my MY $self, my $node) = @_; |
603
|
|
|
|
|
|
|
# <:yatt:elematt>.... は NOP へ。 |
604
|
0
|
|
|
|
|
0
|
return \ ""; |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
sub from_entity { |
607
|
227
|
|
|
227
|
0
|
363
|
(my MY $self, my $node) = @_; |
608
|
227
|
|
|
|
|
625
|
(undef, my @pipe) = nx($node); |
609
|
|
|
|
|
|
|
# XXX: expand のように全体に作用するものも有るから、これも現在の式を渡す方式にすべき。 |
610
|
|
|
|
|
|
|
# 受け手が有るかどうかで式の生成方式も変わる?なら token リスト削りが良いか。 |
611
|
227
|
|
|
|
|
870
|
$self->gen_entpath($self->{needs_escaping}, @pipe); |
612
|
|
|
|
|
|
|
} |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
# XXX: lxnest を caller が呼ぶ必要が有る...が、それって良いことなのか... |
615
|
|
|
|
|
|
|
sub gen_entpath { |
616
|
326
|
|
|
326
|
0
|
659
|
(my MY $self, my ($escape_now)) = splice @_, 0, 2; |
617
|
326
|
50
|
|
|
|
833
|
return '' unless @_; |
618
|
326
|
|
|
|
|
742
|
local $self->{needs_escaping} = 0; |
619
|
326
|
100
|
100
|
|
|
2086
|
if (@_ == 1 and $_[0][0] eq 'call' |
|
|
|
100
|
|
|
|
|
620
|
|
|
|
|
|
|
and my $macro = $self->can("entmacro_$_[0][1]")) { |
621
|
10
|
|
|
|
|
34
|
return $macro->($self, $_[0]); |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
# XXX: path の先頭と以後は分けないと! as_head, as_rest? |
624
|
|
|
|
|
|
|
my @result = map { |
625
|
316
|
|
|
|
|
507
|
my ($type, @rest) = @$_; |
|
354
|
|
|
|
|
859
|
|
626
|
354
|
50
|
|
|
|
1684
|
unless (my $sub = $self->can("as_expr_$type")) { |
627
|
0
|
|
|
|
|
0
|
die $self->generror("unknown entity item %s", terse_dump($type)); |
628
|
|
|
|
|
|
|
} else { |
629
|
354
|
|
|
|
|
861
|
$sub->($self, \$escape_now, @rest); |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
} @_; |
632
|
307
|
50
|
|
|
|
755
|
return '' unless @result; |
633
|
307
|
100
|
|
|
|
742
|
my $result = @result > 1 ? join("->", @result) : $result[0]; |
634
|
|
|
|
|
|
|
# XXX: これだと逆に、 html 型が困る。 |
635
|
307
|
100
|
100
|
|
|
1166
|
if (not $escape_now or ref $result) { |
636
|
149
|
|
|
|
|
610
|
$result; |
637
|
|
|
|
|
|
|
} else { |
638
|
158
|
|
|
|
|
788
|
sprintf(q{YATT::Lite::Util::escape(%s)}, $result); |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
sub gen_entlist { |
642
|
50
|
|
|
50
|
0
|
122
|
(my MY $self, my ($escape_now)) = splice @_, 0, 2; |
643
|
|
|
|
|
|
|
my @list = map { |
644
|
50
|
|
|
|
|
99
|
$self->gen_entpath($escape_now, lxnest($_)) |
|
63
|
|
|
|
|
178
|
|
645
|
|
|
|
|
|
|
} @_; |
646
|
50
|
100
|
|
|
|
339
|
wantarray ? @list : join ", ", @list; |
647
|
|
|
|
|
|
|
} |
648
|
|
|
|
|
|
|
sub as_expr_var { |
649
|
212
|
|
|
212
|
0
|
470
|
(my MY $self, my ($esc_later, $name)) = @_; |
650
|
212
|
100
|
|
|
|
658
|
my $var = $self->find_var($name) |
651
|
|
|
|
|
|
|
or die $self->generror(q{No such variable '%s'}, $name); |
652
|
204
|
100
|
|
|
|
614
|
if (my $sub = $self->can("as_expr_var_" . $var->type->[0])) { |
653
|
25
|
|
|
|
|
66
|
$sub->($self, $esc_later, $var, $name); |
654
|
|
|
|
|
|
|
} else { |
655
|
179
|
|
|
|
|
402
|
$self->as_lvalue($var); |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
} |
658
|
|
|
|
|
|
|
sub as_expr_var_html { |
659
|
20
|
|
|
20
|
0
|
55
|
(my MY $self, my ($esc_later, $var, $name)) = @_; |
660
|
20
|
|
|
|
|
38
|
$$esc_later = 0; |
661
|
20
|
|
|
|
|
46
|
$self->as_lvalue_html($var); |
662
|
|
|
|
|
|
|
} |
663
|
|
|
|
|
|
|
sub as_expr_var_attr { |
664
|
5
|
|
|
5
|
0
|
13
|
(my MY $self, my ($esc_later, $var, $name)) = @_; |
665
|
|
|
|
|
|
|
# $$esc_later = 0; |
666
|
5
|
|
|
|
|
7
|
(undef, my $attname) = @{$var->type}; |
|
5
|
|
|
|
|
16
|
|
667
|
5
|
|
33
|
|
|
44
|
sprintf(q{YATT::Lite::Util::named_attr('%s', $%s)} |
668
|
|
|
|
|
|
|
, $attname // $name, $name); |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
sub as_expr_call { |
671
|
36
|
|
|
36
|
0
|
144
|
(my MY $self, my ($esc_later, $name)) = splice @_, 0, 3; |
672
|
|
|
|
|
|
|
# XXX: 受け側が print か、それとも一般の式か。 print なら \ すべき。 |
673
|
|
|
|
|
|
|
# entns があるか、find_code_var か。さもなければエラーよね。 |
674
|
36
|
100
|
|
|
|
138
|
if (my $var = $self->find_callable_var($name)) { |
675
|
|
|
|
|
|
|
# code 引数の中の引数のデフォルト値の中に、改行が有ったら?? |
676
|
|
|
|
|
|
|
# XXX: body の引数宣言が無い場合に は、ちゃんと呼び出せるか? |
677
|
11
|
|
|
|
|
43
|
return $self->as_expr_call_var($var, $name, @_); |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
|
680
|
25
|
|
|
|
|
100
|
my Template $tmpl = $self->{curtmpl}; |
681
|
25
|
100
|
|
|
|
499
|
unless ($tmpl->{cf_entns}->can("entity_$name")) { |
682
|
|
|
|
|
|
|
die $self->generror(q!No such entity in namespace "%s": %s! |
683
|
1
|
|
|
|
|
6
|
, $tmpl->{cf_entns}, $name); |
684
|
|
|
|
|
|
|
} |
685
|
24
|
|
|
|
|
102
|
my $call = sprintf '$this->entity_%s(%s)', $name |
686
|
|
|
|
|
|
|
, scalar $self->gen_entlist(undef, @_); |
687
|
24
|
|
|
|
|
100
|
$call; |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
sub as_expr_call_var { |
690
|
11
|
|
|
11
|
0
|
33
|
(my MY $self, my ($var, $name, @args)) = @_; |
691
|
11
|
100
|
|
|
|
37
|
if (my $sub = $self->can("as_expr_call_var_" . $var->type->[0])) { |
692
|
1
|
|
|
|
|
12
|
$sub->($self, $var, $name, @args); |
693
|
|
|
|
|
|
|
} else { |
694
|
10
|
|
|
|
|
39
|
\ sprintf q{$%1$s && $%1$s->(%2$s)}, $name |
695
|
|
|
|
|
|
|
, scalar $self->gen_entlist(undef, @args); |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
sub as_expr_call_var_attr { |
699
|
1
|
|
|
1
|
0
|
5
|
(my MY $self, my ($var, $name, @args)) = @_; |
700
|
1
|
|
|
|
|
2
|
(undef, my $attname) = @{$var->type}; |
|
1
|
|
|
|
|
5
|
|
701
|
1
|
|
33
|
|
|
9
|
sprintf q|YATT::Lite::Util::named_attr('%s', %s)| |
702
|
|
|
|
|
|
|
, $attname // $name |
703
|
|
|
|
|
|
|
, join ", ", '$'.$name, $self->gen_entlist(undef, @args); |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
sub as_expr_invoke { |
706
|
5
|
|
|
5
|
0
|
18
|
(my MY $self, my ($esc_later, $name)) = splice @_, 0, 3; |
707
|
5
|
|
|
|
|
37
|
sprintf '%s(%s)', $name |
708
|
|
|
|
|
|
|
, scalar $self->gen_entlist(undef, @_); |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
sub as_expr_expr { |
712
|
21
|
|
|
21
|
0
|
51
|
(my MY $self, my ($esc_later, $expr)) = @_; |
713
|
21
|
|
|
|
|
86
|
$expr; |
714
|
|
|
|
|
|
|
} |
715
|
|
|
|
|
|
|
sub as_expr_array { |
716
|
5
|
|
|
5
|
0
|
11
|
(my MY $self, my ($esc_later)) = splice @_, 0, 2; |
717
|
5
|
|
|
|
|
20
|
'['.$self->gen_entlist(undef, @_).']'; |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
sub as_expr_hash { |
720
|
0
|
|
|
0
|
0
|
0
|
(my MY $self, my ($esc_later)) = splice @_, 0, 2; |
721
|
0
|
|
|
|
|
0
|
'{'.$self->gen_entlist(undef, @_).'}'; |
722
|
|
|
|
|
|
|
} |
723
|
|
|
|
|
|
|
sub as_expr_aref { |
724
|
21
|
|
|
21
|
0
|
41
|
(my MY $self, my ($esc_later, $node)) = @_; |
725
|
21
|
|
|
|
|
63
|
'['.$self->gen_entpath(undef, lxnest($node)).']'; |
726
|
|
|
|
|
|
|
} |
727
|
|
|
|
|
|
|
sub as_expr_href { |
728
|
10
|
|
|
10
|
0
|
22
|
(my MY $self, my ($esc_later, $node)) = @_; |
729
|
10
|
|
|
|
|
41
|
'{'.$self->gen_entpath(undef, lxnest($node)).'}'; |
730
|
|
|
|
|
|
|
} |
731
|
|
|
|
|
|
|
sub as_expr_prop { |
732
|
2
|
|
|
2
|
0
|
6
|
(my MY $self, my ($esc_later, $name)) = @_; |
733
|
2
|
50
|
|
|
|
10
|
if ($name =~ /^\w+$/) { |
734
|
2
|
|
|
|
|
10
|
"{$name}" |
735
|
|
|
|
|
|
|
} else { |
736
|
0
|
|
|
|
|
0
|
'{'.qtext($name).'}'; |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
} |
739
|
|
|
|
|
|
|
sub as_expr_text { |
740
|
42
|
|
|
42
|
0
|
91
|
(my MY $self, my ($esc_later, $expr)) = @_; |
741
|
42
|
|
|
|
|
131
|
qqvalue($expr); |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
#======================================== |
744
|
|
|
|
|
|
|
} |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
sub make_arg_spec { |
747
|
18
|
|
|
18
|
0
|
55
|
my ($pack, $dict, $order) = splice @_, 0, 3; |
748
|
18
|
|
|
|
|
42
|
foreach my $name (@_) { |
749
|
45
|
|
|
|
|
108
|
$dict->{$name} = @$order; |
750
|
45
|
|
|
|
|
121
|
push @$order, $name; |
751
|
|
|
|
|
|
|
} |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
sub feed_arg_spec { |
755
|
22
|
|
|
22
|
0
|
59
|
(my MY $trans, my ($args, $arg_dict, $arg_order)) = splice @_, 0, 4; |
756
|
22
|
|
|
|
|
36
|
my ($found, $nth); |
757
|
22
|
|
|
|
|
61
|
foreach my $arg (lexpand($args)) { |
758
|
25
|
|
|
|
|
68
|
my ($name, @ext) = argName($arg); # XXX: は? |
759
|
25
|
100
|
|
|
|
63
|
unless (defined $name) { |
760
|
7
|
50
|
|
|
|
31
|
$name = $arg_order->[$nth++] |
761
|
|
|
|
|
|
|
or die $trans->generror($arg, "Too many args"); |
762
|
|
|
|
|
|
|
} |
763
|
25
|
50
|
|
|
|
84
|
defined (my $argno = $arg_dict->{$name}) |
764
|
|
|
|
|
|
|
or die $trans->generror($arg, "Unknown arg '%s'", $name); |
765
|
|
|
|
|
|
|
|
766
|
25
|
|
|
|
|
41
|
$_[$argno] = $arg; |
767
|
25
|
|
|
|
|
52
|
$found++; |
768
|
|
|
|
|
|
|
} |
769
|
22
|
|
|
|
|
67
|
$found; |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
{ |
773
|
|
|
|
|
|
|
MY->make_arg_spec(\ my %args, \ my @args, qw(if unless)); |
774
|
|
|
|
|
|
|
sub macro_if { |
775
|
9
|
|
|
9
|
0
|
14
|
(my MY $self, my $node) = @_; |
776
|
9
|
|
|
|
|
35
|
my ($path, $body, $primary, $head, $foot) = nx($node); |
777
|
9
|
|
|
|
|
26
|
my @arms = do { |
778
|
9
|
50
|
|
|
|
39
|
$self->feed_arg_spec($primary, \%args, \@args |
779
|
|
|
|
|
|
|
, my ($if, $unless)) |
780
|
|
|
|
|
|
|
or die $self->generror("Not enough arguments!"); |
781
|
9
|
|
|
|
|
19
|
my ($kw, $cond) = do { |
782
|
9
|
50
|
|
|
|
23
|
if ($if) { (if => $if) } |
|
9
|
0
|
|
|
|
23
|
|
783
|
0
|
|
|
|
|
0
|
elsif ($unless) { (unless => $unless) } |
784
|
0
|
|
|
|
|
0
|
else { die "??" } |
785
|
|
|
|
|
|
|
}; |
786
|
9
|
|
|
|
|
37
|
["$kw (%s) ", $cond->[NODE_VALUE], lexpand($body->[NODE_VALUE])]; |
787
|
|
|
|
|
|
|
}; |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
# いかん、 cond を生成するなら、body も生成しておかないと、行番号が困る。 |
790
|
|
|
|
|
|
|
|
791
|
9
|
|
|
|
|
33
|
foreach my $arg (lexpand($foot)) { |
792
|
6
|
50
|
|
|
|
20
|
if ($arg->[NODE_PATH][-1] eq 'else') { |
793
|
6
|
|
|
|
|
23
|
$self->feed_arg_spec($arg->[NODE_ATTLIST], \%args, \@args |
794
|
|
|
|
|
|
|
, my ($if, $unless)); |
795
|
6
|
|
|
|
|
10
|
my ($fmt, $guard) = do { |
796
|
6
|
100
|
|
|
|
23
|
if ($if) { (q{elsif (%s) }, $if->[NODE_VALUE]) } |
|
2
|
50
|
|
|
|
6
|
|
797
|
0
|
|
|
|
|
0
|
elsif ($unless) { (q{elsif (not %s) }, $unless->[NODE_VALUE]) } |
798
|
4
|
|
|
|
|
10
|
else { (q{else }, undef) } |
799
|
|
|
|
|
|
|
}; |
800
|
6
|
|
|
|
|
21
|
push @arms, [$fmt, $guard, lexpand($arg->[NODE_VALUE])] |
801
|
|
|
|
|
|
|
} else { |
802
|
0
|
|
|
|
|
0
|
push @{$arms[-1]}, lexpand($arg->[NODE_VALUE]); |
|
0
|
|
|
|
|
0
|
|
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
} |
805
|
9
|
|
|
|
|
40
|
local $self->{scope} = $self->mkscope({}, $self->{scope}); |
806
|
|
|
|
|
|
|
my @expr = map { |
807
|
9
|
|
|
|
|
19
|
my ($fmt, $guard, @body) = @$_; |
|
15
|
|
|
|
|
45
|
|
808
|
15
|
|
|
|
|
48
|
local $self->{curtoks} = [@body]; |
809
|
15
|
100
|
|
|
|
61
|
(defined $guard |
810
|
|
|
|
|
|
|
? sprintf($fmt, join "", $self->as_list(lexpand($guard))) : $fmt) |
811
|
|
|
|
|
|
|
.'{'.$self->cut_next_nl.$self->as_print('}'); |
812
|
|
|
|
|
|
|
} @arms; |
813
|
9
|
|
|
|
|
39
|
\ join "", @expr, $self->cut_next_nl; |
814
|
|
|
|
|
|
|
} |
815
|
|
|
|
|
|
|
} |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
{ |
818
|
|
|
|
|
|
|
sub macro_my { |
819
|
15
|
|
|
15
|
0
|
31
|
(my MY $self, my $node) = @_; |
820
|
15
|
|
|
|
|
57
|
my ($path, $body, $primary, $head, $foot) = nx($node); |
821
|
|
|
|
|
|
|
|
822
|
15
|
100
|
66
|
|
|
84
|
my $has_body = $body && @$body ? 1 : 0; |
823
|
|
|
|
|
|
|
my $adder = sub { |
824
|
25
|
|
|
25
|
|
47
|
my ($default_type, $arg, $valNode, $skip) = @_; |
825
|
25
|
|
|
|
|
61
|
my ($name, $typename) = argName($arg, $skip); |
826
|
25
|
100
|
|
|
|
88
|
if (my $oldvar = $self->find_var($name)) { |
827
|
1
|
|
50
|
|
|
6
|
die $self->generror("Conflicting variable '%s'" |
828
|
|
|
|
|
|
|
." (previously defined at line %s)" |
829
|
|
|
|
|
|
|
, $name, $oldvar->lineno // '(unknown)'); |
830
|
|
|
|
|
|
|
} |
831
|
24
|
|
66
|
|
|
88
|
$typename ||= $default_type; |
832
|
24
|
100
|
|
|
|
192
|
if (my $sub = $self->can("_macro_my_$typename")) { |
833
|
3
|
|
|
|
|
10
|
$sub->($self, $node, $name, $valNode); |
834
|
|
|
|
|
|
|
} else { |
835
|
21
|
50
|
|
|
|
64
|
my $var = $self->{scope}[0]{$name} |
836
|
|
|
|
|
|
|
= $self->mkvar_at(undef, $typename, $name) |
837
|
|
|
|
|
|
|
or die $self->generror("Unknown type '%s' for variable '%s'" |
838
|
|
|
|
|
|
|
, $typename, $name); |
839
|
|
|
|
|
|
|
# typename == source の時が問題だ。 |
840
|
21
|
|
|
|
|
57
|
my $expr = 'my '.$self->as_lvalue($var); |
841
|
21
|
|
|
|
|
60
|
my $value = argValue($valNode); |
842
|
21
|
100
|
|
|
|
89
|
$expr .= $value ? (' = '.$self->as_cast_to($var, $value)) : ';'; |
843
|
|
|
|
|
|
|
} |
844
|
15
|
|
|
|
|
72
|
}; |
845
|
15
|
|
|
|
|
26
|
my @assign; |
846
|
15
|
|
|
|
|
34
|
foreach my $arg (@{$primary}[0 .. $#$primary-$has_body]) { |
|
15
|
|
|
|
|
37
|
|
847
|
17
|
|
|
|
|
40
|
push @assign, $adder->(text => $arg, $arg); |
848
|
|
|
|
|
|
|
} |
849
|
14
|
100
|
|
|
|
44
|
if ($has_body) { |
850
|
5
|
|
|
|
|
8
|
my $arg = $primary->[-1]; |
851
|
|
|
|
|
|
|
# XXX: ここは統合できるはず。ただし、NESTED の時に name が無いことを確認すべき。 |
852
|
5
|
100
|
|
|
|
18
|
if ($$arg[NODE_TYPE] == TYPE_ATT_NESTED) { |
853
|
1
|
|
|
|
|
5
|
foreach my $each (nx($arg, 1)) { |
854
|
2
|
|
|
|
|
8
|
push @assign, $adder->(html => $each, $body); |
855
|
|
|
|
|
|
|
} |
856
|
|
|
|
|
|
|
} else { |
857
|
4
|
|
|
|
|
12
|
push @assign, $adder->(html => $arg, $body); |
858
|
|
|
|
|
|
|
} |
859
|
|
|
|
|
|
|
} |
860
|
14
|
|
|
|
|
31
|
foreach my $arg (map {lexpand($_)} $head, $foot) { |
|
28
|
|
|
|
|
76
|
|
861
|
2
|
|
|
|
|
7
|
push @assign, $adder->(text => $arg, $arg, 1); # Skip leading :yatt: |
862
|
|
|
|
|
|
|
} |
863
|
14
|
|
|
|
|
160
|
\ join "; ", @assign; |
864
|
|
|
|
|
|
|
} |
865
|
|
|
|
|
|
|
sub _macro_my_code { |
866
|
2
|
|
|
2
|
|
7
|
(my MY $self, my ($node, $name, $valNode)) = @_; |
867
|
2
|
|
|
|
|
9
|
my $var = $self->{scope}[0]{$name} = $self->mkvar_at(undef, code => $name); |
868
|
2
|
|
|
|
|
9
|
local $self->{curtoks} = [lexpand(argValue($valNode))]; |
869
|
2
|
|
|
|
|
8
|
'my '.$self->as_lvalue($var).' = '.q|sub {| . $self->as_print('}'); |
870
|
|
|
|
|
|
|
} |
871
|
|
|
|
|
|
|
sub _macro_my_source { |
872
|
1
|
|
|
1
|
|
3
|
(my MY $self, my ($node, $name, $valNode)) = @_; |
873
|
1
|
|
|
|
|
5
|
my $var = $self->{scope}[0]{$name} = $self->mkvar_at(undef, text => $name); |
874
|
|
|
|
|
|
|
'my '.$self->as_lvalue($var).' = ' |
875
|
2
|
|
|
|
|
7
|
.join(q|."\n".|, map {qtext($_)} |
876
|
1
|
|
|
|
|
3
|
split /\n/, $self->{curtmpl}->node_body_source($node)); |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
sub macro_block { |
880
|
3
|
|
|
3
|
0
|
5
|
(my MY $self, my $node) = @_; |
881
|
3
|
|
|
|
|
12
|
local $self->{scope} = $self->mkscope({}, $self->{scope}); |
882
|
3
|
|
|
|
|
10
|
my ($path, $body, $primary, $head, $foot) = nx($node); |
883
|
3
|
|
|
|
|
7
|
local $self->{curtoks} = [@{argValue($body)}]; |
|
3
|
|
|
|
|
9
|
|
884
|
3
|
|
|
|
|
9
|
\ ('{'.$self->as_print('}')); |
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
} |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
{ |
889
|
|
|
|
|
|
|
MY->make_arg_spec(\ my %args, \ my @args, qw(list my nth)); |
890
|
|
|
|
|
|
|
sub macro_foreach { |
891
|
7
|
|
|
7
|
0
|
16
|
(my MY $self, my ($node, $opts)) = @_; |
892
|
7
|
|
|
|
|
24
|
my ($path, $body, $primary, $head, $foot) = nx($node); |
893
|
7
|
50
|
|
|
|
37
|
$self->feed_arg_spec($primary, \%args, \@args |
894
|
|
|
|
|
|
|
, my ($list, $my, $nth)) |
895
|
|
|
|
|
|
|
or die $self->generror("Not enough arguments!"); |
896
|
|
|
|
|
|
|
|
897
|
7
|
|
|
|
|
13
|
my ($prologue, $continue, $epilogue) = ('', '', ''); |
898
|
|
|
|
|
|
|
|
899
|
7
|
50
|
|
|
|
19
|
unless (defined $list) { |
900
|
0
|
|
|
|
|
0
|
die $self->generror("no list= is given"); |
901
|
|
|
|
|
|
|
} |
902
|
|
|
|
|
|
|
|
903
|
7
|
|
|
|
|
9
|
my %local; |
904
|
7
|
|
|
|
|
8
|
my $loopvar = do { |
905
|
7
|
100
|
|
|
|
18
|
if ($my) { |
906
|
6
|
|
|
|
|
21
|
my ($x, @type) = lexpand($my->[NODE_PATH]); |
907
|
6
|
|
|
|
|
14
|
my $varname = $my->[NODE_VALUE]; |
908
|
6
|
|
50
|
|
|
39
|
$local{$varname} = $self->mkvar_at(undef, $type[0] || '' => $varname); |
909
|
6
|
|
|
|
|
17
|
'my $' . $varname; |
910
|
|
|
|
|
|
|
} else { |
911
|
|
|
|
|
|
|
# _ は? entity 自体に処理させるか… |
912
|
1
|
|
|
|
|
4
|
'' |
913
|
|
|
|
|
|
|
} |
914
|
|
|
|
|
|
|
}; |
915
|
|
|
|
|
|
|
|
916
|
7
|
|
|
|
|
11
|
my ($nth_var, @nth_type) = do { |
917
|
7
|
100
|
66
|
|
|
31
|
if ($nth and my $vn = $nth->[NODE_VALUE]) { |
918
|
1
|
|
|
|
|
5
|
my ($x, @t) = lexpand($nth->[NODE_PATH]); |
919
|
1
|
50
|
|
|
|
7
|
if ($vn =~ /^(\w+)$/) { |
920
|
1
|
|
|
|
|
5
|
($vn, @t); |
921
|
|
|
|
|
|
|
} else { |
922
|
0
|
|
|
|
|
0
|
die $self->generror("Invalid nth var: %s", $nth); |
923
|
|
|
|
|
|
|
} |
924
|
|
|
|
|
|
|
} |
925
|
|
|
|
|
|
|
}; |
926
|
7
|
100
|
|
|
|
21
|
if ($nth_var) { |
927
|
1
|
|
50
|
|
|
9
|
$local{$nth_var} = $self->mkvar_at(undef, $nth_type[0] || '' => $nth_var); |
928
|
|
|
|
|
|
|
|
929
|
1
|
|
|
|
|
4
|
$prologue .= sprintf q{ my $%s = 1;}, $nth_var; |
930
|
1
|
|
|
|
|
3
|
$continue .= sprintf q{ $%s++;}, $nth_var; |
931
|
|
|
|
|
|
|
} |
932
|
|
|
|
|
|
|
|
933
|
7
|
|
|
|
|
18
|
my $fmt = q|{%4$s; foreach %1$s (%2$s) %3$s continue {%5$s} %6$s}|; |
934
|
7
|
|
|
|
|
10
|
my $listexpr = do { |
935
|
7
|
100
|
|
|
|
17
|
unless (my $passThruVarName = passThruVar($list)) { |
|
|
50
|
|
|
|
|
|
936
|
1
|
|
|
|
|
5
|
$self->as_list(lexpand($list->[NODE_VALUE])); |
937
|
|
|
|
|
|
|
} elsif (my $found_var = $self->find_var($passThruVarName)) { |
938
|
6
|
100
|
|
|
|
34
|
unless ($found_var->is_type('list')) { |
939
|
1
|
|
|
|
|
7
|
die $self->generror(q{%s - %s should be list type.} |
940
|
|
|
|
|
|
|
, join(":", @$path), $passThruVarName); |
941
|
|
|
|
|
|
|
} |
942
|
5
|
|
|
|
|
15
|
'@'.$self->as_lvalue($found_var); |
943
|
|
|
|
|
|
|
} else { |
944
|
0
|
|
|
|
|
0
|
die $self->generror("Unknown list="); |
945
|
|
|
|
|
|
|
} |
946
|
|
|
|
|
|
|
}; |
947
|
|
|
|
|
|
|
|
948
|
6
|
|
|
|
|
13
|
local $self->{curtoks} = [@{argValue($body)}]; |
|
6
|
|
|
|
|
14
|
|
949
|
6
|
|
|
|
|
27
|
local $self->{scope} = $self->mkscope(\%local, $self->{scope}); |
950
|
6
|
|
|
|
|
18
|
my $statements = '{'.$self->as_print('}'); |
951
|
|
|
|
|
|
|
|
952
|
6
|
50
|
33
|
|
|
22
|
if ($opts and $opts->{fragment}) { |
953
|
0
|
|
|
|
|
0
|
($fmt, $loopvar, $listexpr, $statements |
954
|
|
|
|
|
|
|
, $prologue, $continue, $epilogue); |
955
|
|
|
|
|
|
|
} else { |
956
|
6
|
|
|
|
|
55
|
\ sprintf $fmt, $loopvar, $listexpr, $statements |
957
|
|
|
|
|
|
|
, $prologue, $continue, $epilogue; |
958
|
|
|
|
|
|
|
} |
959
|
|
|
|
|
|
|
} |
960
|
|
|
|
|
|
|
} |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
sub entx { |
963
|
10
|
|
|
10
|
0
|
21
|
my ($node) = @_; |
964
|
10
|
|
|
|
|
19
|
@{$node}[2..$#$node]; |
|
10
|
|
|
|
|
35
|
|
965
|
|
|
|
|
|
|
} |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
sub entmacro_if { |
968
|
3
|
|
|
3
|
0
|
7
|
(my MY $self, my $node) = @_; |
969
|
3
|
|
|
|
|
9
|
my ($cond, $then, $else) = $self->gen_entlist(undef, entx($node)); |
970
|
|
|
|
|
|
|
sprintf q|do {(%s) ? (%s) : (%s)}| |
971
|
3
|
50
|
50
|
|
|
11
|
, map {ref $_ ? $$_ : $_} $cond, $then, $else || q{''}; |
|
9
|
|
|
|
|
32
|
|
972
|
|
|
|
|
|
|
} |
973
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
sub entmacro_ifeq { |
975
|
0
|
|
|
0
|
0
|
0
|
(my MY $self, my $node) = @_; |
976
|
0
|
|
|
|
|
0
|
my ($val, $what, $then, $else) = $self->gen_entlist(undef, entx($node)); |
977
|
|
|
|
|
|
|
sprintf q|do {((%s // '') eq (%s // '')) ? (%s) : (%s)}| |
978
|
0
|
0
|
0
|
|
|
0
|
, map {ref $_ ? $$_ : $_} $val, $what, $then, $else || q{''}; |
|
0
|
|
|
|
|
0
|
|
979
|
|
|
|
|
|
|
} |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
sub entmacro_value_checked { |
982
|
0
|
|
|
0
|
0
|
0
|
(my MY $self, my $node) = @_; |
983
|
0
|
|
|
|
|
0
|
my (@list) = $self->gen_entlist(undef, entx($node)); |
984
|
0
|
0
|
|
|
|
0
|
unless (@list == 2) { |
985
|
0
|
|
|
|
|
0
|
die $self->generror("Invalid number of args: value_checked(VALUE, HASH)"); |
986
|
|
|
|
|
|
|
} |
987
|
|
|
|
|
|
|
sprintf q|YATT::Lite::Util::value_checked(%s)| |
988
|
0
|
0
|
|
|
|
0
|
, join ", ", map {ref $_ ? $$_ : $_} @list; |
|
0
|
|
|
|
|
0
|
|
989
|
|
|
|
|
|
|
} |
990
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
sub entmacro_value_selected { |
992
|
0
|
|
|
0
|
0
|
0
|
(my MY $self, my $node) = @_; |
993
|
0
|
|
|
|
|
0
|
my (@list) = $self->gen_entlist(undef, entx($node)); |
994
|
0
|
0
|
|
|
|
0
|
unless (@list == 2) { |
995
|
0
|
|
|
|
|
0
|
die $self->generror("Invalid number of args: value_selected(VALUE, HASH)"); |
996
|
|
|
|
|
|
|
} |
997
|
|
|
|
|
|
|
sprintf q|YATT::Lite::Util::value_selected(%s)| |
998
|
0
|
0
|
|
|
|
0
|
, join ", ", map {ref $_ ? $$_ : $_} @list; |
|
0
|
|
|
|
|
0
|
|
999
|
|
|
|
|
|
|
} |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
sub entmacro_lexpand { |
1002
|
5
|
|
|
5
|
0
|
9
|
(my MY $self, my $node) = @_; |
1003
|
5
|
|
|
|
|
16
|
q|@{|.$self->gen_entpath(undef, map {lxnest($_)} entx($node)).q|}|; |
|
5
|
|
|
|
|
15
|
|
1004
|
|
|
|
|
|
|
} |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
sub entmacro_render { |
1007
|
2
|
|
|
2
|
0
|
5
|
(my MY $self, my $node) = @_; |
1008
|
2
|
|
|
|
|
6
|
my ($wname, @expr) = $self->gen_entlist(undef, entx($node)); |
1009
|
2
|
|
|
|
|
14
|
\ sprintf q{YATT::Lite::Util::safe_render($this, $CON, %s, %s)} |
1010
|
|
|
|
|
|
|
, $wname, join(", ", @expr); |
1011
|
|
|
|
|
|
|
} |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
sub entmacro_dispatch_all { |
1014
|
0
|
|
|
0
|
0
|
|
(my MY $self, my $node) = @_; |
1015
|
0
|
|
|
|
|
|
my ($prefix, $nargs, @list) = $self->gen_entlist(undef, entx($node)); |
1016
|
0
|
|
|
|
|
|
\ sprintf q{YATT::Lite::Util::dispatch_all($this, $CON, %s, %s, %s)} |
1017
|
|
|
|
|
|
|
, $prefix, $nargs, join(", ", @list); |
1018
|
|
|
|
|
|
|
} |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
sub entmacro_dispatch_one { |
1021
|
0
|
|
|
0
|
0
|
|
(my MY $self, my $node) = @_; |
1022
|
0
|
|
|
|
|
|
my ($prefix, $nargs, @list) = $self->gen_entlist(undef, entx($node)); |
1023
|
0
|
|
|
|
|
|
\ sprintf q{YATT::Lite::Util::dispatch_one($this, $CON, %s, %s, %s)} |
1024
|
|
|
|
|
|
|
, $prefix, $nargs, join(", ", @list); |
1025
|
|
|
|
|
|
|
} |
1026
|
|
|
|
|
|
|
|
1027
|
9
|
|
|
9
|
|
81
|
use YATT::Lite::Breakpoint qw(break_load_cgen break_cgen); |
|
9
|
|
|
|
|
20
|
|
|
9
|
|
|
|
|
1088
|
|
1028
|
|
|
|
|
|
|
break_load_cgen(); |
1029
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
1; |