line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Dios; |
2
|
|
|
|
|
|
|
our $VERSION = '0.002012'; |
3
|
|
|
|
|
|
|
|
4
|
56
|
|
|
56
|
|
2507695
|
use 5.014; use warnings; |
|
56
|
|
|
56
|
|
547
|
|
|
56
|
|
|
|
|
277
|
|
|
56
|
|
|
|
|
81
|
|
|
56
|
|
|
|
|
1577
|
|
5
|
56
|
|
|
56
|
|
32359
|
use Dios::Types; |
|
56
|
|
|
|
|
365
|
|
|
56
|
|
|
|
|
399
|
|
6
|
56
|
|
|
56
|
|
3082
|
use Keyword::Declare; |
|
56
|
|
|
|
|
94
|
|
|
56
|
|
|
|
|
348
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
my $PARAMETER_SYNTAX = qr{ |
9
|
|
|
|
|
|
|
(?&WS)?+ |
10
|
|
|
|
|
|
|
(? |
11
|
|
|
|
|
|
|
(? |
12
|
|
|
|
|
|
|
(? (?&PerlNumber) ) |
13
|
|
|
|
|
|
|
| |
14
|
|
|
|
|
|
|
(? (?&PerlQuotelikeQ) ) |
15
|
|
|
|
|
|
|
| |
16
|
|
|
|
|
|
|
(? (?&PerlMatch) ) |
17
|
|
|
|
|
|
|
) |
18
|
|
|
|
|
|
|
| |
19
|
|
|
|
|
|
|
# TYPE... |
20
|
|
|
|
|
|
|
(? (?&TYPE_SPEC) )?+ |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# NAME... |
23
|
|
|
|
|
|
|
(?&WS)?+ |
24
|
|
|
|
|
|
|
(? |
25
|
|
|
|
|
|
|
: (? (?&IDENT) ) \( (?&WS)?+ |
26
|
|
|
|
|
|
|
(? (? [\$\@%]) (?&IDENT) ) (?&WS)?+ |
27
|
|
|
|
|
|
|
\) |
28
|
|
|
|
|
|
|
| |
29
|
|
|
|
|
|
|
: (? (? [\$\@%]) (? (?&IDENT) ) ) |
30
|
|
|
|
|
|
|
| |
31
|
|
|
|
|
|
|
\* (?) |
32
|
|
|
|
|
|
|
(?: |
33
|
|
|
|
|
|
|
(? (? [\@%]) (?&IDENT) ) |
34
|
|
|
|
|
|
|
| |
35
|
|
|
|
|
|
|
: (? (?&IDENT) ) \( (?&WS)? |
36
|
|
|
|
|
|
|
(? (? \@) (?&IDENT) ) (?&WS)? |
37
|
|
|
|
|
|
|
\) |
38
|
|
|
|
|
|
|
| |
39
|
|
|
|
|
|
|
: (? (? \@) (? (?&IDENT) ) ) |
40
|
|
|
|
|
|
|
| |
41
|
|
|
|
|
|
|
(? (? [\@%]) ) |
42
|
|
|
|
|
|
|
) |
43
|
|
|
|
|
|
|
| |
44
|
|
|
|
|
|
|
(? (? [\$\@%]) (?&IDENT) ) |
45
|
|
|
|
|
|
|
| |
46
|
|
|
|
|
|
|
(? (? [\$\@%]?+) ) |
47
|
|
|
|
|
|
|
) |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# OPTIONAL OR REQUIRED... |
50
|
|
|
|
|
|
|
(?: (? \? ) (? ) |
51
|
|
|
|
|
|
|
| (? \! ) |
52
|
|
|
|
|
|
|
)?+ |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# CONSTRAINT... |
55
|
|
|
|
|
|
|
(?&WS)?+ |
56
|
|
|
|
|
|
|
(?: where (?&WS)?+ (? (?&PerlBlock) ) )?+ |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
# READONLY OR ALIAS... |
59
|
|
|
|
|
|
|
(?: (?&WS)?+ is (?&WS)?+ (? ro | alias ) )?+ |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# DEFAULT VALUE... |
62
|
|
|
|
|
|
|
(?: (?&WS)?+ (? (?> // | \|\| )?+ = ) |
63
|
|
|
|
|
|
|
(?&WS)?+ (? (?&PerlConditionalExpression) ))?+ |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
(?&WS)?+ |
66
|
|
|
|
|
|
|
) |
67
|
|
|
|
|
|
|
(? , | : | (?= --> ) | \z ) |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
(?(DEFINE) |
70
|
|
|
|
|
|
|
(? (?&TYPE_NAME) (?: [&|] (?&TYPE_NAME) )*+ ) |
71
|
|
|
|
|
|
|
(? (?&QUAL_IDENT) (?&TYPE_PARAM)?+ ) |
72
|
|
|
|
|
|
|
(? \[ (?: [^][]*+ | (?&TYPE_PARAM) )*+ \] ) |
73
|
|
|
|
|
|
|
(? (?&IDENT) (?: :: (?&IDENT) )*+ ) |
74
|
|
|
|
|
|
|
(? [^\W\d] \w*+ ) |
75
|
|
|
|
|
|
|
(? (\s++ | \# [^\n]*+ \n )++ ) |
76
|
|
|
|
|
|
|
$PPR::GRAMMAR |
77
|
|
|
|
|
|
|
) |
78
|
|
|
|
|
|
|
}xms; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
my $EMPTY_PARAM_LIST = qr{ |
81
|
|
|
|
|
|
|
\A |
82
|
|
|
|
|
|
|
(?&OWS) |
83
|
|
|
|
|
|
|
(?: |
84
|
|
|
|
|
|
|
\( (?&OWS) (\*\@_)?+ (?&OWS) \) |
85
|
|
|
|
|
|
|
)?+ |
86
|
|
|
|
|
|
|
(?&OWS) |
87
|
|
|
|
|
|
|
\z |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
(?(DEFINE) |
90
|
|
|
|
|
|
|
(? \s*+ (?: \# .* \n \s*+ )*+ ) |
91
|
|
|
|
|
|
|
) |
92
|
|
|
|
|
|
|
}xm; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub _translate_parameters { |
95
|
230
|
|
|
230
|
|
2123
|
my $params = shift; |
96
|
230
|
|
|
|
|
496
|
my $kind = shift; |
97
|
230
|
|
|
|
|
450
|
my $sub_name = shift; |
98
|
230
|
|
|
|
|
458
|
my $sub_name_tidy = $sub_name; |
99
|
230
|
|
|
|
|
1058
|
$sub_name_tidy =~ s{\A \s*+ (?: \# .*+ \n \s*+ )*+ }{}x; |
100
|
|
|
|
|
|
|
|
101
|
230
|
|
|
|
|
522
|
my @param_names; |
102
|
230
|
100
|
|
|
|
1056
|
my $sub_desc = $sub_name ? "$kind $sub_name_tidy" : "anonymous $kind"; |
103
|
230
|
|
50
|
|
|
1294
|
my $invocant_name = $^H{'Dios invocant_name'} // '$self'; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# Empty and "standard" parameter lists are easy... |
106
|
230
|
100
|
66
|
|
|
3412
|
if (!defined $params || $params =~ $EMPTY_PARAM_LIST) { |
107
|
52
|
|
|
|
|
505
|
my $std_slurpy = defined $1; |
108
|
52
|
100
|
|
|
|
513
|
my $code |
|
|
100
|
|
|
|
|
|
109
|
|
|
|
|
|
|
= ($kind eq 'method' |
110
|
|
|
|
|
|
|
? _generate_invocant("method $sub_name_tidy", {var=>$invocant_name, sigil=>'$'}) |
111
|
|
|
|
|
|
|
: q{} |
112
|
|
|
|
|
|
|
) |
113
|
|
|
|
|
|
|
. ($std_slurpy ? q{} : qq{Dios::_error(ucfirst(q{$sub_desc takes no arguments})) if \@_;}); |
114
|
|
|
|
|
|
|
|
115
|
52
|
100
|
|
|
|
303
|
my $spec = ( $kind eq 'method' ? q{ {type=>'Any', where=[]}, } : q{} ) |
|
|
100
|
|
|
|
|
|
116
|
|
|
|
|
|
|
. ( $std_slurpy ? q{ {optional => 1, type=>'Slurpy', where=>[]} } : q{} ); |
117
|
|
|
|
|
|
|
|
118
|
52
|
|
|
|
|
409
|
return { code => $code, spec => $spec, names=>\@param_names }; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
178
|
|
|
|
|
865
|
$params =~ s{\A \s*+ \(}{}x; |
122
|
178
|
|
|
|
|
850
|
$params =~ s{\) \s*+ \z}{}x; |
123
|
|
|
|
|
|
|
|
124
|
178
|
|
|
|
|
451
|
my $return_type = undef; |
125
|
178
|
|
|
|
|
326
|
my $return_constraint = undef; |
126
|
178
|
100
|
|
|
|
602
|
my $invocant = $kind eq 'method' ? $invocant_name : undef; |
127
|
178
|
|
|
|
|
440
|
my $first_param = 1; |
128
|
178
|
|
|
|
|
321
|
my @params; |
129
|
|
|
|
|
|
|
|
130
|
178
|
|
66
|
|
|
3973600
|
while (length($params) && $params =~ s{\A \s*+ $PARAMETER_SYNTAX }{}x) { |
131
|
286
|
|
|
|
|
80208
|
my %param = %+; |
132
|
286
|
100
|
|
|
|
4792
|
last if $param{raw_param} !~ /\S/; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# Special case of literal numeric constant as parameter (e.g. multi func fib(0) { 0 } )... |
135
|
253
|
100
|
|
|
|
2642
|
if (defined $param{is_num_constant}) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
136
|
3
|
|
|
|
|
9
|
$param{type} = 'Num'; |
137
|
3
|
|
|
|
|
14
|
$param{constraint} = "{ \$_ == $param{is_num_constant} }"; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# Special case of literal string constant as parameter (e.g. multi func handle_event('add') {...} )... |
141
|
|
|
|
|
|
|
elsif (defined $param{is_str_constant}) { |
142
|
7
|
|
|
|
|
22
|
$param{type} = 'Str'; |
143
|
7
|
|
|
|
|
29
|
$param{constraint} = "{ \$_ eq $param{is_str_constant} }"; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
# Special case of literal regex match as parameter (e.g. multi func # handle_event(/a|b/) {...} )... |
147
|
|
|
|
|
|
|
elsif (defined $param{is_regex_constant}) { |
148
|
2
|
|
|
|
|
8
|
$param{type} = 'Str'; |
149
|
2
|
|
|
|
|
9
|
$param{constraint} = "{ \$_ =~ $param{is_regex_constant} }"; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
253
|
|
|
|
|
2477071
|
push @params, \%param; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# Make an implicit invocant explicit... |
157
|
178
|
100
|
100
|
|
|
1196
|
if (!@params && $kind eq 'method') { |
158
|
1
|
|
|
|
|
22852
|
"$invocant:" =~ m{\A \s*+ $PARAMETER_SYNTAX }x; |
159
|
1
|
|
|
|
|
249
|
push @params, {%+}; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# Extract trailing return type specification... |
163
|
178
|
100
|
|
|
|
1038
|
if ($params =~ s{ (?&WS) --> (?&WS) (.*+) (?(DEFINE) (? \s*+ (\# [^\n]*+ \n \s*+ )*+)) }{}xms ) { |
164
|
33
|
|
|
|
|
235
|
($return_type, $return_constraint) = split /\bwhere\b/, $1, 2; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# Anything else in the parameter list is a mistake... |
168
|
178
|
50
|
|
|
|
667
|
_error( qq{Invalid parameter specification: $params\n in $kind declaration} ) |
169
|
|
|
|
|
|
|
if $params =~ /\S/; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# Convert the parameters into checking code... |
172
|
178
|
|
|
|
|
413
|
my $code = q{}; |
173
|
178
|
|
|
|
|
394
|
my $spec = q{}; |
174
|
178
|
|
|
|
|
389
|
my $nameless_pos = 0; |
175
|
178
|
|
|
|
|
426
|
my (%param_named, @positional, @named, $slurpy); |
176
|
|
|
|
|
|
|
|
177
|
178
|
|
|
|
|
576
|
for my $param (@params) { |
178
|
254
|
|
|
|
|
392
|
$nameless_pos++; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# Constraints imply an Any type... |
181
|
254
|
100
|
66
|
|
|
1012
|
if (defined $param->{constraint} && (!defined $param->{type} || $param->{type} !~ /\S/)) { |
|
|
|
100
|
|
|
|
|
182
|
1
|
|
|
|
|
3
|
$param->{type} = 'Any'; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Rectify nameless params... |
186
|
254
|
100
|
|
|
|
677
|
if (exists $param->{nameless}) { |
187
|
19
|
|
100
|
|
|
80
|
$param->{sigil} ||= '$'; |
188
|
19
|
100
|
|
|
|
107
|
my $nth = $nameless_pos |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
189
|
|
|
|
|
|
|
. ( $nameless_pos =~ /(?
|
190
|
|
|
|
|
|
|
: $nameless_pos =~ /(?
|
191
|
|
|
|
|
|
|
: $nameless_pos =~ /(?
|
192
|
|
|
|
|
|
|
: 'th' |
193
|
|
|
|
|
|
|
); |
194
|
19
|
|
|
|
|
85
|
$param->{var} = $param->{sigil} . '__nameless_'.$nth.'_parameter__'; |
195
|
19
|
|
|
|
|
55
|
$param->{namedvar} = $param->{sigil} . ' (unnamed $nth parameter)'; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# "There ken be onla one!" (...parameter of any given name)... |
199
|
|
|
|
|
|
|
_error( qq{Can't declare two parameters named $param->{var}\n in specification of $sub_desc}) |
200
|
254
|
50
|
|
|
|
864
|
if exists $param_named{ $param->{var} }; |
201
|
254
|
|
|
|
|
812
|
$param_named{ $param->{var} }++; |
202
|
254
|
100
|
|
|
|
759
|
push @param_names, $param->{name} if $param->{name}; |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# Parameters are lexical, so can't be named @_ or $_ or %_... |
205
|
|
|
|
|
|
|
_error( |
206
|
|
|
|
|
|
|
qq{Can't declare a }, |
207
|
|
|
|
|
|
|
(exists $param->{name} ? 'named' : exists $param->{slurpy} ? 'slurpy' : 'positional'), |
208
|
|
|
|
|
|
|
qq{ parameter named $param->{var}\nin specification of $sub_desc}, |
209
|
254
|
0
|
66
|
|
|
1061
|
) if substr($param->{var},1) eq '_' && $param->{namedvar} ne '*@_'; |
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# Handle implicit invocant specially... |
212
|
254
|
100
|
100
|
|
|
1526
|
if ($first_param && $kind eq 'method' && $param->{terminator} ne ':') { |
|
|
|
100
|
|
|
|
|
213
|
91
|
|
|
|
|
950
|
$code .= _generate_invocant( "$sub_desc", {var=>$invocant_name, sigil=>'$'} ); |
214
|
91
|
|
|
|
|
310
|
$first_param = 0; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
# Handle explicit invocant... |
218
|
254
|
100
|
100
|
|
|
1580
|
if ($first_param && $param->{terminator} && $param->{terminator} eq ':') { |
|
|
100
|
100
|
|
|
|
|
219
|
18
|
50
|
|
|
|
54
|
_error( qq{Can't specify invocant ($param->{raw_param}:) for $sub_desc} ) if $kind ne 'method'; |
220
|
18
|
|
|
|
|
106
|
$code .= _generate_invocant( "$sub_desc", $param ); |
221
|
18
|
|
50
|
|
|
109
|
my $type = $param->{type} // 'Any'; |
222
|
18
|
50
|
|
|
|
66
|
my $constraint = $param->{constraint} ? "where => sub $param->{constraint}" : q{}; |
223
|
18
|
|
|
|
|
60
|
$spec .= qq{{type => '$type', $constraint },}; |
224
|
18
|
|
|
|
|
47
|
$first_param = 0; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# Save a scalar (named or positional) paramater... |
228
|
|
|
|
|
|
|
elsif (!exists $param->{slurpy}) { |
229
|
216
|
100
|
|
|
|
519
|
if (exists $param->{name}) { push @named, $param } |
|
60
|
|
|
|
|
156
|
|
230
|
156
|
|
|
|
|
354
|
else { push @positional, $param } |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# Save the final slurpy array or hash... |
234
|
|
|
|
|
|
|
else { |
235
|
20
|
50
|
|
|
|
77
|
_error( qq{Can't specify more than one slurpy parameter }, |
236
|
|
|
|
|
|
|
qq{($slurpy->{namedvar}, $param->{namedvar})\n}, |
237
|
|
|
|
|
|
|
qq{ in specification of $sub_desc} |
238
|
|
|
|
|
|
|
) if defined $slurpy; |
239
|
|
|
|
|
|
|
|
240
|
20
|
100
|
|
|
|
80
|
if (exists $param->{name}) { |
241
|
|
|
|
|
|
|
_error( qq{Can't specify non-array named slurpy parameter ($param->{namedvar})\n}, |
242
|
|
|
|
|
|
|
qq{ in specification of $sub_desc} |
243
|
2
|
50
|
33
|
|
|
10
|
) if exists $param->{name} && $param->{sigil} ne '@'; |
244
|
|
|
|
|
|
|
|
245
|
2
|
|
|
|
|
5
|
push @named, $param; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
else { |
248
|
18
|
|
|
|
|
45
|
$slurpy = $param; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
178
|
100
|
|
|
|
551
|
if (@positional) { |
254
|
104
|
|
|
|
|
548
|
$code .= _generate_positionals( "$sub_desc", @positional ); |
255
|
104
|
|
|
|
|
298
|
for my $param (@positional) { |
256
|
156
|
|
100
|
|
|
532
|
my $type = $param->{type} // 'Any'; |
257
|
|
|
|
|
|
|
|
258
|
156
|
100
|
|
|
|
598
|
if ($param->{sigil} eq '@') { $type = "Array[$type]"; } |
|
6
|
100
|
|
|
|
19
|
|
259
|
2
|
|
|
|
|
5
|
elsif ($param->{sigil} eq '%') { $type = "Hash[$type]"; } |
260
|
|
|
|
|
|
|
|
261
|
156
|
100
|
|
|
|
414
|
my $constraint = $param->{constraint} ? "where => sub $param->{constraint}" : q{}; |
262
|
|
|
|
|
|
|
|
263
|
156
|
100
|
|
|
|
372
|
my $is_optional = exists $param->{default_type} ? 1 : 0; |
264
|
|
|
|
|
|
|
|
265
|
156
|
|
|
|
|
630
|
$spec .= qq{{optional => $is_optional, type => '$type', $constraint},}; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
} |
268
|
178
|
100
|
|
|
|
552
|
if (@named) { |
269
|
42
|
|
|
|
|
224
|
$code .= _generate_nameds( "$sub_desc", @named ); |
270
|
42
|
|
|
|
|
110
|
for my $param (@named) { |
271
|
62
|
|
100
|
|
|
214
|
my $type = $param->{type} // 'Any'; |
272
|
|
|
|
|
|
|
|
273
|
62
|
100
|
|
|
|
240
|
if ($param->{sigil} eq '@') { $type = "Array[$type]"; } |
|
5
|
100
|
|
|
|
13
|
|
274
|
1
|
|
|
|
|
3
|
elsif ($param->{sigil} eq '%') { $type = "Hash[$type]"; } |
275
|
|
|
|
|
|
|
|
276
|
62
|
100
|
|
|
|
151
|
my $constraint = $param->{constraint} ? "where => sub $param->{constraint}" : q{}; |
277
|
|
|
|
|
|
|
|
278
|
62
|
100
|
|
|
|
146
|
my $is_optional = exists $param->{default_type} ? 1 : 0; |
279
|
|
|
|
|
|
|
|
280
|
62
|
|
|
|
|
293
|
$spec .= qq{{named => '$param->{name}', optional => $is_optional, type => '$type', $constraint},}; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
178
|
100
|
|
|
|
511
|
if (defined $slurpy) { |
285
|
18
|
100
|
|
|
|
98
|
if ($slurpy->{var} ne '@_') { |
286
|
17
|
50
|
|
|
|
128
|
my $constraint = $slurpy->{constraint} ? "where => sub $slurpy->{constraint}" : q{}; |
287
|
17
|
|
|
|
|
92
|
$code .= _generate_slurpies( "$sub_desc", $slurpy ); |
288
|
17
|
|
|
|
|
61
|
$spec .= qq{ {optional => 1, type=>'Slurpy', $constraint} }; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
else { |
292
|
160
|
|
|
|
|
819
|
$code .= qq[Dios::_error q{Unexpected extra argument}.(\@_==1?q{}:q{s}).' ('.join(', ', map { Dios::_perl \$_ } \@_).q{) in call to $sub_desc} if \@_;]; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
178
|
100
|
|
|
|
554
|
$return_type = defined $return_type ? qq{q{$return_type}} : ""; |
296
|
178
|
50
|
|
|
|
463
|
if (defined $return_constraint) { |
297
|
0
|
|
|
|
|
0
|
$return_type .= qq{, sub $return_constraint }; |
298
|
|
|
|
|
|
|
} |
299
|
178
|
|
|
|
|
2382
|
return { code => $code, return_type => $return_type, spec => $spec, names => \@param_names }; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub _verify_required_named { |
303
|
42
|
|
|
42
|
|
126
|
my ($context, @params) = @_; |
304
|
42
|
|
|
|
|
99
|
my $code = q{}; |
305
|
42
|
|
|
|
|
107
|
for my $param (@params) { |
306
|
62
|
100
|
|
|
|
196
|
next if !$param->{required}; |
307
|
1
|
|
|
|
|
3
|
my $vardesc = quotemeta $param->{namedvar}; |
308
|
1
|
|
50
|
|
|
5
|
my $argdesc = qq{'$param->{name}' => <} . lc($param->{type}//'value'). q{>}; |
309
|
1
|
|
|
|
|
6
|
$code .= qq[Dios::_error(qq{No argument ($argdesc) found for required named parameter $vardesc\\n] |
310
|
|
|
|
|
|
|
. qq[in call to $context}) if !\$seen{$param->{name}}; ]; |
311
|
|
|
|
|
|
|
} |
312
|
42
|
|
|
|
|
98
|
return $code; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
sub _generate_invocant { |
316
|
157
|
|
|
157
|
|
513
|
my ($context, $param) = @_; |
317
|
157
|
|
|
|
|
282
|
my $code; |
318
|
157
|
|
|
|
|
535
|
my $vardesc = qq{invocant $param->{var}}; |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# Create and unpack corresponding argument... |
321
|
157
|
|
|
|
|
580
|
$code .= qq{my $param->{var}; }; |
322
|
157
|
|
|
|
|
384
|
$code .= _unpack_code( @{$param}{'sigil','var','name','default','special'}, $vardesc, $context ); |
|
157
|
|
|
|
|
1209
|
|
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# Install a type check, if necessary... |
325
|
157
|
50
|
|
|
|
586
|
if (exists $param->{type}) { |
326
|
0
|
|
|
|
|
0
|
$code .= _typecheck_code(@{$param}{'sigil','var','type','constraint'}, $vardesc, $context); |
|
0
|
|
|
|
|
0
|
|
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
157
|
|
|
|
|
577
|
return $code; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
sub _generate_positionals { |
333
|
104
|
|
|
104
|
|
375
|
my ($context, @positionals) = @_; |
334
|
104
|
|
|
|
|
180
|
my $code; |
335
|
|
|
|
|
|
|
|
336
|
104
|
|
|
|
|
254
|
for my $param (@positionals) { |
337
|
|
|
|
|
|
|
# Create and unpack corresponding argument... |
338
|
156
|
|
|
|
|
328
|
my $var = $param->{var}; |
339
|
156
|
100
|
|
|
|
658
|
my $vardesc = $var =~ /^(.)__nameless_(\d++[^\W_]++)_parameter__$/ |
340
|
|
|
|
|
|
|
? "unnamed $2 positional parameter" |
341
|
|
|
|
|
|
|
: "positional parameter $var"; |
342
|
156
|
|
|
|
|
429
|
$code .= qq{my $var; }; |
343
|
|
|
|
|
|
|
$code .= _unpack_code( |
344
|
156
|
|
|
|
|
317
|
@{$param}{'sigil','var','name','default','special'}, |
|
156
|
|
|
|
|
722
|
|
345
|
|
|
|
|
|
|
$vardesc, |
346
|
|
|
|
|
|
|
$context |
347
|
|
|
|
|
|
|
); |
348
|
156
|
100
|
66
|
|
|
753
|
if (exists $param->{name} && exists $param->{default_type}) { |
349
|
36
|
100
|
100
|
|
|
237
|
if ($param->{default_type} eq '//=' && $param->{sigil} eq '$') { |
|
|
100
|
|
|
|
|
|
350
|
9
|
|
|
|
|
16
|
my $assign_code = _assign_value_code( @{$param}{'sigil','var','special','default'}, q{}); |
|
9
|
|
|
|
|
24
|
|
351
|
9
|
|
|
|
|
29
|
$code .= qq{ do {$assign_code} if !defined $var; }; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
elsif ($param->{default_type} eq '||=') { |
354
|
10
|
|
|
|
|
21
|
my $assign_code = _assign_value_code( @{$param}{'sigil','var','special','default'}, q{}); |
|
10
|
|
|
|
|
25
|
|
355
|
10
|
|
|
|
|
30
|
$code .= qq{ do {$assign_code} if !$var; }; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# Install a type check, if necessary... |
360
|
156
|
100
|
|
|
|
476
|
next if !exists $param->{type}; |
361
|
55
|
|
|
|
|
118
|
$code .= _typecheck_code(@{$param}{'sigil','var','type','constraint'}, $vardesc, $context); |
|
55
|
|
|
|
|
205
|
|
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
104
|
|
|
|
|
541
|
return $code; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
sub _generate_nameds { |
368
|
42
|
|
|
42
|
|
377
|
my ($context, @nameds) = @_; |
369
|
42
|
|
|
|
|
224
|
my $code; |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
# Declare all named args... |
372
|
42
|
|
|
|
|
149
|
$code .= 'my (' . join(',', map { $_->{var} } @nameds) . '); '; |
|
62
|
|
|
|
|
327
|
|
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# Walk the arg list, unpacking them... |
375
|
42
|
|
|
|
|
118
|
$code .= qq[{ my %seen; while (\@_) { my \$next_key = shift;]; |
376
|
|
|
|
|
|
|
|
377
|
42
|
|
|
|
|
89
|
my $defaults = q{}; |
378
|
42
|
|
|
|
|
114
|
for my $param (@nameds) { |
379
|
62
|
|
|
|
|
192
|
$code .= qq[ if (\$next_key eq q{$param->{name}}) {]; |
380
|
|
|
|
|
|
|
my $unpack_code = |
381
|
|
|
|
|
|
|
exists $param->{slurpy} ? _unpack_named_slurpy_code( |
382
|
2
|
|
|
|
|
13
|
@{$param}{qw< var sigil name special >}, |
383
|
|
|
|
|
|
|
"slurpy named parameter $param->{namedvar}", $context |
384
|
|
|
|
|
|
|
) |
385
|
|
|
|
|
|
|
: _unpack_code( |
386
|
60
|
|
|
|
|
362
|
@{$param}{'sigil','var','name'}, undef, $param->{special}, |
387
|
62
|
100
|
|
|
|
193
|
"named parameter $param->{namedvar}", $context |
388
|
|
|
|
|
|
|
); |
389
|
62
|
|
|
|
|
200
|
$code .= qq[$unpack_code next}]; |
390
|
|
|
|
|
|
|
|
391
|
62
|
100
|
66
|
|
|
394
|
if (exists $param->{name} && exists $param->{default}) { |
392
|
2
|
|
|
|
|
7
|
my $assign_code = _assign_value_code( @{$param}{'sigil','var','special','default'}, q{}); |
|
2
|
|
|
|
|
9
|
|
393
|
|
|
|
|
|
|
$defaults .= qq{ do {$assign_code} if } |
394
|
|
|
|
|
|
|
. ( $param->{default_type} eq '//=' ? qq{!defined $param->{var}; } |
395
|
2
|
50
|
|
|
|
19
|
: $param->{default_type} eq '||=' ? qq{!$param->{var}; } |
|
|
100
|
|
|
|
|
|
396
|
|
|
|
|
|
|
: qq{!\$seen{$param->{'name'}}; } |
397
|
|
|
|
|
|
|
); |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
42
|
|
|
|
|
174
|
my $requireds = _verify_required_named($context, @nameds); |
402
|
|
|
|
|
|
|
|
403
|
42
|
|
|
|
|
168
|
$code .= qq[unshift \@_, \$next_key; last} $defaults $requireds}]; |
404
|
|
|
|
|
|
|
|
405
|
42
|
|
|
|
|
99
|
for my $param (@nameds) { |
406
|
62
|
100
|
|
|
|
169
|
next if !exists $param->{type}; |
407
|
|
|
|
|
|
|
|
408
|
40
|
100
|
|
|
|
113
|
my $slurpy = exists $param->{slurpy} ? q{slurpy } : q{}; |
409
|
|
|
|
|
|
|
$code .= _typecheck_code( |
410
|
40
|
|
|
|
|
71
|
@{$param}{'sigil','var','type','constraint'}, "${slurpy}named parameter $param->{namedvar}", $context |
|
40
|
|
|
|
|
207
|
|
411
|
|
|
|
|
|
|
); |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
|
414
|
42
|
|
|
|
|
206
|
return $code; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
my $REFALIASING = q{use experimental 'refaliasing'}; |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub _generate_slurpies { |
420
|
17
|
|
|
17
|
|
48
|
my ($context, $param) = @_; |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
# No slurpy by default... |
423
|
17
|
50
|
|
|
|
77
|
return q{} if !defined $param; |
424
|
17
|
|
|
|
|
44
|
my $special = $param->{special}; |
425
|
17
|
|
|
|
|
44
|
my $code = q{}; |
426
|
|
|
|
|
|
|
|
427
|
17
|
100
|
|
|
|
84
|
my $vardesc = $param->{var} =~ /^(.)__nameless_.*_parameter__$/ |
428
|
|
|
|
|
|
|
? "nameless slurpy parameter (*$1)" |
429
|
|
|
|
|
|
|
: "slurpy parameter *$param->{var}"; |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
# Check named slurpies... |
432
|
17
|
100
|
|
|
|
67
|
if ($param->{sigil} eq '%') { |
433
|
2
|
|
|
|
|
10
|
$code .= qq{Dios::_error('Final key ('.Dios::dump(\$_[-1]).qq{) for $vardesc is missing its value\\nin call to $context}) if \@_ % 2;} |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# Create and unpack corresponding argument... |
437
|
17
|
50
|
33
|
|
|
92
|
$code .= !$special ? qq{ my $param->{var} = } |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
438
|
|
|
|
|
|
|
: $special eq 'ro' ? qq{ Const::Fast::const my $param->{var} => } |
439
|
|
|
|
|
|
|
: $special eq 'alias' && $] < 5.022 ? qq{ Data::Alias::alias my $param->{var} = } |
440
|
|
|
|
|
|
|
: $special eq 'alias' ? qq{ $REFALIASING; \\my $param->{var} =\\ } |
441
|
|
|
|
|
|
|
: die "Internal error: unknown special trait: is $special"; |
442
|
|
|
|
|
|
|
|
443
|
17
|
100
|
|
|
|
59
|
$code .= exists $param->{default} ? qq{ (\@_ ? \@_ : $param->{default}); } |
444
|
|
|
|
|
|
|
: qq{ \@_; }; |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
# Install a type check, if necessary... |
447
|
17
|
100
|
|
|
|
56
|
if (exists $param->{type}) { |
448
|
1
|
|
|
|
|
2
|
$code .= _typecheck_code(@{$param}{'sigil','var','type','constraint'}, $vardesc, $context, 'slurpy'); |
|
1
|
|
|
|
|
4
|
|
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# Install existence check, if necessary... |
452
|
17
|
100
|
|
|
|
51
|
if (exists $param->{required}) { |
453
|
1
|
|
|
|
|
3
|
my $vardesc = quotemeta $vardesc; |
454
|
1
|
|
|
|
|
3
|
$code .= qq[Dios::_error qq{Missing argument for required $vardesc\\nin $context} if !\@_;]; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
17
|
|
|
|
|
48
|
return $code; |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub _assign_value_code { |
461
|
394
|
|
|
394
|
|
920
|
my ($sigil, $var, $special, $value_source, $check_type) = @_; |
462
|
394
|
|
100
|
|
|
1540
|
$special //= q{}; |
463
|
|
|
|
|
|
|
|
464
|
394
|
100
|
|
|
|
1000
|
if ($sigil eq '$') { |
465
|
381
|
100
|
66
|
|
|
3104
|
return $special eq 'ro' ? qq[ Const::Fast::const($var => $value_source); ] |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
466
|
|
|
|
|
|
|
: $special eq 'alias' && $] < 5.022 ? qq[ Data::Alias::alias $var = $value_source ; ] |
467
|
|
|
|
|
|
|
: $special eq 'alias' ? qq[ $REFALIASING; \\$var = \\($value_source); ] |
468
|
|
|
|
|
|
|
: qq[ $var = $value_source ; ] |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# Arrays and hashes, need more type-checking... |
472
|
13
|
100
|
|
|
|
39
|
if ($sigil eq '@') { |
473
|
10
|
50
|
33
|
|
|
122
|
return qq[ { my \$next_value = $value_source; ] |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
474
|
|
|
|
|
|
|
. $check_type |
475
|
|
|
|
|
|
|
. ( $special eq 'ro' ? qq[ Const::Fast::const($var => \@{\$next_value}); ] |
476
|
|
|
|
|
|
|
: $special eq 'alias' && $] < 5.022 ? qq[ Data::Alias::alias $var = \@{\$next_value} ; ] |
477
|
|
|
|
|
|
|
: $special eq 'alias' ? qq[ $REFALIASING; \\$var = \@{\$next_value} ; ] |
478
|
|
|
|
|
|
|
: qq[ $var = \@{\$next_value} ; ] |
479
|
|
|
|
|
|
|
) |
480
|
|
|
|
|
|
|
. qq[} ]; |
481
|
|
|
|
|
|
|
} |
482
|
3
|
50
|
|
|
|
19
|
if ($sigil eq '%') { |
483
|
3
|
50
|
33
|
|
|
45
|
return qq[ { my \$next_value = $value_source; ] |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
484
|
|
|
|
|
|
|
. $check_type |
485
|
|
|
|
|
|
|
. ( $special eq 'ro' ? qq[ Const::Fast::const($var => \%{\$next_value}); ] |
486
|
|
|
|
|
|
|
: $special eq 'alias' && $] < 5.022 ? qq[ Data::Alias::alias $var = \%{\$next_value} ; ] |
487
|
|
|
|
|
|
|
: $special eq 'alias' ? qq[ $REFALIASING; \\$var = \%{\$next_value} ; ] |
488
|
|
|
|
|
|
|
: qq[ $var = \%{\$next_value} ; ] |
489
|
|
|
|
|
|
|
) |
490
|
|
|
|
|
|
|
. qq[} ]; |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
sub _unpack_code { |
495
|
373
|
|
|
373
|
|
1171
|
my ($sigil, $var, $name, $default, $special, $vardesc, $context) = @_; |
496
|
373
|
|
|
|
|
819
|
state $type_of = { '$' => q{}, '@' => 'ARRAY', '%' => 'HASH' }; |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
# Set up for readonly or aliasing, if specified... |
499
|
373
|
100
|
|
|
|
847
|
if ($special) { |
500
|
4
|
100
|
33
|
|
|
26
|
if ($special eq 'ro') { |
|
|
50
|
|
|
|
|
|
501
|
|
|
|
|
|
|
_error(q{'is ro' requires the Const::Fast module (which could not be loaded)}) |
502
|
2
|
50
|
|
|
|
6
|
if !eval { require Const::Fast; 1 }; |
|
2
|
|
|
|
|
551
|
|
|
2
|
|
|
|
|
775
|
|
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
elsif ($special eq 'alias' && $] < 5.022) { |
505
|
|
|
|
|
|
|
_error(q{'is alias' requires the Data::Alias module (which could not be loaded)}) |
506
|
0
|
0
|
|
|
|
0
|
if !eval { require Data::Alias; 1 }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
# Set up for default handling, if specified... |
511
|
373
|
|
|
|
|
1021
|
my $value_source = qq{ ( !\@_ ? Dios::_error(q{No argument found for $vardesc in call to $context}) : shift) }; |
512
|
373
|
|
|
|
|
1885
|
my $type_check = qq[ Dios::_error q{Argument for $vardesc is not \L$type_of->{$sigil}\E ref in call to $context} ] |
513
|
|
|
|
|
|
|
. qq[ if ref(\$next_value) ne '$type_of->{$sigil}';]; |
514
|
|
|
|
|
|
|
|
515
|
373
|
100
|
|
|
|
867
|
if (defined($default)) { |
516
|
36
|
50
|
66
|
|
|
141
|
$default ||= $sigil eq '$' ? 'undef' |
|
|
100
|
|
|
|
|
|
517
|
|
|
|
|
|
|
: $sigil eq '@' ? '[]' |
518
|
|
|
|
|
|
|
: '{}'; |
519
|
36
|
100
|
|
|
|
120
|
my $and_type_test = $sigil eq '$' ? '' : "&& ref(\$_[0]) eq '$type_of->{$sigil}'"; |
520
|
36
|
|
|
|
|
102
|
$value_source = qq{ \@_ $and_type_test ? shift() : $default }; |
521
|
36
|
|
|
|
|
81
|
$type_check = q{}; |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
# Named params have to be tracked, if they have defaults... |
525
|
373
|
100
|
|
|
|
990
|
my $note_seen |
526
|
|
|
|
|
|
|
= $name ? qq{ Dios::_error(q{Unexpected second value (}.Dios::_perl($var).q{) for named '$name' parameter in call to $context}) if \$seen{$name}; \$seen{$name} = 1; } |
527
|
|
|
|
|
|
|
: q{}; |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
# Return the code... |
530
|
373
|
|
|
|
|
1023
|
return _assign_value_code($sigil, $var, $special, $value_source, $type_check) |
531
|
|
|
|
|
|
|
. $note_seen; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
sub _unpack_named_slurpy_code { |
535
|
2
|
|
|
2
|
|
5
|
my ($var, $sigil, $name, $special, $vardesc, $context) = @_; |
536
|
2
|
|
50
|
|
|
9
|
$special //= q{}; |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# Must be able to use the module, if it's required |
539
|
2
|
50
|
33
|
|
|
6
|
if ($special eq 'alias' && $] < 5.022) { |
540
|
|
|
|
|
|
|
_error(q{'is alias' requires the Data::Alias module (which could not be loaded)}) |
541
|
0
|
0
|
|
|
|
0
|
if !eval { require Data::Alias; 1 }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
# Work out how at unpack the arg |
545
|
2
|
50
|
33
|
|
|
10
|
my $unpack_code |
|
|
50
|
|
|
|
|
|
546
|
|
|
|
|
|
|
= $special eq 'alias' && $] >= 5.022 ? qq{use experimental 'refaliasing';\\\$${name}[\@$name]=\\shift;} |
547
|
|
|
|
|
|
|
: $special eq 'alias' ? qq{ Data::Alias::alias( \$${name}[\@$name] = shift); } |
548
|
|
|
|
|
|
|
: qq{ push $var, shift; }; |
549
|
|
|
|
|
|
|
|
550
|
2
|
|
|
|
|
9
|
return qq{ Dios::_error q{No argument found for $vardesc in call to $context} if !\@_; } |
551
|
|
|
|
|
|
|
. $unpack_code; |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
sub _typecheck_code { |
555
|
96
|
|
|
96
|
|
290
|
my ($sigil, $var, $type, $constraint, $vardesc, $context, $is_slurpy) = @_; |
556
|
96
|
100
|
|
|
|
247
|
$constraint = $constraint ? "sub $constraint" : q{}; |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
# Provide a human-readble description for any error message... |
559
|
96
|
|
|
|
|
197
|
$vardesc = qq{q{Value (%s) for $vardesc}}; |
560
|
|
|
|
|
|
|
|
561
|
96
|
100
|
|
|
|
218
|
if ($sigil eq '$') { |
562
|
94
|
|
|
|
|
513
|
return qq[{package Dios::Types; validate(q{$type}, $var,$vardesc,$constraint)}]; |
563
|
|
|
|
|
|
|
} |
564
|
2
|
50
|
|
|
|
3
|
if ($sigil eq '@') { |
565
|
2
|
100
|
|
|
|
7
|
return qq[{package Dios::Types; validate(q{List[$type]}, \\$var,$vardesc,$constraint)}] if $is_slurpy; |
566
|
1
|
|
|
|
|
5
|
return qq[{package Dios::Types; validate(q{Array[$type]},\\$var,$vardesc,$constraint)}]; |
567
|
|
|
|
|
|
|
} |
568
|
0
|
0
|
|
|
|
0
|
if ($sigil eq '%') { |
569
|
0
|
|
|
|
|
0
|
return qq[{package Dios::Types; validate(q{Hash[$type]}, \\$var,$vardesc,$constraint)}]; |
570
|
|
|
|
|
|
|
} |
571
|
0
|
|
|
|
|
0
|
die 'Internal error: unable to generate type checking code'; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
sub _perl { |
575
|
56
|
|
|
56
|
|
184784
|
use Data::Dump 'dump'; |
|
56
|
|
|
|
|
138
|
|
|
56
|
|
|
|
|
5069
|
|
576
|
7
|
|
|
7
|
|
7733
|
return dump(@_); |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
our @CARP_NOT = 'Keyword::Declare'; |
580
|
|
|
|
|
|
|
sub _error { |
581
|
56
|
|
|
56
|
|
365
|
use Carp; |
|
56
|
|
|
|
|
90
|
|
|
56
|
|
|
|
|
4240
|
|
582
|
20
|
|
|
20
|
|
17574
|
croak @_; |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
|
585
|
56
|
|
|
56
|
|
340
|
use re 'eval'; |
|
56
|
|
|
|
|
105
|
|
|
56
|
|
|
|
|
120531
|
|
586
|
|
|
|
|
|
|
my $FIELD_DEFN = qr{ |
587
|
|
|
|
|
|
|
(? |
588
|
|
|
|
|
|
|
(?&TYPE_SPEC) |
589
|
|
|
|
|
|
|
)? \s*+ |
590
|
|
|
|
|
|
|
(? |
591
|
|
|
|
|
|
|
[\$\@%] |
592
|
|
|
|
|
|
|
) |
593
|
|
|
|
|
|
|
(? |
594
|
|
|
|
|
|
|
[.!]? |
595
|
|
|
|
|
|
|
) |
596
|
|
|
|
|
|
|
(? |
597
|
|
|
|
|
|
|
[^\W\d] \w* # Simple identifier |
598
|
|
|
|
|
|
|
) |
599
|
|
|
|
|
|
|
(? |
600
|
|
|
|
|
|
|
\s+ is \s+ req(?:uired)? |
601
|
|
|
|
|
|
|
)? |
602
|
|
|
|
|
|
|
(?: |
603
|
|
|
|
|
|
|
\s+ is \s+ |
604
|
|
|
|
|
|
|
(? r[wo] ) |
605
|
|
|
|
|
|
|
)? |
606
|
|
|
|
|
|
|
(? # repeat to allow 'is' options in either order |
607
|
|
|
|
|
|
|
\s+ is \s+ req(?:uired)? |
608
|
|
|
|
|
|
|
)? |
609
|
|
|
|
|
|
|
(? |
610
|
|
|
|
|
|
|
\s*+ : \s*+ (?&ATTR) |
611
|
|
|
|
|
|
|
(?: |
612
|
|
|
|
|
|
|
(?: \s*+ : \s*+ | \s++) (?&ATTR) |
613
|
|
|
|
|
|
|
)*+ |
614
|
|
|
|
|
|
|
)? |
615
|
|
|
|
|
|
|
(? |
616
|
|
|
|
|
|
|
.*+ |
617
|
|
|
|
|
|
|
) |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
(?(DEFINE) |
620
|
|
|
|
|
|
|
(? (?&TYPE_NAME) (?: [&|] (?&TYPE_NAME) )*+ ) |
621
|
|
|
|
|
|
|
(? (?&QUAL_IDENT) (?&TYPE_PARAM)?+ ) |
622
|
|
|
|
|
|
|
(? \[ (?: [^][]*+ | (?&TYPE_PARAM) )*+ \] ) |
623
|
|
|
|
|
|
|
(? (?&IDENT) (?: :: (?&IDENT) )*+ ) |
624
|
|
|
|
|
|
|
(? [^\W\d] \w*+ ) |
625
|
|
|
|
|
|
|
(? [^\W\d]\w*+ (?! [(] ) ) |
626
|
|
|
|
|
|
|
) |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
}xms; |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
my $SHARED_DEFN = qr{ |
631
|
|
|
|
|
|
|
(? |
632
|
|
|
|
|
|
|
(?&TYPE_SPEC) |
633
|
|
|
|
|
|
|
)? |
634
|
|
|
|
|
|
|
\s*+ |
635
|
|
|
|
|
|
|
(? |
636
|
|
|
|
|
|
|
\$ | \@ | \% |
637
|
|
|
|
|
|
|
) |
638
|
|
|
|
|
|
|
(? |
639
|
|
|
|
|
|
|
[.!]? |
640
|
|
|
|
|
|
|
) |
641
|
|
|
|
|
|
|
(? |
642
|
|
|
|
|
|
|
[^\W\d] \w* # Simple identifier |
643
|
|
|
|
|
|
|
) |
644
|
|
|
|
|
|
|
(?: |
645
|
|
|
|
|
|
|
\s+ is \s+ |
646
|
|
|
|
|
|
|
(? r[wo] ) |
647
|
|
|
|
|
|
|
)? |
648
|
|
|
|
|
|
|
(? |
649
|
|
|
|
|
|
|
.* |
650
|
|
|
|
|
|
|
) |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
(?(DEFINE) |
653
|
|
|
|
|
|
|
(? (?&TYPE_NAME) (?: [&|] (?&TYPE_NAME) )*+ ) |
654
|
|
|
|
|
|
|
(? (?&QUAL_IDENT) (?&TYPE_PARAM)?+ ) |
655
|
|
|
|
|
|
|
(? \[ (?: [^][]*+ | (?&TYPE_PARAM) )*+ \] ) |
656
|
|
|
|
|
|
|
(? (?&IDENT) (?: :: (?&IDENT) )*+ ) |
657
|
|
|
|
|
|
|
(? [^\W\d] \w*+ ) |
658
|
|
|
|
|
|
|
) |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
}xms; |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
my $LEXICAL_DEFN = qr{ |
663
|
|
|
|
|
|
|
(? |
664
|
|
|
|
|
|
|
(?&TYPE_SPEC) |
665
|
|
|
|
|
|
|
)? |
666
|
|
|
|
|
|
|
\s*+ |
667
|
|
|
|
|
|
|
(? |
668
|
|
|
|
|
|
|
\$ | \@ | \% |
669
|
|
|
|
|
|
|
) |
670
|
|
|
|
|
|
|
(? |
671
|
|
|
|
|
|
|
[^\W\d] \w* # Simple identifier |
672
|
|
|
|
|
|
|
) |
673
|
|
|
|
|
|
|
(? |
674
|
|
|
|
|
|
|
.* |
675
|
|
|
|
|
|
|
) |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
(?(DEFINE) |
678
|
|
|
|
|
|
|
(? (?&TYPE_NAME) (?: (?: [&|] | => ) (?&TYPE_NAME) )*+ ) |
679
|
|
|
|
|
|
|
(? (?&QUAL_IDENT) (?&TYPE_PARAM)?+ ) |
680
|
|
|
|
|
|
|
(? \[ (?: [^][]*+ | (?&TYPE_PARAM) )*+ \] ) |
681
|
|
|
|
|
|
|
(? (?&IDENT) (?: :: (?&IDENT) )*+ ) |
682
|
|
|
|
|
|
|
(? [^\W\d] \w*+ ) |
683
|
|
|
|
|
|
|
) |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
}xms; |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
# These options can be passed in when importing, to change how accessors are generated... |
689
|
|
|
|
|
|
|
my %OIO_accessor_keyword = ( |
690
|
|
|
|
|
|
|
'standard' => { rw => 'Std', ro => 'StdRO' }, |
691
|
|
|
|
|
|
|
'unified' => { rw => 'Acc', ro => 'Get' }, |
692
|
|
|
|
|
|
|
'lvalue' => { rw => 'Lvalue', ro => 'Get' }, |
693
|
|
|
|
|
|
|
); |
694
|
|
|
|
|
|
|
@OIO_accessor_keyword{qw< std uni lval >} |
695
|
|
|
|
|
|
|
= @OIO_accessor_keyword{qw< standard unified lvalue >}; |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
my %OIO_accessor_generate = ( |
698
|
|
|
|
|
|
|
'standard' => { |
699
|
|
|
|
|
|
|
rw => sub { my ($name, $sigil) = @_; |
700
|
|
|
|
|
|
|
my $var = $sigil.$name; |
701
|
|
|
|
|
|
|
my $unpack = $sigil eq '$' ? 'shift' : '@_'; |
702
|
|
|
|
|
|
|
return qq{ sub get_$name { shift; $var } |
703
|
|
|
|
|
|
|
sub set_$name { local \$Carp::CarpLevel = 1; |
704
|
|
|
|
|
|
|
shift; |
705
|
|
|
|
|
|
|
$var = $unpack; |
706
|
|
|
|
|
|
|
}; |
707
|
|
|
|
|
|
|
}; |
708
|
|
|
|
|
|
|
}, |
709
|
|
|
|
|
|
|
ro => sub { my ($name, $sigil) = @_; my $var = $sigil.$name; |
710
|
|
|
|
|
|
|
return qq{ sub get_$name { shift; $var } }; |
711
|
|
|
|
|
|
|
}, |
712
|
|
|
|
|
|
|
}, |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
'unified' => { |
715
|
|
|
|
|
|
|
rw => sub { my ($name, $sigil) = @_; |
716
|
|
|
|
|
|
|
my $var = $sigil.$name; |
717
|
|
|
|
|
|
|
my $unpack = $sigil eq '$' ? 'shift' : '@_'; |
718
|
|
|
|
|
|
|
return qq{ sub $name { local \$Carp::CarpLevel = 1; |
719
|
|
|
|
|
|
|
shift; |
720
|
|
|
|
|
|
|
if (\@_) { |
721
|
|
|
|
|
|
|
$var = $unpack; |
722
|
|
|
|
|
|
|
} |
723
|
|
|
|
|
|
|
$var |
724
|
|
|
|
|
|
|
}; }; |
725
|
|
|
|
|
|
|
}, |
726
|
|
|
|
|
|
|
ro => sub { my ($name, $sigil) = @_; my $var = $sigil.$name; |
727
|
|
|
|
|
|
|
return qq{ sub $name { shift; $var } }; |
728
|
|
|
|
|
|
|
}, |
729
|
|
|
|
|
|
|
}, |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
'lvalue' => { |
732
|
|
|
|
|
|
|
rw => sub { my ($name, $sigil) = @_; |
733
|
|
|
|
|
|
|
my $var = $sigil.$name; |
734
|
|
|
|
|
|
|
return qq{ sub $name :lvalue { |
735
|
|
|
|
|
|
|
local \$Carp::CarpLevel = 1; |
736
|
|
|
|
|
|
|
$var |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
}; |
739
|
|
|
|
|
|
|
}, |
740
|
|
|
|
|
|
|
ro => sub { my ($name, $sigil) = @_; my $var = $sigil.$name; |
741
|
|
|
|
|
|
|
return qq{ sub $name { $var } }; |
742
|
|
|
|
|
|
|
}, |
743
|
|
|
|
|
|
|
}, |
744
|
|
|
|
|
|
|
); |
745
|
|
|
|
|
|
|
@OIO_accessor_generate{qw< std uni lval >} |
746
|
|
|
|
|
|
|
= @OIO_accessor_generate{qw< standard unified lvalue >}; |
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
# Convert a 'has' to an OIO variable declaration with attributes... |
749
|
|
|
|
|
|
|
sub _compose_field { |
750
|
34
|
|
|
34
|
|
111
|
my ($type, $var, $traits, $handles, $initializer, $constraint) = @_; |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
# Normalize constraint... |
753
|
34
|
100
|
|
|
|
170
|
$constraint = $constraint ? 'sub ' . substr($constraint, 5) : q{}; |
754
|
34
|
50
|
66
|
|
|
410
|
if ($constraint && !defined $type) { |
755
|
0
|
|
|
|
|
0
|
$type = 'Any'; |
756
|
|
|
|
|
|
|
} |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
# Read-only or readwrite??? |
759
|
34
|
100
|
|
|
|
87
|
my $rw = $traits =~ /\brw\b/ ? 'rw' : 'ro'; |
760
|
34
|
|
|
|
|
287
|
my $required = $traits =~ /\breq(?:uired)?\b/; |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
# Did the user specify a particular kind of accessor generation??? |
763
|
34
|
|
|
|
|
281
|
my $accessor_type = $^H{'Dios accessor_type'}; |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
# Unpack the parsed components of the field declaration... |
766
|
34
|
|
|
|
|
81
|
my ($sigil, $twigil, $name) = $var =~ m{\A ([\$\@%]) ([.!]?+) (\S*+) }xms; |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
# Adapt type to sigil... |
769
|
34
|
100
|
50
|
|
|
394
|
my $container_type = ($sigil eq '@') ? "Array[".($type//'Any')."]" |
|
|
100
|
50
|
|
|
|
|
770
|
|
|
|
|
|
|
: ($sigil eq '%') ? "Hash[".($type//'Any')."]" |
771
|
|
|
|
|
|
|
: $type; |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
# Is it type-checked??? |
774
|
34
|
|
|
|
|
80
|
my $TYPE_SETUP = q{}; |
775
|
34
|
|
|
|
|
66
|
my $TYPE_VALIDATOR = q{}; |
776
|
34
|
100
|
|
|
|
101
|
if ($type) { |
777
|
28
|
|
|
|
|
60
|
state $validator_num = 0; $validator_num++; |
|
28
|
|
|
|
|
60
|
|
778
|
28
|
|
|
|
|
146
|
$TYPE_VALIDATOR = qq[ { no warnings; \$Dios::_internal::attr_validator_$validator_num = Dios::Types::validator_for(q{$container_type}, 'Value (%s) for $sigil$name attribute', $constraint ); } ]; |
779
|
28
|
|
|
|
|
81
|
$TYPE_SETUP = qq[ :Type( sub{ \$Dios::_internal::attr_validator_$validator_num->(shift) }) ]; |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
# Define accessors... |
783
|
34
|
100
|
|
|
|
259
|
my $access = $twigil ne '.' ? q{} : $OIO_accessor_keyword{$accessor_type}{$rw}."(Name=>q{$name}) $TYPE_SETUP"; |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
# Is it a delegated handler??? |
786
|
34
|
|
|
|
|
71
|
my $delegators = ''; |
787
|
34
|
|
|
|
|
101
|
for my $delegation (split /(?&WS) handles (?&WS) (?(DEFINE) (? \s*+ (?: \# [^\n]*+ \n \s*+ )*+ ))/x, $handles) { |
788
|
0
|
0
|
|
|
|
0
|
next unless $delegation; |
789
|
0
|
0
|
|
|
|
0
|
if ($delegation =~ m{^:(.*)<(.*)>$}xms) { |
790
|
0
|
|
|
|
|
0
|
$delegators .= " :Handles($1-->$2)"; |
791
|
|
|
|
|
|
|
} |
792
|
|
|
|
|
|
|
else { |
793
|
0
|
|
|
|
|
0
|
$delegators .= " :Handles($delegation)"; |
794
|
|
|
|
|
|
|
} |
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
# Is it initialized??? |
798
|
34
|
100
|
|
|
|
302
|
my $init = qq{:Arg(Name=>q{$name} } . ($required ? q{, Mandatory=>1)} : q{)} ); |
799
|
34
|
|
|
|
|
65
|
my $INIT_FUNC = q{}; |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
# Ensure array and hash attrs are initialized... |
802
|
34
|
50
|
33
|
|
|
186
|
if ($sigil =~ /[\@%]/ && (!$initializer || $initializer =~ m{\A \s*+ \z}xms)) { |
|
|
|
66
|
|
|
|
|
803
|
15
|
|
|
|
|
100
|
$initializer = '//=()'; |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
# Install the initialization code... |
807
|
34
|
100
|
|
|
|
141
|
if ($initializer =~ m{\A \s*+ (? // \s*+ )? = (? .*+ ) }xms) { |
808
|
20
|
|
|
|
|
240
|
my %init_field = %+; |
809
|
20
|
|
|
|
|
72
|
my $init_val = $init_field{INIT_VAL}; |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
# Adapt initializer value to sigil... |
812
|
20
|
100
|
|
|
|
92
|
if ($sigil eq '@') { $init_val = "[$init_val]"; } |
|
7
|
100
|
|
|
|
23
|
|
813
|
8
|
|
|
|
|
26
|
elsif ($sigil eq '%') { $init_val = "+{$init_val}"; } |
814
|
|
|
|
|
|
|
|
815
|
20
|
100
|
|
|
|
90
|
$init = qq{:DEFAULT(___i_n_i_t__${name}___(\$self)) } . ($init_field{DEFAULT_INIT} ? $init : q{}); |
816
|
20
|
|
|
|
|
79
|
$INIT_FUNC = qq{sub ___i_n_i_t__${name}___ { my (\$self) = \@_; $init_val }}; |
817
|
|
|
|
|
|
|
} |
818
|
|
|
|
|
|
|
else { |
819
|
14
|
|
|
|
|
78
|
$init .= $initializer; |
820
|
|
|
|
|
|
|
} |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
# Update the attribute setting code... |
823
|
34
|
|
|
|
|
232
|
$^H{'Dios attrnames'} .= "$name,"; |
824
|
34
|
100
|
|
|
|
109
|
if ($sigil eq '$') { |
825
|
19
|
50
|
|
|
|
204
|
$^H{'Dios attrs'} .= $] < 5.022 ? qq{alias my \$$name = \$_Dios__attr_${name}[\${\$_[0]}];} |
826
|
|
|
|
|
|
|
: qq{ \\ my \$$name = \\ \$_Dios__attr_${name}[\${\$_[0]}];}; |
827
|
|
|
|
|
|
|
} |
828
|
|
|
|
|
|
|
else { |
829
|
15
|
50
|
|
|
|
124
|
$^H{'Dios attrs'} |
830
|
|
|
|
|
|
|
.= $] < 5.022 ? qq{alias my $sigil$name = $sigil}.qq{{\$_Dios__attr_${name}[\${\$_[0]}]};} |
831
|
|
|
|
|
|
|
: qq{ \\ my $sigil$name = \$_Dios__attr_${name}[\${\$_[0]}]; }; |
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
# Add type-checking code to alias... |
834
|
34
|
100
|
|
|
|
105
|
if ($type) { |
835
|
28
|
|
|
|
|
156
|
$^H{'Dios attrs'} .= qq{ Dios::Types::_set_var_type(q{$type}, \\$sigil$name, 'Value (%s) for $sigil$name attribute', $constraint ); }; |
836
|
|
|
|
|
|
|
} |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
# Return the converted syntax... |
839
|
34
|
|
|
|
|
426
|
return qq{ $TYPE_VALIDATOR my \@_Dios__attr_$name : Field $access $delegators $init $TYPE_SETUP; $INIT_FUNC; }; |
840
|
|
|
|
|
|
|
} |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
# Convert a typed lexical variable... |
843
|
|
|
|
|
|
|
sub _compose_lexical { |
844
|
3
|
|
|
3
|
|
10
|
my ($type, $variable, $constraint) = @_; |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
# Normalize constraint... |
847
|
3
|
100
|
|
|
|
42
|
$constraint = $constraint ? 'sub ' . substr($constraint, 5) : q{}; |
848
|
3
|
50
|
66
|
|
|
57
|
if ($constraint && !defined $type) { |
849
|
0
|
|
|
|
|
0
|
$type = 'Any'; |
850
|
|
|
|
|
|
|
} |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
# Is it type-checked??? |
853
|
3
|
|
|
|
|
6
|
my $TYPE_SETUP = q{}; |
854
|
3
|
50
|
|
|
|
10
|
if (defined $type) { |
855
|
3
|
|
|
|
|
14
|
$TYPE_SETUP = qq[ Dios::Types::_set_var_type(q{$type}, \\$variable, 'Value (%s) assigned to $variable', $constraint ); ]; |
856
|
|
|
|
|
|
|
} |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
# Return the converted syntax... |
859
|
3
|
|
|
|
|
26
|
return qq{my $variable; $TYPE_SETUP; $variable = $variable}; |
860
|
|
|
|
|
|
|
} |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
# Convert a 'shared' to a class attribute... |
864
|
|
|
|
|
|
|
sub _compose_shared { |
865
|
5
|
|
|
5
|
|
15
|
my ($type, $var, $traits, $initializer, $constraint) = @_; |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
# Normalize constraint... |
868
|
5
|
100
|
|
|
|
25
|
$constraint = $constraint ? 'sub ' . substr($constraint, 5) : q{}; |
869
|
5
|
50
|
66
|
|
|
62
|
if ($constraint && !defined $type) { |
870
|
0
|
|
|
|
|
0
|
$type = 'Any'; |
871
|
|
|
|
|
|
|
} |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
# Did the user specify a particular kind of accessor generation??? |
874
|
5
|
|
|
|
|
17
|
my $accessor_type = $^H{'Dios accessor_type'}; |
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
# Unpack the parsed components of the shared declaration... |
877
|
5
|
|
|
|
|
14
|
my ($sigil, $twigil, $name) = $var =~ m{\A ([\$\@%]) ([.!]?+) (\S*+) }xms; |
878
|
5
|
100
|
|
|
|
37
|
my $rw = $traits =~ /\brw\b/ ? 'rw' : 'ro'; |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
# Generate accessor subs... |
881
|
|
|
|
|
|
|
my $accessors = $twigil ne '.' ? q{} |
882
|
5
|
50
|
|
|
|
59
|
: $OIO_accessor_generate{$accessor_type}{$rw}->($name, $sigil); |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
# Build type checking sub... |
885
|
5
|
|
|
|
|
12
|
my $type_func = q{}; |
886
|
5
|
100
|
|
|
|
10
|
if ($type) { |
887
|
1
|
|
|
|
|
6
|
$type_func = qq[ sub ___t_y_p_e__${name}___ { state \$check = Dios::Types::validator_for(q{$type}, 'Value (%s) for \$$name attribute' ); \$check->($_[0]) } ___t_y_p_e__${name}___($sigil$name); ]; |
888
|
|
|
|
|
|
|
} |
889
|
|
|
|
|
|
|
else { |
890
|
4
|
|
|
|
|
22
|
$type_func = q{}; |
891
|
|
|
|
|
|
|
} |
892
|
|
|
|
|
|
|
# Is it type-checked??? |
893
|
5
|
|
|
|
|
10
|
my $TYPE_SETUP = q{}; |
894
|
5
|
100
|
|
|
|
9
|
if ($type) { |
895
|
1
|
|
|
|
|
5
|
$TYPE_SETUP = qq[ Dios::Types::_set_var_type(q{$type}, \\$sigil$name, 'Value (%s) for shared $sigil$name attribute', '$sigil', $constraint ); ]; |
896
|
|
|
|
|
|
|
} |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
# Return the converted syntax... |
899
|
5
|
|
|
|
|
31
|
return qq{my $sigil$name $initializer; $TYPE_SETUP; $accessors}; |
900
|
|
|
|
|
|
|
} |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
sub _multi_dispatch { |
905
|
56
|
|
|
56
|
|
483
|
use Data::Dump 'dump'; |
|
56
|
|
|
|
|
103
|
|
|
56
|
|
|
|
|
33190
|
|
906
|
|
|
|
|
|
|
|
907
|
58
|
|
|
58
|
|
75998
|
my $subname = shift; |
908
|
58
|
|
|
|
|
109
|
my $kind = shift; |
909
|
58
|
|
|
|
|
158
|
my @arg_list = @_; |
910
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
# Find all possible variants for this call... |
912
|
58
|
|
|
|
|
102
|
our %multis; |
913
|
58
|
|
50
|
|
|
114
|
my @variants = @{ $Dios::multis{$subname} //= [] }; |
|
58
|
|
|
|
|
331
|
|
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
# But only those in the right hierarchy, if it's a method call |
916
|
58
|
100
|
|
|
|
182
|
if ($kind eq 'method') { |
917
|
28
|
|
|
|
|
57
|
@variants = grep { $arg_list[0]->isa($_->{class}) } @variants; |
|
196
|
|
|
|
|
1850
|
|
918
|
|
|
|
|
|
|
} |
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
# And only those in the right namespace, if it's a function call... |
921
|
|
|
|
|
|
|
else { |
922
|
30
|
|
|
|
|
100
|
my $caller = caller; |
923
|
30
|
|
|
|
|
581
|
@variants = grep { $_->{class} eq $caller } @variants; |
|
122
|
|
|
|
|
301
|
|
924
|
|
|
|
|
|
|
} |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
# Eliminate variants that doen't match the argument list... |
927
|
58
|
|
|
|
|
348
|
for my $variant (@variants) { |
928
|
290
|
|
|
|
|
374
|
my $match = eval{ $variant->{validator}(@arg_list) }; |
|
290
|
|
|
|
|
1042
|
|
929
|
290
|
100
|
|
|
|
53857
|
if (defined $match) { |
930
|
103
|
|
|
|
|
128
|
@{$variant}{ keys %{$match} } = values %{$match}; |
|
103
|
|
|
|
|
486
|
|
|
103
|
|
|
|
|
191
|
|
|
103
|
|
|
|
|
262
|
|
931
|
|
|
|
|
|
|
} |
932
|
|
|
|
|
|
|
else { |
933
|
187
|
|
|
|
|
387
|
$variant = undef; |
934
|
|
|
|
|
|
|
} |
935
|
|
|
|
|
|
|
} |
936
|
58
|
|
|
|
|
126
|
@variants = grep { defined } @variants; |
|
290
|
|
|
|
|
442
|
|
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
# If there's only one left, we're done... |
939
|
58
|
100
|
|
|
|
227
|
return $variants[0] if @variants == 1; |
940
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
# If there isn't one left, we're also done (but not in a good way)... |
942
|
|
|
|
|
|
|
return { |
943
|
6
|
|
|
6
|
|
74
|
impl => sub { my $args = dump(@arg_list); |
944
|
6
|
50
|
|
|
|
1407
|
croak "No suitable '$subname' variant found for call to multi $subname", |
945
|
|
|
|
|
|
|
(($args =~ m{\A \( .* \) \Z}xms) ? $args : qq{($args)}); |
946
|
|
|
|
|
|
|
}, |
947
|
33
|
100
|
|
|
|
163
|
} if @variants == 0; |
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
# There were 2+ left, so pick the one with the most specific signature... |
950
|
27
|
|
|
|
|
98
|
@variants = Dios::Types::_resolve_signatures($kind, @variants); |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
# If there isn't one left, we're also done (but in an even worse way than before)... |
953
|
|
|
|
|
|
|
return { |
954
|
0
|
|
|
0
|
|
0
|
impl => sub { my $args = dump(@arg_list); |
955
|
0
|
0
|
|
|
|
0
|
croak "Dios: Internal error in dispatch resolution of multi $subname", |
956
|
|
|
|
|
|
|
(($args =~ m{\A \( .* \) \Z}xms) ? $args : qq{($args)}); |
957
|
|
|
|
|
|
|
}, |
958
|
27
|
50
|
|
|
|
76
|
} if @variants == 0; |
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
# Otherwise, return the most specific/earliest... |
961
|
27
|
|
|
|
|
89
|
return $variants[0]; |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
#====[ NOTE: I still prefer an ambiguity warning, but Perl 6 no longer does that :-( ]===== |
964
|
|
|
|
|
|
|
# |
965
|
|
|
|
|
|
|
# # Otherwise, the call is ambiguous, so report that... |
966
|
|
|
|
|
|
|
# return { |
967
|
|
|
|
|
|
|
# impl => sub { |
968
|
|
|
|
|
|
|
# croak "Ambiguous call to multi '$subname'. Could invoke any of:\n", |
969
|
|
|
|
|
|
|
# map({ my $sig = $_->{sig}; "\t$subname(". join(',',map({$_->{type}} @$sig)) .")\n" } @variants), |
970
|
|
|
|
|
|
|
# "to handle:\n\t$subname(", dump(@arg_list)=~s/^\(|\)$//gr, ")\ncalled"; |
971
|
|
|
|
|
|
|
# }, |
972
|
|
|
|
|
|
|
# }; |
973
|
|
|
|
|
|
|
} |
974
|
|
|
|
|
|
|
|
975
|
56
|
|
|
56
|
|
1415109
|
keytype ParamList is m{ |
976
|
|
|
|
|
|
|
\( |
977
|
|
|
|
|
|
|
(?: |
978
|
|
|
|
|
|
|
(?&Parameter) |
979
|
|
|
|
|
|
|
(?: |
980
|
|
|
|
|
|
|
(?: (?&PerlOWS) [:,] |
981
|
|
|
|
|
|
|
(?: (?&Parameter) (?&PerlOWS) , )*+ |
982
|
|
|
|
|
|
|
(?&Parameter)?+ |
983
|
|
|
|
|
|
|
)?+ |
984
|
|
|
|
|
|
|
)?+ |
985
|
|
|
|
|
|
|
)?+ |
986
|
|
|
|
|
|
|
(?: (?&PerlOWS) --> [^)]*+ )?+ |
987
|
|
|
|
|
|
|
(?&PerlOWS) |
988
|
|
|
|
|
|
|
\) |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
(?(DEFINE) |
991
|
|
|
|
|
|
|
(? |
992
|
|
|
|
|
|
|
(?&PerlOWS) |
993
|
|
|
|
|
|
|
(?: |
994
|
|
|
|
|
|
|
# Nameless literal constraint |
995
|
|
|
|
|
|
|
(?&PerlNumber) | (?&PerlQuotelikeQ) | (?&PerlMatch) |
996
|
|
|
|
|
|
|
| |
997
|
|
|
|
|
|
|
(?! , | --> | \) ) # Every component is optional, but there must be at least one |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
# TYPE... |
1000
|
|
|
|
|
|
|
(?: (?&TYPE_SPEC) (?&PerlOWS) )?+ |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
# NAME... |
1003
|
|
|
|
|
|
|
(?> |
1004
|
|
|
|
|
|
|
: (?&IDENT) \( (?&PerlOWS) [\$\@%] (?&IDENT) (?&PerlOWS) \) |
1005
|
|
|
|
|
|
|
| |
1006
|
|
|
|
|
|
|
: [\$\@%] (?&IDENT) |
1007
|
|
|
|
|
|
|
| |
1008
|
|
|
|
|
|
|
\* |
1009
|
|
|
|
|
|
|
(?: |
1010
|
|
|
|
|
|
|
[\@%] (?&IDENT)?+ |
1011
|
|
|
|
|
|
|
| |
1012
|
|
|
|
|
|
|
: (?&IDENT) \( (?&PerlOWS) \@ (?&IDENT) (?&PerlOWS) \) |
1013
|
|
|
|
|
|
|
| |
1014
|
|
|
|
|
|
|
: \@ (?&IDENT) |
1015
|
|
|
|
|
|
|
) |
1016
|
|
|
|
|
|
|
| |
1017
|
|
|
|
|
|
|
[\$\@%] (?&IDENT)?+ |
1018
|
|
|
|
|
|
|
)?+ |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
# OPTIONAL OR REQUIRED... |
1021
|
|
|
|
|
|
|
[?!]?+ |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
# CONSTRAINT... |
1024
|
|
|
|
|
|
|
(?: (?&PerlOWS) where (?&PerlOWS) (?&PerlBlock) )?+ |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
# READONLY OR ALIAS... |
1027
|
|
|
|
|
|
|
(?: (?&PerlOWS) is (?&PerlOWS) (?: ro | alias ) )?+ |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
# DEFAULT VALUE... |
1030
|
|
|
|
|
|
|
(?: (?&PerlOWS) (?://|\|\|)? = (?&PerlOWS) (?&PerlConditionalExpression) )?+ |
1031
|
|
|
|
|
|
|
) |
1032
|
|
|
|
|
|
|
) |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
(? (?&TYPE_NAME) (?: [&|] (?&TYPE_NAME) )*+ ) |
1035
|
|
|
|
|
|
|
(? (?&QUAL_IDENT) (?&TYPE_PARAM)?+ ) |
1036
|
|
|
|
|
|
|
(? \[ (?: [^][]*+ | (?&TYPE_PARAM) )*+ \] ) |
1037
|
|
|
|
|
|
|
(? (?&IDENT) (?: :: (?&IDENT) )*+ ) |
1038
|
|
|
|
|
|
|
(? [^\W\d] \w*+ ) |
1039
|
|
|
|
|
|
|
) |
1040
|
|
|
|
|
|
|
}xms; |
1041
|
|
|
|
|
|
|
|
1042
|
0
|
|
|
|
|
|
sub import { |
1043
|
66
|
|
|
66
|
|
6638
|
my (undef, $opt) = @_; |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
# What kind of accessors were requested in this scope??? |
1046
|
|
|
|
|
|
|
$^H{'Dios accessor_type'} |
1047
|
66
|
|
66
|
|
|
1159
|
= $opt->{accessor} // $opt->{accessors} // $opt->{acc} // q{standard}; |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
1048
|
|
|
|
|
|
|
|
1049
|
|
|
|
|
|
|
# How should the invocants be named in this scope??? |
1050
|
66
|
|
100
|
|
|
603
|
my $invocant_name = $opt->{invocant} // $opt->{inv} // q{$self}; |
|
|
|
100
|
|
|
|
|
1051
|
66
|
50
|
|
|
|
751
|
if ($invocant_name =~ m{\A (\$?+) ([^\W\d]\w*+) \Z}xms) { |
1052
|
66
|
|
100
|
|
|
663
|
$^H{'Dios invocant_name'} = ($1||'$').$2; |
1053
|
|
|
|
|
|
|
} |
1054
|
|
|
|
|
|
|
else { |
1055
|
0
|
|
|
|
|
0
|
_error "Invalid invocant specification: '$invocant_name'\nin 'use Dios' statement"; |
1056
|
|
|
|
|
|
|
} |
1057
|
|
|
|
|
|
|
|
1058
|
66
|
|
|
|
|
137
|
# Class definitions are translated to encapsulated packages using OIO... |
1059
|
56
|
|
|
56
|
|
1267702
|
keytype Bases is /is (?&PerlNWS) (?&PerlQualifiedIdentifier)/x; |
|
66
|
|
|
|
|
117
|
|
1060
|
0
|
50
|
50
|
52
|
|
0
|
keyword class ( |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
459
|
|
|
52
|
|
|
|
|
3623566
|
|
|
52
|
|
|
|
|
136
|
|
|
52
|
|
|
|
|
148
|
|
1061
|
0
|
|
|
|
|
0
|
QualIdent $class_name, |
|
66
|
|
|
|
|
2497
|
|
|
52
|
|
|
|
|
183
|
|
1062
|
0
|
|
|
|
|
0
|
Bases* @bases, |
|
52
|
|
|
|
|
1154
|
|
1063
|
|
|
|
|
|
|
Block $block |
1064
|
0
|
|
|
|
|
0
|
) |
|
0
|
|
|
|
|
0
|
|
|
52
|
|
|
|
|
1881
|
|
|
52
|
|
|
|
|
108
|
|
1065
|
0
|
|
|
|
|
0
|
{{{ { package <{$class_name}>; use Object::InsideOut <{ s{^ is (?&WS) (?(DEFINE) (? \s*+ (?: \# .*+ \n \s*+ )*+ ))}{}x for @bases; (@bases ? qq{qw{@bases}} : q{}) }>; do <{ $block }> } }}} |
|
52
|
|
|
|
|
113
|
|
1066
|
0
|
|
0
|
|
|
0
|
|
|
52
|
|
100
|
|
|
281324
|
|
1067
|
0
|
|
|
|
|
0
|
# Function definitions are translated to subroutines with extra argument-unpacking code... |
|
21
|
|
|
|
|
176631
|
|
|
66
|
|
|
|
|
1456
|
|
1068
|
0
|
50
|
50
|
53
|
|
0
|
keyword func ( |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
249
|
|
|
53
|
|
|
|
|
2785265
|
|
|
53
|
|
|
|
|
95
|
|
|
53
|
|
|
|
|
113
|
|
1069
|
0
|
|
|
|
|
0
|
QualIdent $sub_name = '', |
|
66
|
|
|
|
|
1450
|
|
|
53
|
|
|
|
|
108
|
|
1070
|
0
|
|
|
|
|
0
|
ParamList $parameter_list = '', |
|
0
|
|
|
|
|
0
|
|
|
52
|
|
|
|
|
284826
|
|
|
53
|
|
|
|
|
1147
|
|
1071
|
|
|
|
|
|
|
Attributes $attrs = '', |
1072
|
0
|
|
|
|
|
0
|
Block $block |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
52
|
|
|
|
|
115
|
|
|
52
|
|
|
|
|
133
|
|
|
53
|
|
|
|
|
1588
|
|
|
53
|
|
|
|
|
109
|
|
1073
|
0
|
|
|
|
|
0
|
) |
|
0
|
|
|
|
|
0
|
|
|
52
|
|
|
|
|
5579
|
|
|
53
|
|
|
|
|
1090530
|
|
1074
|
0
|
|
|
|
|
0
|
{ |
|
52
|
|
|
|
|
1118
|
|
1075
|
|
|
|
|
|
|
# Generate code that unpacks and tests arguments... |
1076
|
56
|
0
|
|
|
|
409
|
$parameter_list = _translate_parameters($parameter_list, func => "$sub_name"); |
|
0
|
100
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
662
|
|
|
52
|
|
|
|
|
859
|
|
|
52
|
|
|
|
|
150
|
|
|
52
|
|
|
|
|
118
|
|
|
52
|
|
|
|
|
261
|
|
|
52
|
|
|
|
|
286
|
|
|
52
|
|
|
|
|
782
|
|
1077
|
66
|
|
|
|
|
3459
|
|
1078
|
56
|
|
|
56
|
|
1477156
|
# Assemble and return the sub definition... |
1079
|
|
|
|
|
|
|
if (my $return_type = $parameter_list->{return_type}) { |
1080
|
|
|
|
|
|
|
qq{sub $sub_name $attrs { $parameter_list->{code} Dios::Types::_validate_return_type [q{$sub_name}, $return_type], \@_, sub $block } }; |
1081
|
|
|
|
|
|
|
} |
1082
|
|
|
|
|
|
|
else { |
1083
|
|
|
|
|
|
|
($sub_name ? "sub $sub_name;" : q{} ) |
1084
|
|
|
|
|
|
|
. qq{sub $sub_name $attrs { $parameter_list->{code} do $block } }; |
1085
|
|
|
|
|
|
|
} |
1086
|
|
|
|
|
|
|
} |
1087
|
|
|
|
|
|
|
|
1088
|
66
|
|
|
|
|
1354
|
# Multi definitions are translated to subroutines with extra argument-unpacking code... |
1089
|
0
|
50
|
50
|
34
|
|
0
|
keyword multi ( |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
211
|
|
|
34
|
|
|
|
|
2174356
|
|
|
34
|
|
|
|
|
73
|
|
|
34
|
|
|
|
|
91
|
|
1090
|
0
|
|
|
|
|
0
|
/method|func/ $type = 'func', |
|
66
|
|
|
|
|
1360
|
|
|
34
|
|
|
|
|
98
|
|
1091
|
0
|
|
|
|
|
0
|
QualIdent $sub_name = '', |
|
34
|
|
|
|
|
1055
|
|
1092
|
|
|
|
|
|
|
ParamList $parameter_list = '', |
1093
|
0
|
|
|
|
|
0
|
Attributes $attrs = '', |
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
1267
|
|
|
34
|
|
|
|
|
92
|
|
1094
|
0
|
|
|
|
|
0
|
Block $block |
|
34
|
|
|
|
|
95
|
|
1095
|
0
|
|
|
|
|
0
|
) |
|
34
|
|
|
|
|
677
|
|
1096
|
|
|
|
|
|
|
{ |
1097
|
0
|
|
|
|
|
0
|
# Generate code that unpacks and tests arguments... |
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
719
|
|
|
34
|
|
|
|
|
77
|
|
1098
|
0
|
|
|
|
|
0
|
$parameter_list = _translate_parameters($parameter_list, $type => "$sub_name"); |
|
34
|
|
|
|
|
795269
|
|
1099
|
|
|
|
|
|
|
my $parameter_types = $parameter_list->{spec}; |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
# Assemble and return the method definition... |
1102
|
|
|
|
|
|
|
my $code = qq{ BEGIN { *$sub_name = sub { my \$best_variant = Dios::_multi_dispatch('$sub_name', '$type', \@_); \@_ = \@{\$best_variant->{args}//[]}; goto &{\$best_variant->{impl}}; } if ! *${sub_name}{CODE}; } }; |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
my $multiname = sprintf 'DIOS_multi_%010d', ++$Dios::multinum; |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
# Assemble and return the sub definition... |
1107
|
|
|
|
|
|
|
if (my $return_type = $parameter_list->{return_type}) { |
1108
|
|
|
|
|
|
|
$code .= qq{sub $multiname; sub $multiname $attrs { local *$multiname = '$sub_name'; $parameter_list->{code}; return { args => \\\@_, impl => sub { local *__ANON__ = '$sub_name'; Dios::Types::_validate_return_type [q{$sub_name}, $return_type], \@_, sub $block } } } }; |
1109
|
|
|
|
|
|
|
} |
1110
|
|
|
|
|
|
|
else { |
1111
|
|
|
|
|
|
|
$block = substr($block,1,-1); |
1112
|
|
|
|
|
|
|
$code .= qq{sub $multiname; sub $multiname $attrs { local *$multiname = '$sub_name'; $parameter_list->{code}; return { args => \\\@_, impl => sub { local *__ANON__ = '$sub_name'; $block } } } }; |
1113
|
|
|
|
|
|
|
} |
1114
|
|
|
|
|
|
|
$code .= qq{BEGIN{ push \@{ \$Dios::multis{q{$sub_name}} }, { sig => [$parameter_types], class => __PACKAGE__, validator => \\&$multiname }; }}; |
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
return $code; |
1117
|
|
|
|
|
|
|
} |
1118
|
|
|
|
|
|
|
|
1119
|
66
|
|
|
|
|
1370
|
# Method definitions are translated to subroutines with extra invocant-and-argument-unpacking code... |
1120
|
0
|
50
|
50
|
131
|
|
0
|
keyword method ( |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
244
|
|
|
131
|
|
|
|
|
8290578
|
|
|
131
|
|
|
|
|
358
|
|
|
131
|
|
|
|
|
341
|
|
1121
|
0
|
|
|
|
|
0
|
QualIdent $sub_name = '', |
|
66
|
|
|
|
|
1479
|
|
|
131
|
|
|
|
|
357
|
|
1122
|
0
|
|
|
|
|
0
|
ParamList $parameter_list = '', |
|
131
|
|
|
|
|
3486
|
|
1123
|
|
|
|
|
|
|
Attributes $attrs = '', |
1124
|
0
|
|
|
|
|
0
|
Block $block |
|
0
|
|
|
|
|
0
|
|
|
131
|
|
|
|
|
4558
|
|
|
131
|
|
|
|
|
293
|
|
1125
|
0
|
|
|
|
|
0
|
) |
|
131
|
|
|
|
|
2977497
|
|
1126
|
|
|
|
|
|
|
{ |
1127
|
|
|
|
|
|
|
# Which kind of aliasing do we need (to create local vars bound to the object's fields)??? |
1128
|
|
|
|
|
|
|
my $use_aliasing = $] < 5.022 ? q{use Data::Alias} : q{use experimental 'refaliasing'}; |
1129
|
|
|
|
|
|
|
my $attr_binding = $^H{'Dios attrs'} ? "$use_aliasing; $^H{'Dios attrs'}" : q{}; |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
# Generate code that unpacks and tests arguments... |
1132
|
|
|
|
|
|
|
$parameter_list = _translate_parameters($parameter_list, method => "$sub_name"); |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
# Assemble and return the method definition... |
1135
|
|
|
|
|
|
|
($sub_name ? "sub $sub_name;" : q{} ) |
1136
|
|
|
|
|
|
|
. qq{sub $sub_name $attrs { $attr_binding { $parameter_list->{code}; do $block } } }; |
1137
|
|
|
|
|
|
|
} |
1138
|
|
|
|
|
|
|
|
1139
|
0
|
|
|
|
|
0
|
# Submethod definitions are translated like methods, but with special re-routing... |
|
53
|
|
|
|
|
12380
|
|
|
66
|
|
|
|
|
1260
|
|
1140
|
0
|
50
|
50
|
12
|
|
0
|
keyword submethod ( |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
203
|
|
|
12
|
|
|
|
|
742302
|
|
|
12
|
|
|
|
|
38
|
|
|
12
|
|
|
|
|
35
|
|
1141
|
0
|
|
|
|
|
0
|
QualIdent $sub_name = '', |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
53
|
|
|
|
|
3338
|
|
|
53
|
|
|
|
|
134
|
|
|
66
|
|
|
|
|
1362
|
|
|
12
|
|
|
|
|
30
|
|
1142
|
0
|
|
|
|
|
0
|
ParamList $parameter_list = '', |
|
0
|
|
|
|
|
0
|
|
|
53
|
|
|
|
|
117
|
|
|
12
|
|
|
|
|
284
|
|
1143
|
0
|
|
|
|
|
0
|
Attributes $attrs = '', |
|
53
|
|
|
|
|
1897
|
|
1144
|
0
|
|
|
|
|
0
|
Block $block |
|
0
|
|
|
|
|
0
|
|
|
12
|
|
|
|
|
406
|
|
|
12
|
|
|
|
|
36
|
|
1145
|
0
|
|
|
|
|
0
|
) |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
53
|
|
|
|
|
1317
|
|
|
53
|
|
|
|
|
121
|
|
|
12
|
|
|
|
|
272463
|
|
1146
|
0
|
|
|
|
|
0
|
{ |
|
53
|
|
|
|
|
21166
|
|
1147
|
0
|
|
|
|
|
0
|
# Which kind of aliasing do we need (to create local vars bound to the object's fields)??? |
|
53
|
|
|
|
|
11081
|
|
1148
|
|
|
|
|
|
|
my $use_aliasing = $] < 5.022 ? q{use Data::Alias} : q{use experimental 'refaliasing'}; |
1149
|
0
|
|
|
|
|
0
|
my $attr_binding = $^H{'Dios attrs'} ? "$use_aliasing; $^H{'Dios attrs'}" : q{}; |
|
53
|
|
|
|
|
1068
|
|
1150
|
|
|
|
|
|
|
|
1151
|
0
|
|
|
|
|
0
|
# Extract attribute names... |
|
53
|
|
|
|
|
479
|
|
1152
|
|
|
|
|
|
|
my %attr_name = map { $_ => 1 } split ',', ($^H{'Dios attrnames'}//q{}); |
1153
|
|
|
|
|
|
|
|
1154
|
0
|
0
|
|
|
|
0
|
# Generate the code to unpack and test arguments... |
|
53
|
100
|
|
|
|
225
|
|
1155
|
0
|
|
|
|
|
0
|
my $parameter_spec = _translate_parameters($parameter_list, method => "$sub_name"); |
|
30
|
|
|
|
|
241
|
|
1156
|
|
|
|
|
|
|
|
1157
|
|
|
|
|
|
|
# Handle any special submethod names... |
1158
|
0
|
0
|
|
|
|
0
|
my $init_args = q{}; |
|
23
|
100
|
|
|
|
148
|
|
1159
|
|
|
|
|
|
|
if ($sub_name eq 'BUILD') { |
1160
|
|
|
|
|
|
|
# Extract named args for :InitArgs hash (TODO: this should pull out type/required info too)... |
1161
|
56
|
|
|
|
|
408
|
|
|
66
|
|
|
|
|
495
|
|
1162
|
66
|
|
|
|
|
2414
|
my $invalid_names |
1163
|
56
|
|
|
56
|
|
1872854
|
= join ', ', map { $attr_name{$_} ? ":$_" : () } @{$parameter_spec->{names}}; |
1164
|
0
|
|
|
|
|
0
|
if (my $invalid_names = join ', ', map { $attr_name{$_} ? ":$_" : () } @{$parameter_spec->{names}} ) { |
|
34
|
|
|
|
|
8502
|
|
1165
|
|
|
|
|
|
|
_error("Can't use an attribute name as a parameter name ($invalid_names)\nin submethod BUILD()"); |
1166
|
0
|
|
|
|
|
0
|
} |
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
2455
|
|
|
34
|
|
|
|
|
110
|
|
1167
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
91
|
|
1168
|
0
|
|
|
|
|
0
|
# Tell OIO about this constructor args... |
|
34
|
|
|
|
|
1595
|
|
1169
|
|
|
|
|
|
|
$init_args = qq{ BEGIN{ my %$sub_name :InitArgs = map { \$_ => {} } qw{@{$parameter_spec->{names}}}; } }; |
1170
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
1019
|
|
|
34
|
|
|
|
|
77
|
|
1171
|
0
|
|
|
|
|
0
|
# Mark the sub as an initializer |
|
34
|
|
|
|
|
16673
|
|
1172
|
0
|
|
|
|
|
0
|
$attrs .= ' :Private :Init'; |
|
34
|
|
|
|
|
5971
|
|
1173
|
|
|
|
|
|
|
|
1174
|
0
|
|
|
|
|
0
|
# Repack the arguments from ($self, {attr=>val, et=>cetera}) to ($self, attr=>val, et=>cetera)... |
|
34
|
|
|
|
|
835
|
|
1175
|
|
|
|
|
|
|
$attr_binding = q{@_ = ($_[0], %{$_[1]});} . $attr_binding; |
1176
|
0
|
|
|
|
|
0
|
} |
|
34
|
|
|
|
|
390
|
|
1177
|
0
|
|
|
|
|
0
|
elsif ($sub_name eq 'DESTROY') { |
|
34
|
|
|
|
|
123
|
|
1178
|
|
|
|
|
|
|
# Parameter list will never be satisfied (which breaks cleanup), so don't allow it at all... |
1179
|
|
|
|
|
|
|
return q{die 'submethod DESTROY cannot have a parameter list';} |
1180
|
0
|
|
|
|
|
0
|
if $parameter_list && $parameter_list !~ /^\(\s*+\)$/; |
|
34
|
|
|
|
|
157
|
|
1181
|
|
|
|
|
|
|
|
1182
|
0
|
|
|
|
|
0
|
# Mark it as a destructor... |
|
34
|
|
|
|
|
599
|
|
1183
|
|
|
|
|
|
|
$attrs .= ' :Private :Destroy'; |
1184
|
|
|
|
|
|
|
|
1185
|
0
|
0
|
|
|
|
0
|
# Rename it so as not to clash with OIO's DESTROY... |
|
34
|
50
|
|
|
|
124
|
|
1186
|
0
|
|
|
|
|
0
|
$sub_name = '___DESTROY___'; |
|
0
|
|
|
|
|
0
|
|
1187
|
|
|
|
|
|
|
} |
1188
|
|
|
|
|
|
|
else { |
1189
|
0
|
|
|
|
|
0
|
$attr_binding = qq{ if ((ref(\$_[0])||\$_[0]) ne __PACKAGE__) { return \$_[0]->SUPER::$sub_name(\@_[1..\$#_]); } } . $attr_binding; |
|
34
|
|
|
|
|
103
|
|
1190
|
0
|
|
|
|
|
0
|
} |
|
34
|
|
|
|
|
376
|
|
1191
|
0
|
|
|
|
|
0
|
|
|
131
|
|
|
|
|
33275
|
|
1192
|
0
|
|
|
|
|
0
|
# Assemble and return the method definition... |
|
34
|
|
|
|
|
452
|
|
1193
|
0
|
|
|
|
|
0
|
($sub_name ? "sub $sub_name;" : q{} ) |
|
0
|
|
|
|
|
0
|
|
|
131
|
|
|
|
|
9156
|
|
|
131
|
|
|
|
|
408
|
|
1194
|
0
|
|
|
|
|
0
|
. qq{$init_args sub $sub_name $attrs { $attr_binding { $parameter_spec->{code}; do $block } } }; |
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
938
|
|
|
131
|
|
|
|
|
435
|
|
1195
|
56
|
|
|
|
|
487
|
} |
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
1663
|
|
|
131
|
|
|
|
|
5008
|
|
1196
|
66
|
|
|
|
|
3592
|
|
1197
|
56
|
|
|
56
|
|
2067559
|
# Components of variable declaration... |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
131
|
|
|
|
|
3565
|
|
|
131
|
|
|
|
|
315
|
|
|
66
|
|
|
|
|
1240
|
|
1198
|
0
|
|
|
56
|
|
0
|
keytype TypeSpec is m{ (?&TypeSpec) |
|
56
|
|
|
|
|
1301170
|
|
|
131
|
|
|
|
|
24739
|
|
1199
|
0
|
|
|
|
|
0
|
(?(DEFINE) |
|
131
|
|
|
|
|
111458
|
|
1200
|
|
|
|
|
|
|
(? |
1201
|
0
|
|
|
|
|
0
|
(?&TypeName) (?: (?: [&|] | => ) (?&TypeName) )*+ |
|
131
|
|
|
|
|
3122
|
|
1202
|
|
|
|
|
|
|
) |
1203
|
0
|
0
|
|
|
|
0
|
(? |
|
131
|
50
|
|
|
|
742
|
|
1204
|
0
|
0
|
|
|
|
0
|
\s* (?&TypeName) (?: \s* (?: [&|] | => ) \s* (?&TypeName) )*+ \s* |
|
131
|
100
|
|
|
|
682
|
|
1205
|
|
|
|
|
|
|
) |
1206
|
|
|
|
|
|
|
(? |
1207
|
0
|
|
|
|
|
0
|
Match \[ [^]]*+ \] |
|
131
|
|
|
|
|
1268
|
|
1208
|
|
|
|
|
|
|
| |
1209
|
|
|
|
|
|
|
(?&PerlIdentifier) \[ (?&TypeSpecSpacey) \] |
1210
|
0
|
0
|
|
|
|
0
|
| |
|
131
|
100
|
|
|
|
937
|
|
1211
|
0
|
|
|
|
|
0
|
(?&PerlQualifiedIdentifier) |
|
12
|
|
|
|
|
2646
|
|
1212
|
56
|
|
|
|
|
400
|
) |
|
66
|
|
|
|
|
452
|
|
1213
|
0
|
|
|
|
|
0
|
) |
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
2321
|
|
|
12
|
|
|
|
|
1141
|
|
|
12
|
|
|
|
|
59
|
|
1214
|
56
|
|
|
56
|
|
1991536
|
}x; |
|
0
|
|
|
|
|
0
|
|
|
12
|
|
|
|
|
34
|
|
|
66
|
|
|
|
|
108
|
|
1215
|
0
|
|
|
56
|
|
0
|
keytype Var is / [\$\@%] [.!]?+ (?&PerlIdentifier) /x; |
|
56
|
|
|
|
|
1284751
|
|
|
12
|
|
|
|
|
394
|
|
|
66
|
|
|
|
|
92
|
|
1216
|
56
|
|
|
56
|
|
1273686
|
keytype Traits is / (?: (?&PerlOWS) is (?&PerlOWS) (?: ro | rw | req(?:uired)? ) )++ /x; |
|
66
|
|
|
|
|
89
|
|
1217
|
0
|
|
|
56
|
|
0
|
keytype Handles is / (?: (?&PerlOWS) handles (?&PerlOWS) |
|
0
|
|
|
|
|
0
|
|
|
56
|
|
|
|
|
1282894
|
|
|
12
|
|
|
|
|
311
|
|
|
12
|
|
|
|
|
26
|
|
1218
|
0
|
|
|
|
|
0
|
(?: (?&PerlIdentifier) | :(?&PerlIdentifier)<(?&PerlIdentifier)> ) |
|
12
|
|
|
|
|
1424
|
|
1219
|
0
|
|
|
|
|
0
|
)++ /x; |
|
12
|
|
|
|
|
7074
|
|
|
66
|
|
|
|
|
96
|
|
1220
|
56
|
|
|
56
|
|
1283818
|
keytype Init is m{ (?: // )?+ = (?&PerlOWS) (?&PerlExpression) }x; |
|
66
|
|
|
|
|
89
|
|
1221
|
0
|
|
|
56
|
|
0
|
keytype Constraint is m{ where (?&PerlOWS) (?&PerlBlock) }x; |
|
56
|
|
|
|
|
1281900
|
|
|
12
|
|
|
|
|
273
|
|
1222
|
|
|
|
|
|
|
|
1223
|
0
|
0
|
|
|
|
0
|
# An attribute definition is translated into an array with a :Field attribute... |
|
12
|
50
|
|
|
|
75
|
|
|
66
|
|
|
|
|
102
|
|
1224
|
0
|
0
|
50
|
34
|
|
0
|
keyword has ( |
|
0
|
100
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
12
|
|
|
|
|
85
|
|
|
66
|
|
|
|
|
189
|
|
|
34
|
|
|
|
|
2130748
|
|
|
34
|
|
|
|
|
87
|
|
|
34
|
|
|
|
|
108
|
|
1225
|
0
|
|
|
|
|
0
|
TypeSpec $type = '', |
|
66
|
|
|
|
|
1391
|
|
|
34
|
|
|
|
|
753124
|
|
1226
|
|
|
|
|
|
|
Var $variable, |
1227
|
0
|
|
0
|
|
|
0
|
Constraint $constraint = '', |
|
0
|
|
100
|
|
|
0
|
|
|
12
|
|
|
|
|
102
|
|
|
7
|
|
|
|
|
35
|
|
1228
|
|
|
|
|
|
|
Traits $traits = '', |
1229
|
|
|
|
|
|
|
Handles $handles = '', |
1230
|
0
|
|
|
|
|
0
|
Init $init = '', |
|
12
|
|
|
|
|
69
|
|
1231
|
|
|
|
|
|
|
) { |
1232
|
|
|
|
|
|
|
_compose_field($type, $variable, $traits, $handles, $init, $constraint) |
1233
|
0
|
|
|
|
|
0
|
} |
|
12
|
|
|
|
|
35
|
|
1234
|
0
|
0
|
|
|
|
0
|
|
|
12
|
0
|
|
|
|
64
|
|
|
66
|
100
|
|
|
|
1312
|
|
|
|
100
|
|
|
|
|
|
1235
|
56
|
|
|
56
|
|
1284076
|
keytype ReadTraits is / (?&PerlOWS) is (?&PerlOWS) (?: ro | rw ) /x; |
1236
|
|
|
|
|
|
|
|
1237
|
66
|
|
|
|
|
110
|
# An attribute definition is translated into an my var with extra code for accessors... |
1238
|
0
|
0
|
50
|
5
|
|
0
|
keyword shared ( |
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
8
|
|
|
|
|
101
|
|
|
5
|
|
|
|
|
62
|
|
|
8
|
|
|
|
|
45
|
|
|
66
|
|
|
|
|
186
|
|
|
5
|
|
|
|
|
356953
|
|
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
10
|
|
1239
|
0
|
0
|
|
|
|
0
|
TypeSpec $type = '', |
|
0
|
0
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
8
|
|
|
|
|
17
|
|
|
5
|
|
|
|
|
43
|
|
|
8
|
|
|
|
|
23
|
|
|
66
|
|
|
|
|
1322
|
|
|
5
|
|
|
|
|
101489
|
|
1240
|
0
|
|
|
|
|
0
|
Var $variable, |
|
0
|
|
|
|
|
0
|
|
1241
|
|
|
|
|
|
|
Constraint $constraint = '', |
1242
|
0
|
|
|
|
|
0
|
ReadTraits $traits = '', |
|
34
|
|
|
|
|
7979
|
|
1243
|
|
|
|
|
|
|
Init $init = '', |
1244
|
0
|
|
|
|
|
0
|
) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
8
|
|
|
|
|
40
|
|
|
8
|
|
|
|
|
53
|
|
|
34
|
|
|
|
|
2387
|
|
|
34
|
|
|
|
|
110
|
|
1245
|
0
|
|
|
|
|
0
|
_compose_shared($type, $variable, $traits, $init, $constraint) |
|
34
|
|
|
|
|
2908
|
|
1246
|
0
|
|
|
|
|
0
|
} |
|
34
|
|
|
|
|
1468
|
|
1247
|
0
|
|
|
|
|
0
|
|
|
8
|
|
|
|
|
18
|
|
1248
|
0
|
|
|
|
|
0
|
# An lexical variable definition is translated into a typed lexical... |
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
1195
|
|
|
34
|
|
|
|
|
79
|
|
|
66
|
|
|
|
|
1328
|
|
1249
|
0
|
50
|
50
|
3
|
|
0
|
keyword lex (TypeSpec? $type, Var $variable, Constraint? $constraint) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
109
|
|
|
66
|
|
|
|
|
215
|
|
|
3
|
|
|
|
|
218499
|
|
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
8
|
|
1250
|
0
|
|
|
|
|
0
|
_compose_lexical($type, $variable, $constraint) |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
8
|
|
|
|
|
60
|
|
|
34
|
|
|
|
|
696
|
|
|
66
|
|
|
|
|
1391
|
|
|
3
|
|
|
|
|
66962
|
|
1251
|
|
|
|
|
|
|
} |
1252
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
735
|
|
|
34
|
|
|
|
|
74
|
|
1253
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
948
|
|
1254
|
0
|
0
|
0
|
|
|
0
|
# Subtypes are handled by Dios::Types... |
|
0
|
50
|
66
|
|
|
0
|
|
|
3
|
|
|
|
|
49
|
|
|
34
|
|
|
|
|
572
|
|
|
66
|
|
|
|
|
1354
|
|
1255
|
56
|
50
|
50
|
2
|
|
387
|
keyword subtype {{{ use Dios::Types; subtype }}} |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
66
|
|
|
|
|
203
|
|
|
66
|
|
|
|
|
329
|
|
|
2
|
|
|
|
|
132091
|
|
|
2
|
|
|
|
|
9
|
|
1256
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
615
|
|
|
34
|
|
|
|
|
67
|
|
|
5
|
|
|
|
|
1027
|
|
|
66
|
|
|
|
|
1360
|
|
|
66
|
|
|
|
|
1748
|
|
1257
|
0
|
|
|
56
|
|
0
|
# Tail recursion is handled as in Perl 6... |
|
56
|
|
|
|
|
1670028
|
|
|
34
|
|
|
|
|
65
|
|
|
66
|
|
|
|
|
1355
|
|
1258
|
0
|
50
|
50
|
1
|
|
0
|
keyword callwith () {{{ goto &{+do{no strict 'refs'; \&{(caller 0)[3]} }} for 1, @_ = grep 1, }}} |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
56
|
|
|
|
|
383
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
3
|
|
|
|
|
17
|
|
|
34
|
|
|
|
|
432
|
|
|
5
|
|
|
|
|
309
|
|
|
5
|
|
|
|
|
14
|
|
|
66
|
|
|
|
|
207
|
|
|
66
|
|
|
|
|
332
|
|
|
1
|
|
|
|
|
52586
|
|
|
1
|
|
|
|
|
7
|
|
|
66
|
|
|
|
|
1296
|
|
1259
|
0
|
50
|
50
|
1
|
|
0
|
keyword callsame () {{{ goto &{+do{no strict 'refs'; \&{(caller 0)[3]} }} }}} |
|
56
|
|
|
|
|
386
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
5
|
|
|
|
|
328
|
|
|
66
|
|
|
|
|
1293
|
|
|
66
|
|
|
|
|
1750
|
|
|
66
|
|
|
|
|
227
|
|
|
66
|
|
|
|
|
320
|
|
|
1
|
|
|
|
|
54122
|
|
|
1
|
|
|
|
|
6
|
|
1260
|
0
|
|
|
56
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
56
|
|
|
|
|
1689550
|
|
|
34
|
|
|
|
|
558
|
|
|
34
|
|
|
|
|
79
|
|
|
5
|
|
|
|
|
113
|
|
|
66
|
|
|
|
|
1263
|
|
|
66
|
|
|
|
|
1703
|
|
1261
|
0
|
|
|
56
|
|
0
|
} |
|
0
|
|
|
|
|
0
|
|
|
56
|
|
|
|
|
1712106
|
|
|
3
|
|
|
|
|
19
|
|
|
34
|
|
|
|
|
176
|
|
1262
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
34
|
|
|
|
|
392
|
|
|
5
|
|
|
|
|
112
|
|
|
5
|
|
|
|
|
10
|
|
1263
|
0
|
|
|
|
|
0
|
1; # Magic true value required at end of module |
|
5
|
|
|
|
|
44
|
|
1264
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
9
|
|
|
34
|
|
|
|
|
535
|
|
|
5
|
|
|
|
|
75
|
|
1265
|
0
|
|
|
|
|
0
|
__END__ |