line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mylisp::LintMyAst;
|
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
3070
|
use 5.012;
|
|
1
|
|
|
|
|
4
|
|
4
|
1
|
|
|
1
|
|
7
|
use experimental 'switch';
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
6
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
166
|
use Exporter;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
96
|
|
7
|
|
|
|
|
|
|
our @ISA = qw(Exporter);
|
8
|
|
|
|
|
|
|
our @EXPORT = qw(Report IsDefine Context InBlock InFunc InContext OutContext OutBlock GetIndent LintMyAst GetAtomType GetArrayType GetCallType);
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
16
|
use Mylisp;
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
81
|
|
11
|
1
|
|
|
1
|
|
18
|
use Mylisp::Builtin;
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
241
|
|
12
|
1
|
|
|
1
|
|
9
|
use Mylisp::Estr;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
183
|
|
13
|
1
|
|
|
1
|
|
8
|
use Mylisp::Match;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
11734
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub get_type_grammar {
|
16
|
|
|
|
|
|
|
return <<'EOF'
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
door -> |\s+ Spec|+ $
|
19
|
|
|
|
|
|
|
Spec -> Rule '->' pat
|
20
|
|
|
|
|
|
|
pat -> |\h+ Branch More Maybe Token Str|+
|
21
|
|
|
|
|
|
|
Branch -> '|'
|
22
|
|
|
|
|
|
|
More -> Token'+'
|
23
|
|
|
|
|
|
|
Maybe -> Token'?'
|
24
|
|
|
|
|
|
|
Rule -> name
|
25
|
|
|
|
|
|
|
Token -> name
|
26
|
|
|
|
|
|
|
Str -> ':'\a+
|
27
|
|
|
|
|
|
|
name -> \a+
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
EOF
|
30
|
0
|
|
|
0
|
0
|
|
;;
|
31
|
|
|
|
|
|
|
}
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub get_my_type_grammar {
|
34
|
|
|
|
|
|
|
return <<'EOF'
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
Nil -> :Nil
|
37
|
|
|
|
|
|
|
Bool -> :Bool
|
38
|
|
|
|
|
|
|
Str -> :Str|:String|:Lstr|:Char
|
39
|
|
|
|
|
|
|
Int -> :Int
|
40
|
|
|
|
|
|
|
Strs -> :Strs
|
41
|
|
|
|
|
|
|
Ints -> :Ints
|
42
|
|
|
|
|
|
|
Table -> :Table
|
43
|
|
|
|
|
|
|
Tree -> :Tree
|
44
|
|
|
|
|
|
|
Fn -> :Fn
|
45
|
|
|
|
|
|
|
Atom -> Str|Int
|
46
|
|
|
|
|
|
|
Array -> Strs|Ints
|
47
|
|
|
|
|
|
|
Hash -> Table|Tree
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
EOF
|
50
|
0
|
|
|
0
|
0
|
|
;;
|
51
|
|
|
|
|
|
|
}
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub get_type_table {
|
54
|
0
|
|
|
0
|
0
|
|
my $grammar = get_type_grammar;
|
55
|
0
|
|
|
|
|
|
my $ast = GrammarToAst($grammar);
|
56
|
0
|
|
|
|
|
|
return AstToTable($ast);
|
57
|
|
|
|
|
|
|
}
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub get_my_type_table {
|
60
|
0
|
|
|
0
|
0
|
|
my $table = get_type_table;
|
61
|
0
|
|
|
|
|
|
my $grammar = get_my_type_grammar;
|
62
|
0
|
|
|
|
|
|
my ($match,$ok) = MatchTable($table,$grammar);
|
63
|
0
|
0
|
|
|
|
|
if (not($ok)) {
|
64
|
0
|
|
|
|
|
|
error("$match my-type-grammar syntax error");
|
65
|
|
|
|
|
|
|
}
|
66
|
0
|
|
|
|
|
|
my $ast = opt_type_match($match);
|
67
|
0
|
|
|
|
|
|
lint_type_ast($ast);
|
68
|
0
|
|
|
|
|
|
return AstToTable($ast);
|
69
|
|
|
|
|
|
|
}
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub new_lint {
|
72
|
0
|
|
|
0
|
0
|
|
my $table = get_type_table();
|
73
|
0
|
|
|
|
|
|
my $mytable = get_my_type_table();
|
74
|
0
|
|
|
|
|
|
my $stack = ['main'];
|
75
|
0
|
|
|
|
|
|
return {'text' => '','locate' => '','stack' => $stack,'tree' => {},'ret' => '','depth' => 0,'pos' => 0,'count' => 0,'typetable' => $table,'mytypetable' => $mytable};
|
76
|
|
|
|
|
|
|
}
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub pat_to_type_rule {
|
79
|
0
|
|
|
0
|
0
|
|
my ($t,$pat) = @_;
|
80
|
0
|
|
|
|
|
|
my $table = $t->{'typetable'};
|
81
|
0
|
|
|
|
|
|
my ($match,$ok) = MatchDoor($table,$pat,'pat');
|
82
|
0
|
0
|
|
|
|
|
if (not($ok)) {
|
83
|
0
|
|
|
|
|
|
Report($t,"pattern: |$pat| could not to rule!");
|
84
|
|
|
|
|
|
|
}
|
85
|
0
|
|
|
|
|
|
return opt_type_pat($match);
|
86
|
|
|
|
|
|
|
}
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub opt_type_pat {
|
89
|
0
|
|
|
0
|
0
|
|
my $atoms = shift;
|
90
|
0
|
|
|
|
|
|
my $end = estr('End','e');
|
91
|
0
|
0
|
|
|
|
|
if (is_atom($atoms)) {
|
92
|
0
|
|
|
|
|
|
my $atom = opt_type_atom($atoms);
|
93
|
0
|
|
|
|
|
|
return estr('Rules',estr($atom,$end));
|
94
|
|
|
|
|
|
|
}
|
95
|
0
|
|
|
|
|
|
my $rule = opt_type_atoms($atoms);
|
96
|
0
|
0
|
|
|
|
|
if (is_branch($rule)) {
|
97
|
0
|
|
|
|
|
|
return estr('Rules',estr($rule,$end));
|
98
|
|
|
|
|
|
|
}
|
99
|
0
|
|
|
|
|
|
return epush($rule,$end);
|
100
|
|
|
|
|
|
|
}
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub opt_type_match {
|
103
|
0
|
|
|
0
|
0
|
|
my $match = shift;
|
104
|
0
|
0
|
|
|
|
|
if (is_atom($match)) {
|
105
|
0
|
|
|
|
|
|
return opt_type_atom($match);
|
106
|
|
|
|
|
|
|
}
|
107
|
0
|
|
|
|
|
|
return estr_strs([ map { opt_type_atom($_) } @{atoms($match)} ]);
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
}
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub opt_type_atom {
|
111
|
0
|
|
|
0
|
0
|
|
my $atom = shift;
|
112
|
0
|
|
|
|
|
|
my ($name,$value) = flat($atom);
|
113
|
0
|
|
|
|
|
|
given ($name) {
|
114
|
0
|
|
|
|
|
|
when ('Spec') {
|
115
|
0
|
|
|
|
|
|
return opt_type_spec($value);
|
116
|
|
|
|
|
|
|
}
|
117
|
0
|
|
|
|
|
|
when ('More') {
|
118
|
0
|
|
|
|
|
|
return opt_type_more($value);
|
119
|
|
|
|
|
|
|
}
|
120
|
0
|
|
|
|
|
|
when ('Maybe') {
|
121
|
0
|
|
|
|
|
|
return opt_type_maybe($value);
|
122
|
|
|
|
|
|
|
}
|
123
|
0
|
|
|
|
|
|
when ('Str') {
|
124
|
0
|
|
|
|
|
|
return opt_type_str($value);
|
125
|
|
|
|
|
|
|
}
|
126
|
0
|
|
|
|
|
|
default {
|
127
|
0
|
|
|
|
|
|
return estr($name,$value);
|
128
|
|
|
|
|
|
|
}
|
129
|
|
|
|
|
|
|
}
|
130
|
|
|
|
|
|
|
}
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub opt_type_spec {
|
133
|
0
|
|
|
0
|
0
|
|
my $atoms = shift;
|
134
|
0
|
|
|
|
|
|
my ($token,$rules) = match($atoms);
|
135
|
0
|
|
|
|
|
|
my $name = value($token);
|
136
|
0
|
|
|
|
|
|
my $opt_rules = opt_type_atoms($rules);
|
137
|
0
|
|
|
|
|
|
return estr($name,$opt_rules);
|
138
|
|
|
|
|
|
|
}
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub opt_type_atoms {
|
141
|
0
|
|
|
0
|
0
|
|
my $atoms = shift;
|
142
|
0
|
|
|
|
|
|
my $opt_atoms = [ map { opt_type_atom($_) } @{atoms($atoms)} ];
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
143
|
0
|
|
|
|
|
|
return gather_type_branch($opt_atoms);
|
144
|
|
|
|
|
|
|
}
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub gather_type_branch {
|
147
|
0
|
|
|
0
|
0
|
|
my $atoms = shift;
|
148
|
0
|
|
|
|
|
|
my $branches = [];
|
149
|
0
|
|
|
|
|
|
my $branch = [];
|
150
|
0
|
|
|
|
|
|
my $flag = 0;
|
151
|
0
|
|
|
|
|
|
my $count = 0;
|
152
|
0
|
|
|
|
|
|
for my $atom (@{$atoms}) {
|
|
0
|
|
|
|
|
|
|
153
|
0
|
0
|
|
|
|
|
if (is_branch($atom)) {
|
154
|
0
|
0
|
|
|
|
|
if ($count > 1) {
|
|
|
0
|
|
|
|
|
|
155
|
0
|
|
|
|
|
|
apush($branches,estr('Rules',estr_strs($branch)));
|
156
|
|
|
|
|
|
|
}
|
157
|
|
|
|
|
|
|
elsif ($count == 0) {
|
158
|
0
|
|
|
|
|
|
croak("branch -> error locate");
|
159
|
|
|
|
|
|
|
}
|
160
|
|
|
|
|
|
|
else {
|
161
|
0
|
|
|
|
|
|
apush($branches,$branch->[0]);
|
162
|
|
|
|
|
|
|
}
|
163
|
0
|
|
|
|
|
|
$flag = 1;
|
164
|
0
|
|
|
|
|
|
$branch = [];
|
165
|
0
|
|
|
|
|
|
$count = 0;
|
166
|
|
|
|
|
|
|
}
|
167
|
|
|
|
|
|
|
else {
|
168
|
0
|
|
|
|
|
|
apush($branch,$atom);
|
169
|
0
|
|
|
|
|
|
$count++;;
|
170
|
|
|
|
|
|
|
}
|
171
|
|
|
|
|
|
|
}
|
172
|
0
|
0
|
|
|
|
|
if ($flag == 0) {
|
173
|
0
|
0
|
|
|
|
|
if ($count == 1) {
|
174
|
0
|
|
|
|
|
|
return $branch->[0];
|
175
|
|
|
|
|
|
|
}
|
176
|
|
|
|
|
|
|
else {
|
177
|
0
|
|
|
|
|
|
return estr('Rules',estr_strs($branch));
|
178
|
|
|
|
|
|
|
}
|
179
|
|
|
|
|
|
|
}
|
180
|
0
|
0
|
|
|
|
|
if ($count > 1) {
|
181
|
0
|
|
|
|
|
|
apush($branches,estr('Rules',estr_strs($branch)));
|
182
|
|
|
|
|
|
|
}
|
183
|
|
|
|
|
|
|
else {
|
184
|
0
|
|
|
|
|
|
apush($branches,$branch->[0]);
|
185
|
|
|
|
|
|
|
}
|
186
|
0
|
|
|
|
|
|
return estr('Branch',estr_strs($branches));
|
187
|
|
|
|
|
|
|
}
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub is_branch {
|
190
|
0
|
|
|
0
|
0
|
|
my $atom = shift;
|
191
|
0
|
|
|
|
|
|
return is_atom_name($atom,'Branch');
|
192
|
|
|
|
|
|
|
}
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub opt_type_more {
|
195
|
0
|
|
|
0
|
0
|
|
my $atoms = shift;
|
196
|
0
|
|
|
|
|
|
my $atom = first(atoms($atoms));
|
197
|
0
|
|
|
|
|
|
return estr('More',opt_type_atom($atom));
|
198
|
|
|
|
|
|
|
}
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub opt_type_maybe {
|
201
|
0
|
|
|
0
|
0
|
|
my $atoms = shift;
|
202
|
0
|
|
|
|
|
|
my $atom = first(atoms($atoms));
|
203
|
0
|
|
|
|
|
|
return estr('Maybe',opt_type_atom($atom));
|
204
|
|
|
|
|
|
|
}
|
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub opt_type_str {
|
207
|
0
|
|
|
0
|
0
|
|
my $str = shift;
|
208
|
0
|
|
|
|
|
|
return estr('Str',rest_str($str));
|
209
|
|
|
|
|
|
|
}
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub lint_type_ast {
|
212
|
0
|
|
|
0
|
0
|
|
my $ast = shift;
|
213
|
0
|
|
|
|
|
|
my $table = {};
|
214
|
0
|
|
|
|
|
|
for my $atom (@{atoms($ast)}) {
|
|
0
|
|
|
|
|
|
|
215
|
0
|
|
|
|
|
|
my ($name,$value) = flat($atom);
|
216
|
0
|
0
|
|
|
|
|
if (exists $table->{$name}) {
|
217
|
0
|
|
|
|
|
|
say "repeat define type: |$name|";
|
218
|
|
|
|
|
|
|
}
|
219
|
|
|
|
|
|
|
else {
|
220
|
0
|
|
|
|
|
|
$table->{$name} = 'ok';
|
221
|
0
|
|
|
|
|
|
lint_type_atom($value,$table);
|
222
|
|
|
|
|
|
|
}
|
223
|
|
|
|
|
|
|
}
|
224
|
|
|
|
|
|
|
}
|
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub lint_type_atom {
|
227
|
0
|
|
|
0
|
0
|
|
my ($rule,$t) = @_;
|
228
|
0
|
|
|
|
|
|
my ($name,$atoms) = flat($rule);
|
229
|
0
|
0
|
|
|
|
|
if (not($name ~~ ['Str','End'])) {
|
230
|
0
|
|
|
|
|
|
given ($name) {
|
231
|
0
|
|
|
|
|
|
when ('Rules') {
|
232
|
0
|
|
|
|
|
|
lint_type_atoms($atoms,$t);
|
233
|
|
|
|
|
|
|
}
|
234
|
0
|
|
|
|
|
|
when ('Branch') {
|
235
|
0
|
|
|
|
|
|
lint_type_atoms($atoms,$t);
|
236
|
|
|
|
|
|
|
}
|
237
|
0
|
|
|
|
|
|
when ('More') {
|
238
|
0
|
|
|
|
|
|
lint_type_atom($atoms,$t);
|
239
|
|
|
|
|
|
|
}
|
240
|
0
|
|
|
|
|
|
when ('Maybe') {
|
241
|
0
|
|
|
|
|
|
lint_type_atom($atoms,$t);
|
242
|
|
|
|
|
|
|
}
|
243
|
0
|
|
|
|
|
|
default {
|
244
|
0
|
|
|
|
|
|
lint_type_token($atoms,$t);
|
245
|
|
|
|
|
|
|
}
|
246
|
|
|
|
|
|
|
}
|
247
|
|
|
|
|
|
|
}
|
248
|
|
|
|
|
|
|
}
|
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
sub lint_type_token {
|
251
|
0
|
|
|
0
|
0
|
|
my ($name,$table) = @_;
|
252
|
0
|
0
|
|
|
|
|
if (not(exists $table->{$name})) {
|
253
|
0
|
|
|
|
|
|
say "not exists type define: |$name|";
|
254
|
|
|
|
|
|
|
}
|
255
|
|
|
|
|
|
|
}
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
sub lint_type_atoms {
|
258
|
0
|
|
|
0
|
0
|
|
my ($atoms,$table) = @_;
|
259
|
0
|
|
|
|
|
|
for my $atom (@{atoms($atoms)}) {
|
|
0
|
|
|
|
|
|
|
260
|
0
|
|
|
|
|
|
lint_type_atom($atom,$table);
|
261
|
|
|
|
|
|
|
}
|
262
|
|
|
|
|
|
|
}
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub apply_char {
|
265
|
0
|
|
|
0
|
0
|
|
my $t = shift;
|
266
|
0
|
|
|
|
|
|
my $text = $t->{'text'};
|
267
|
0
|
|
|
|
|
|
my $pos = $t->{'pos'};
|
268
|
0
|
|
|
|
|
|
return substr($text, $pos, 1);
|
269
|
|
|
|
|
|
|
}
|
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub load_text {
|
272
|
0
|
|
|
0
|
0
|
|
my ($t,$text) = @_;
|
273
|
0
|
|
|
|
|
|
$t->{'text'} = add($text,End);
|
274
|
0
|
|
|
|
|
|
$t->{'pos'} = 0;
|
275
|
|
|
|
|
|
|
}
|
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub match_type {
|
278
|
0
|
|
|
0
|
0
|
|
my ($t,$rule,$text) = @_;
|
279
|
0
|
|
|
|
|
|
load_text($t,$text);
|
280
|
0
|
|
|
|
|
|
return match_type_rule($t,$rule);
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub match_type_rule {
|
284
|
0
|
|
|
0
|
0
|
|
my ($t,$rule) = @_;
|
285
|
0
|
|
|
|
|
|
my ($name,$value) = flat($rule);
|
286
|
0
|
|
|
|
|
|
given ($name) {
|
287
|
0
|
|
|
|
|
|
when ('Rules') {
|
288
|
0
|
|
|
|
|
|
return match_type_rules($t,$value);
|
289
|
|
|
|
|
|
|
}
|
290
|
0
|
|
|
|
|
|
when ('Branch') {
|
291
|
0
|
|
|
|
|
|
return match_type_branch($t,$value);
|
292
|
|
|
|
|
|
|
}
|
293
|
0
|
|
|
|
|
|
when ('More') {
|
294
|
0
|
|
|
|
|
|
return match_type_more($t,$value);
|
295
|
|
|
|
|
|
|
}
|
296
|
0
|
|
|
|
|
|
when ('Maybe') {
|
297
|
0
|
|
|
|
|
|
return match_type_maybe($t,$value);
|
298
|
|
|
|
|
|
|
}
|
299
|
0
|
|
|
|
|
|
when ('Str') {
|
300
|
0
|
|
|
|
|
|
return match_type_str($t,$value);
|
301
|
|
|
|
|
|
|
}
|
302
|
0
|
|
|
|
|
|
when ('Token') {
|
303
|
0
|
|
|
|
|
|
return match_type_token($t,$value);
|
304
|
|
|
|
|
|
|
}
|
305
|
0
|
|
|
|
|
|
when ('End') {
|
306
|
0
|
|
|
|
|
|
return match_type_end($t,$value);
|
307
|
|
|
|
|
|
|
}
|
308
|
0
|
|
|
|
|
|
default {
|
309
|
0
|
|
|
|
|
|
croak("unknown rule: $name to match!");
|
310
|
|
|
|
|
|
|
}
|
311
|
|
|
|
|
|
|
}
|
312
|
0
|
|
|
|
|
|
return 0;
|
313
|
|
|
|
|
|
|
}
|
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
sub match_type_rules {
|
316
|
0
|
|
|
0
|
0
|
|
my ($t,$rules) = @_;
|
317
|
0
|
|
|
|
|
|
for my $rule (@{atoms($rules)}) {
|
|
0
|
|
|
|
|
|
|
318
|
0
|
0
|
|
|
|
|
if (not(match_type_rule($t,$rule))) {
|
319
|
0
|
|
|
|
|
|
return 0;
|
320
|
|
|
|
|
|
|
}
|
321
|
|
|
|
|
|
|
}
|
322
|
0
|
|
|
|
|
|
return 1;
|
323
|
|
|
|
|
|
|
}
|
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
sub match_type_branch {
|
326
|
0
|
|
|
0
|
0
|
|
my ($t,$branch) = @_;
|
327
|
0
|
|
|
|
|
|
my $pos = $t->{'pos'};
|
328
|
0
|
|
|
|
|
|
for my $rule (@{atoms($branch)}) {
|
|
0
|
|
|
|
|
|
|
329
|
0
|
0
|
|
|
|
|
if (match_type_rule($t,$rule)) {
|
330
|
0
|
|
|
|
|
|
return 1;
|
331
|
|
|
|
|
|
|
}
|
332
|
0
|
|
|
|
|
|
$t->{'pos'} = $pos;
|
333
|
|
|
|
|
|
|
}
|
334
|
0
|
|
|
|
|
|
return 0;
|
335
|
|
|
|
|
|
|
}
|
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
sub match_type_token {
|
338
|
0
|
|
|
0
|
0
|
|
my ($t,$name) = @_;
|
339
|
0
|
|
|
|
|
|
while (is_space(apply_char($t))) {
|
340
|
0
|
|
|
|
|
|
$t->{'pos'}++;;
|
341
|
|
|
|
|
|
|
}
|
342
|
0
|
|
|
|
|
|
my $mytable = $t->{'mytypetable'};
|
343
|
0
|
0
|
|
|
|
|
if (not(exists $mytable->{$name})) {
|
344
|
0
|
|
|
|
|
|
Report($t,"not regist type: |$name|");
|
345
|
|
|
|
|
|
|
}
|
346
|
0
|
|
|
|
|
|
my $rule = $mytable->{$name};
|
347
|
0
|
|
|
|
|
|
return match_type_rule($t,$rule);
|
348
|
|
|
|
|
|
|
}
|
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
sub match_type_more {
|
351
|
0
|
|
|
0
|
0
|
|
my ($t,$rule) = @_;
|
352
|
0
|
|
|
|
|
|
my $time = 0;
|
353
|
0
|
|
|
|
|
|
while (1) {
|
354
|
0
|
|
|
|
|
|
my $pos = $t->{'pos'};
|
355
|
0
|
0
|
|
|
|
|
if (not(match_type_rule($t,$rule))) {
|
356
|
0
|
0
|
|
|
|
|
if ($time == 0) {
|
357
|
0
|
|
|
|
|
|
return 0;
|
358
|
|
|
|
|
|
|
}
|
359
|
0
|
|
|
|
|
|
$t->{'pos'} = $pos;
|
360
|
0
|
|
|
|
|
|
return 1;
|
361
|
|
|
|
|
|
|
}
|
362
|
0
|
|
|
|
|
|
$time++;;
|
363
|
|
|
|
|
|
|
}
|
364
|
0
|
|
|
|
|
|
return 1;
|
365
|
|
|
|
|
|
|
}
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
sub match_type_maybe {
|
368
|
0
|
|
|
0
|
0
|
|
my ($t,$rule) = @_;
|
369
|
0
|
|
|
|
|
|
my $cache = $t->{'pos'};
|
370
|
0
|
0
|
|
|
|
|
if (not(match_type_rule($t,$rule))) {
|
371
|
0
|
|
|
|
|
|
$t->{'pos'} = $cache;
|
372
|
|
|
|
|
|
|
}
|
373
|
0
|
|
|
|
|
|
return 1;
|
374
|
|
|
|
|
|
|
}
|
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub match_type_str {
|
377
|
0
|
|
|
0
|
0
|
|
my ($t,$str) = @_;
|
378
|
0
|
|
|
|
|
|
for my $char (@{to_chars($str)}) {
|
|
0
|
|
|
|
|
|
|
379
|
0
|
0
|
|
|
|
|
if ($char ne apply_char($t)) {
|
380
|
0
|
|
|
|
|
|
return 0;
|
381
|
|
|
|
|
|
|
}
|
382
|
0
|
|
|
|
|
|
$t->{'pos'}++;;
|
383
|
|
|
|
|
|
|
}
|
384
|
0
|
|
|
|
|
|
return 1;
|
385
|
|
|
|
|
|
|
}
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub match_type_end {
|
388
|
0
|
|
|
0
|
0
|
|
my ($t,$end) = @_;
|
389
|
0
|
0
|
|
|
|
|
if (apply_char($t) eq End) {
|
390
|
0
|
|
|
|
|
|
return 1;
|
391
|
|
|
|
|
|
|
}
|
392
|
0
|
|
|
|
|
|
return 0;
|
393
|
|
|
|
|
|
|
}
|
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
sub Report {
|
396
|
0
|
|
|
0
|
0
|
|
my ($t,$message) = @_;
|
397
|
0
|
|
|
|
|
|
my $locate = $t->{'locate'};
|
398
|
0
|
|
|
|
|
|
my $line = value($locate);
|
399
|
0
|
|
|
|
|
|
error("error! line: $line $message");
|
400
|
|
|
|
|
|
|
}
|
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub IsDefine {
|
403
|
0
|
|
|
0
|
0
|
|
my ($t,$name) = @_;
|
404
|
0
|
|
|
|
|
|
my $stack = $t->{'stack'};
|
405
|
0
|
|
|
|
|
|
for my $ns (@{$stack}) {
|
|
0
|
|
|
|
|
|
|
406
|
0
|
|
|
|
|
|
my $tree = $t->{'tree'};
|
407
|
0
|
0
|
|
|
|
|
if (exists $tree->{$ns}{$name}) {
|
408
|
0
|
|
|
|
|
|
return 1;
|
409
|
|
|
|
|
|
|
}
|
410
|
|
|
|
|
|
|
}
|
411
|
0
|
|
|
|
|
|
return 0;
|
412
|
|
|
|
|
|
|
}
|
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
sub update_off {
|
415
|
0
|
|
|
0
|
0
|
|
my ($t,$atom) = @_;
|
416
|
0
|
|
|
|
|
|
$t->{'locate'} = off($atom);
|
417
|
|
|
|
|
|
|
}
|
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub Context {
|
420
|
0
|
|
|
0
|
0
|
|
my $t = shift;
|
421
|
0
|
|
|
|
|
|
my $stack = $t->{'stack'};
|
422
|
0
|
|
|
|
|
|
return $stack->[0];
|
423
|
|
|
|
|
|
|
}
|
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
sub InBlock {
|
426
|
0
|
|
|
0
|
0
|
|
my $t = shift;
|
427
|
0
|
|
|
|
|
|
my $ns = int_to_str($t->{'count'});
|
428
|
0
|
|
|
|
|
|
$t->{'count'}++;;
|
429
|
0
|
|
|
|
|
|
$t->{'depth'}++;;
|
430
|
0
|
|
|
|
|
|
InContext($t,$ns);
|
431
|
|
|
|
|
|
|
}
|
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub InFunc {
|
434
|
0
|
|
|
0
|
0
|
|
my ($t,$ns) = @_;
|
435
|
0
|
|
|
|
|
|
$t->{'depth'}++;;
|
436
|
0
|
|
|
|
|
|
InContext($t,$ns);
|
437
|
|
|
|
|
|
|
}
|
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
sub InContext {
|
440
|
0
|
|
|
0
|
0
|
|
my ($t,$ns) = @_;
|
441
|
0
|
0
|
|
|
|
|
if ($ns ne Context($t)) {
|
442
|
0
|
|
|
|
|
|
my $tree = $t->{'tree'};
|
443
|
0
|
0
|
|
|
|
|
if (not(exists $tree->{$ns})) {
|
444
|
0
|
|
|
|
|
|
$tree->{$ns} = {};
|
445
|
|
|
|
|
|
|
}
|
446
|
0
|
|
|
|
|
|
aunshift($ns,$t->{'stack'});
|
447
|
|
|
|
|
|
|
}
|
448
|
|
|
|
|
|
|
}
|
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
sub OutContext {
|
451
|
0
|
|
|
0
|
0
|
|
my $t = shift;
|
452
|
0
|
|
|
|
|
|
ashift($t->{'stack'});
|
453
|
|
|
|
|
|
|
}
|
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub OutBlock {
|
456
|
0
|
|
|
0
|
0
|
|
my $t = shift;
|
457
|
0
|
|
|
|
|
|
OutContext($t);
|
458
|
0
|
|
|
|
|
|
$t->{'depth'} --;
|
459
|
|
|
|
|
|
|
}
|
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
sub GetIndent {
|
462
|
0
|
|
|
0
|
0
|
|
my $t = shift;
|
463
|
0
|
|
|
|
|
|
my $depth = $t->{'depth'};
|
464
|
0
|
|
|
|
|
|
return repeat(' ',$depth);
|
465
|
|
|
|
|
|
|
}
|
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
sub set_name_value {
|
468
|
0
|
|
|
0
|
0
|
|
my ($t,$name,$value) = @_;
|
469
|
0
|
|
|
|
|
|
my $ns = Context($t);
|
470
|
0
|
|
|
|
|
|
my $tree = $t->{'tree'};
|
471
|
0
|
0
|
|
|
|
|
if (exists $tree->{$ns}{$name}) {
|
472
|
0
|
|
|
|
|
|
Report($t,"redefine exists symbol |$name|.");
|
473
|
|
|
|
|
|
|
}
|
474
|
0
|
|
|
|
|
|
$tree->{$ns}{$name} = $value;
|
475
|
|
|
|
|
|
|
}
|
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
sub get_name_value {
|
478
|
0
|
|
|
0
|
0
|
|
my ($t,$name) = @_;
|
479
|
0
|
|
|
|
|
|
my $stack = $t->{'stack'};
|
480
|
0
|
|
|
|
|
|
my $tree = $t->{'tree'};
|
481
|
0
|
|
|
|
|
|
for my $ns (@{$stack}) {
|
|
0
|
|
|
|
|
|
|
482
|
0
|
0
|
|
|
|
|
if (exists $tree->{$ns}{$name}) {
|
483
|
0
|
|
|
|
|
|
return $tree->{$ns}{$name};
|
484
|
|
|
|
|
|
|
}
|
485
|
|
|
|
|
|
|
}
|
486
|
0
|
|
|
|
|
|
Report($t,"|$name| undefine!");
|
487
|
0
|
|
|
|
|
|
return '';
|
488
|
|
|
|
|
|
|
}
|
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
sub LintMyAst {
|
491
|
0
|
|
|
0
|
0
|
|
my $ast = shift;
|
492
|
0
|
|
|
|
|
|
my $t = new_lint();
|
493
|
0
|
|
|
|
|
|
init_my_lint($t,$ast);
|
494
|
0
|
|
|
|
|
|
lint_my_atoms($t,$ast);
|
495
|
0
|
|
|
|
|
|
$t->{'count'} = 0;
|
496
|
0
|
|
|
|
|
|
return $t;
|
497
|
|
|
|
|
|
|
}
|
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
sub init_my_lint {
|
500
|
0
|
|
|
0
|
0
|
|
my ($t,$ast) = @_;
|
501
|
0
|
|
|
|
|
|
for my $expr (@{atoms($ast)}) {
|
|
0
|
|
|
|
|
|
|
502
|
0
|
|
|
|
|
|
my ($name,$args) = flat($expr);
|
503
|
0
|
|
|
|
|
|
update_off($t,$expr);
|
504
|
0
|
|
|
|
|
|
given ($name) {
|
505
|
0
|
|
|
|
|
|
when ('package') {
|
506
|
0
|
|
|
|
|
|
InContext($t,$args);
|
507
|
|
|
|
|
|
|
}
|
508
|
0
|
|
|
|
|
|
when ('func') {
|
509
|
0
|
|
|
|
|
|
regist_func($t,$args);
|
510
|
|
|
|
|
|
|
}
|
511
|
|
|
|
|
|
|
}
|
512
|
|
|
|
|
|
|
}
|
513
|
|
|
|
|
|
|
}
|
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
sub use_package {
|
516
|
0
|
|
|
0
|
0
|
|
my ($t,$package) = @_;
|
517
|
0
|
|
|
|
|
|
my $dirs = asplit('::',$package);
|
518
|
0
|
|
|
|
|
|
my $path = ajoin('/',$dirs);
|
519
|
0
|
|
|
|
|
|
my $ast_file = add($path,'.o');
|
520
|
0
|
|
|
|
|
|
my $ast = read_file($ast_file);
|
521
|
0
|
|
|
|
|
|
load_ast($t,$ast);
|
522
|
|
|
|
|
|
|
}
|
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
sub load_ast {
|
525
|
0
|
|
|
0
|
0
|
|
my ($t,$ast) = @_;
|
526
|
0
|
|
|
|
|
|
for my $expr (@{atoms($ast)}) {
|
|
0
|
|
|
|
|
|
|
527
|
0
|
|
|
|
|
|
my ($name,$args) = flat($expr);
|
528
|
0
|
|
|
|
|
|
update_off($t,$expr);
|
529
|
0
|
|
|
|
|
|
given ($name) {
|
530
|
0
|
|
|
|
|
|
when ('const') {
|
531
|
0
|
|
|
|
|
|
regist_const($t,$args);
|
532
|
|
|
|
|
|
|
}
|
533
|
0
|
|
|
|
|
|
when ('type') {
|
534
|
0
|
|
|
|
|
|
regist_type($t,$args);
|
535
|
|
|
|
|
|
|
}
|
536
|
0
|
|
|
|
|
|
when ('struct') {
|
537
|
0
|
|
|
|
|
|
regist_struct($t,$args);
|
538
|
|
|
|
|
|
|
}
|
539
|
0
|
|
|
|
|
|
when ('func') {
|
540
|
0
|
|
|
|
|
|
regist_func($t,$args);
|
541
|
|
|
|
|
|
|
}
|
542
|
|
|
|
|
|
|
}
|
543
|
|
|
|
|
|
|
}
|
544
|
|
|
|
|
|
|
}
|
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
sub regist_const {
|
547
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
548
|
0
|
|
|
|
|
|
my ($sym,$value) = flat($args);
|
549
|
0
|
|
|
|
|
|
my $name = value($sym);
|
550
|
0
|
|
|
|
|
|
my $value_type = GetAtomType($t,$value);
|
551
|
0
|
|
|
|
|
|
set_name_value($t,$name,$value_type);
|
552
|
|
|
|
|
|
|
}
|
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
sub regist_type {
|
555
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
556
|
0
|
|
|
|
|
|
my ($sym,$type) = flat($args);
|
557
|
0
|
|
|
|
|
|
my $name = value($sym);
|
558
|
0
|
|
|
|
|
|
my $value = value($type);
|
559
|
0
|
|
|
|
|
|
set_name_value($t,$name,$value);
|
560
|
|
|
|
|
|
|
}
|
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
sub regist_struct {
|
563
|
0
|
|
|
0
|
0
|
|
my ($t,$atom) = @_;
|
564
|
0
|
|
|
|
|
|
my ($type,$fields) = flat($atom);
|
565
|
0
|
|
|
|
|
|
my $type_value = estr('Table',$type);
|
566
|
0
|
|
|
|
|
|
set_name_value($t,$type,$type_value);
|
567
|
0
|
|
|
|
|
|
InContext($t,$type);
|
568
|
0
|
|
|
|
|
|
for my $field (@{atoms($fields)}) {
|
|
0
|
|
|
|
|
|
|
569
|
0
|
|
|
|
|
|
my ($name,$value) = flat($field);
|
570
|
0
|
|
|
|
|
|
set_name_value($t,$name,$value);
|
571
|
|
|
|
|
|
|
}
|
572
|
0
|
|
|
|
|
|
OutContext($t);
|
573
|
|
|
|
|
|
|
}
|
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
sub regist_func {
|
576
|
0
|
|
|
0
|
0
|
|
my ($t,$atoms) = @_;
|
577
|
0
|
|
|
|
|
|
my ($name_args,$return) = flat($atoms);
|
578
|
0
|
|
|
|
|
|
my $return_type = get_my_atoms_value(value($return));
|
579
|
0
|
|
|
|
|
|
my ($name,$args) = flat($name_args);
|
580
|
0
|
0
|
|
|
|
|
if (is_blank($args)) {
|
581
|
0
|
|
|
|
|
|
set_name_value($t,$name,$return_type);
|
582
|
|
|
|
|
|
|
}
|
583
|
|
|
|
|
|
|
else {
|
584
|
0
|
|
|
|
|
|
my $args_type = get_my_atoms_value($args);
|
585
|
0
|
|
|
|
|
|
my $value = estr($args_type,$return_type);
|
586
|
0
|
|
|
|
|
|
set_name_value($t,$name,$value);
|
587
|
|
|
|
|
|
|
}
|
588
|
|
|
|
|
|
|
}
|
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
sub get_my_atoms_value {
|
591
|
0
|
|
|
0
|
0
|
|
my $atoms = shift;
|
592
|
0
|
|
|
|
|
|
my $names = [ map { value($_) } @{atoms($atoms)} ];
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
593
|
0
|
|
|
|
|
|
return ajoin(' ',$names);
|
594
|
|
|
|
|
|
|
}
|
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
sub get_return_type_str {
|
597
|
0
|
|
|
0
|
0
|
|
my $expr = shift;
|
598
|
0
|
|
|
|
|
|
my $args = value($expr);
|
599
|
0
|
|
|
|
|
|
my $names = [ map { value($_) } @{atoms($args)} ];
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
600
|
0
|
|
|
|
|
|
my $types = [ map { arg_type_to_return($_) } @{$names} ];
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
601
|
0
|
|
|
|
|
|
return ajoin(' ',$types);
|
602
|
|
|
|
|
|
|
}
|
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
sub arg_type_to_return {
|
605
|
0
|
|
|
0
|
0
|
|
my $type = shift;
|
606
|
0
|
|
|
|
|
|
given ($type) {
|
607
|
0
|
|
|
|
|
|
when ('Str+') {
|
608
|
0
|
|
|
|
|
|
return 'Strs';
|
609
|
|
|
|
|
|
|
}
|
610
|
0
|
|
|
|
|
|
when ('Int+') {
|
611
|
0
|
|
|
|
|
|
return 'Ints';
|
612
|
|
|
|
|
|
|
}
|
613
|
0
|
|
|
|
|
|
when ('Str?') {
|
614
|
0
|
|
|
|
|
|
return 'Str';
|
615
|
|
|
|
|
|
|
}
|
616
|
0
|
|
|
|
|
|
when ('Int?') {
|
617
|
0
|
|
|
|
|
|
return 'Int';
|
618
|
|
|
|
|
|
|
}
|
619
|
0
|
|
|
|
|
|
default {
|
620
|
0
|
|
|
|
|
|
return $type;
|
621
|
|
|
|
|
|
|
}
|
622
|
|
|
|
|
|
|
}
|
623
|
|
|
|
|
|
|
}
|
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
sub lint_my_atoms {
|
626
|
0
|
|
|
0
|
0
|
|
my ($t,$atoms) = @_;
|
627
|
0
|
|
|
|
|
|
for my $atom (@{atoms($atoms)}) {
|
|
0
|
|
|
|
|
|
|
628
|
0
|
|
|
|
|
|
lint_my_atom($t,$atom);
|
629
|
|
|
|
|
|
|
}
|
630
|
|
|
|
|
|
|
}
|
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
sub lint_my_atom {
|
633
|
0
|
|
|
0
|
0
|
|
my ($t,$atom) = @_;
|
634
|
0
|
|
|
|
|
|
my ($name,$args) = flat($atom);
|
635
|
0
|
0
|
|
|
|
|
if (not($name ~~ ['package','Str','Lstr','Int','Bool','Char','->'])) {
|
636
|
0
|
|
|
|
|
|
update_off($t,$atom);
|
637
|
0
|
|
|
|
|
|
given ($name) {
|
638
|
0
|
|
|
|
|
|
when ('use') {
|
639
|
0
|
|
|
|
|
|
use_package($t,$args);
|
640
|
|
|
|
|
|
|
}
|
641
|
0
|
|
|
|
|
|
when ('const') {
|
642
|
0
|
|
|
|
|
|
regist_const($t,$args);
|
643
|
|
|
|
|
|
|
}
|
644
|
0
|
|
|
|
|
|
when ('type') {
|
645
|
0
|
|
|
|
|
|
regist_type($t,$args);
|
646
|
|
|
|
|
|
|
}
|
647
|
0
|
|
|
|
|
|
when ('struct') {
|
648
|
0
|
|
|
|
|
|
regist_struct($t,$args);
|
649
|
|
|
|
|
|
|
}
|
650
|
0
|
|
|
|
|
|
when ('Array') {
|
651
|
0
|
|
|
|
|
|
lint_my_atoms($t,$args);
|
652
|
|
|
|
|
|
|
}
|
653
|
0
|
|
|
|
|
|
when ('Aindex') {
|
654
|
0
|
|
|
|
|
|
lint_my_atoms($t,$args);
|
655
|
|
|
|
|
|
|
}
|
656
|
0
|
|
|
|
|
|
when ('Arange') {
|
657
|
0
|
|
|
|
|
|
lint_my_atoms($t,$args);
|
658
|
|
|
|
|
|
|
}
|
659
|
0
|
|
|
|
|
|
when ('func') {
|
660
|
0
|
|
|
|
|
|
lint_my_func($t,$args);
|
661
|
|
|
|
|
|
|
}
|
662
|
0
|
|
|
|
|
|
when (':ocall') {
|
663
|
0
|
|
|
|
|
|
lint_my_ocall($t,$args);
|
664
|
|
|
|
|
|
|
}
|
665
|
0
|
|
|
|
|
|
when ('return') {
|
666
|
0
|
|
|
|
|
|
lint_my_return($t,$args);
|
667
|
|
|
|
|
|
|
}
|
668
|
0
|
|
|
|
|
|
when ('my') {
|
669
|
0
|
|
|
|
|
|
lint_my_my($t,$args);
|
670
|
|
|
|
|
|
|
}
|
671
|
0
|
|
|
|
|
|
when ('our') {
|
672
|
0
|
|
|
|
|
|
lint_my_our($t,$args);
|
673
|
|
|
|
|
|
|
}
|
674
|
0
|
|
|
|
|
|
when ('set') {
|
675
|
0
|
|
|
|
|
|
lint_my_set($t,$args);
|
676
|
|
|
|
|
|
|
}
|
677
|
0
|
|
|
|
|
|
when ('Sym') {
|
678
|
0
|
|
|
|
|
|
lint_my_sym($t,$args);
|
679
|
|
|
|
|
|
|
}
|
680
|
0
|
|
|
|
|
|
when ('for') {
|
681
|
0
|
|
|
|
|
|
lint_my_for($t,$args);
|
682
|
|
|
|
|
|
|
}
|
683
|
0
|
|
|
|
|
|
when ('while') {
|
684
|
0
|
|
|
|
|
|
lint_my_exprs($t,$args);
|
685
|
|
|
|
|
|
|
}
|
686
|
0
|
|
|
|
|
|
when ('given') {
|
687
|
0
|
|
|
|
|
|
lint_my_exprs($t,$args);
|
688
|
|
|
|
|
|
|
}
|
689
|
0
|
|
|
|
|
|
when ('when') {
|
690
|
0
|
|
|
|
|
|
lint_my_exprs($t,$args);
|
691
|
|
|
|
|
|
|
}
|
692
|
0
|
|
|
|
|
|
when ('if') {
|
693
|
0
|
|
|
|
|
|
lint_my_exprs($t,$args);
|
694
|
|
|
|
|
|
|
}
|
695
|
0
|
|
|
|
|
|
when ('elif') {
|
696
|
0
|
|
|
|
|
|
lint_my_exprs($t,$args);
|
697
|
|
|
|
|
|
|
}
|
698
|
0
|
|
|
|
|
|
when ('then') {
|
699
|
0
|
|
|
|
|
|
lint_my_block($t,$args);
|
700
|
|
|
|
|
|
|
}
|
701
|
0
|
|
|
|
|
|
when ('else') {
|
702
|
0
|
|
|
|
|
|
lint_my_block($t,$args);
|
703
|
|
|
|
|
|
|
}
|
704
|
0
|
|
|
|
|
|
when ('Hash') {
|
705
|
0
|
|
|
|
|
|
lint_my_hash($t,$args);
|
706
|
|
|
|
|
|
|
}
|
707
|
0
|
|
|
|
|
|
when ('String') {
|
708
|
0
|
|
|
|
|
|
lint_my_string($t,$args);
|
709
|
|
|
|
|
|
|
}
|
710
|
0
|
|
|
|
|
|
default {
|
711
|
0
|
|
|
|
|
|
lint_my_call($t,$name,$args);
|
712
|
|
|
|
|
|
|
}
|
713
|
|
|
|
|
|
|
}
|
714
|
|
|
|
|
|
|
}
|
715
|
|
|
|
|
|
|
}
|
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
sub lint_my_string {
|
718
|
0
|
|
|
0
|
0
|
|
my ($t,$strs) = @_;
|
719
|
0
|
|
|
|
|
|
for my $name (@{atoms($strs)}) {
|
|
0
|
|
|
|
|
|
|
720
|
0
|
0
|
|
|
|
|
if (start_with($name,'$')) {
|
721
|
0
|
0
|
|
|
|
|
next if IsDefine($t,$name);
|
722
|
0
|
|
|
|
|
|
Report($t,"undefine Variable: |$name|");
|
723
|
|
|
|
|
|
|
}
|
724
|
|
|
|
|
|
|
}
|
725
|
|
|
|
|
|
|
}
|
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
sub lint_my_hash {
|
728
|
0
|
|
|
0
|
0
|
|
my ($t,$pairs) = @_;
|
729
|
0
|
|
|
|
|
|
for my $pair (@{atoms($pairs)}) {
|
|
0
|
|
|
|
|
|
|
730
|
0
|
|
|
|
|
|
lint_my_atom($t,value($pair));
|
731
|
|
|
|
|
|
|
}
|
732
|
|
|
|
|
|
|
}
|
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
sub lint_my_exprs {
|
735
|
0
|
|
|
0
|
0
|
|
my ($t,$atoms) = @_;
|
736
|
0
|
|
|
|
|
|
my ($cond_atom,$exprs) = match($atoms);
|
737
|
0
|
|
|
|
|
|
lint_my_atom($t,$cond_atom);
|
738
|
0
|
|
|
|
|
|
lint_my_block($t,$exprs);
|
739
|
|
|
|
|
|
|
}
|
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
sub lint_my_block {
|
742
|
0
|
|
|
0
|
0
|
|
my ($t,$exprs) = @_;
|
743
|
0
|
|
|
|
|
|
InBlock($t);
|
744
|
0
|
|
|
|
|
|
lint_my_atoms($t,$exprs);
|
745
|
0
|
|
|
|
|
|
OutBlock($t);
|
746
|
|
|
|
|
|
|
}
|
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
sub lint_my_func {
|
749
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
750
|
0
|
|
|
|
|
|
my ($name_args,$rest) = match($args);
|
751
|
0
|
|
|
|
|
|
my ($return,$atoms) = match($rest);
|
752
|
0
|
|
|
|
|
|
my $return_type_str = get_return_type_str($return);
|
753
|
0
|
|
|
|
|
|
$t->{'ret'} = $return_type_str;
|
754
|
0
|
|
|
|
|
|
my ($call,$func_args) = flat($name_args);
|
755
|
0
|
|
|
|
|
|
InFunc($t,$call);
|
756
|
0
|
|
|
|
|
|
for my $arg (@{atoms($func_args)}) {
|
|
0
|
|
|
|
|
|
|
757
|
0
|
|
|
|
|
|
my ($name,$type) = flat($arg);
|
758
|
0
|
|
|
|
|
|
$type = arg_type_to_return($type);
|
759
|
0
|
|
|
|
|
|
set_name_value($t,$name,$type);
|
760
|
|
|
|
|
|
|
}
|
761
|
0
|
|
|
|
|
|
lint_my_atoms($t,$atoms);
|
762
|
0
|
|
|
|
|
|
OutBlock($t);
|
763
|
|
|
|
|
|
|
}
|
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
sub lint_my_return {
|
766
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
767
|
0
|
|
|
|
|
|
my $return_type = $t->{'ret'};
|
768
|
0
|
|
|
|
|
|
my $args_type_str = get_args_type_str($t,$args);
|
769
|
0
|
0
|
|
|
|
|
if ($return_type ne $args_type_str) {
|
770
|
0
|
|
|
|
|
|
my $args_pat = pat_to_type_rule($t,$args_type_str);
|
771
|
0
|
|
|
|
|
|
lint_my_atoms($t,$args);
|
772
|
0
|
0
|
|
|
|
|
if (not(match_type($t,$args_pat,$return_type))) {
|
773
|
0
|
|
|
|
|
|
say "|$args_type_str| != |$return_type|";
|
774
|
0
|
|
|
|
|
|
Report($t,"return type != declare type|");
|
775
|
|
|
|
|
|
|
}
|
776
|
|
|
|
|
|
|
}
|
777
|
|
|
|
|
|
|
}
|
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
sub get_args_type_str {
|
780
|
0
|
|
|
0
|
0
|
|
my ($t,$atoms) = @_;
|
781
|
0
|
|
|
|
|
|
my $types = [];
|
782
|
0
|
|
|
|
|
|
for my $atom (@{atoms($atoms)}) {
|
|
0
|
|
|
|
|
|
|
783
|
0
|
|
|
|
|
|
apush($types,GetAtomType($t,$atom));
|
784
|
|
|
|
|
|
|
}
|
785
|
0
|
|
|
|
|
|
return ajoin(' ',$types);
|
786
|
|
|
|
|
|
|
}
|
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
sub lint_my_my {
|
789
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
790
|
0
|
|
|
|
|
|
my ($sym,$value) = flat($args);
|
791
|
0
|
|
|
|
|
|
lint_my_atom($t,$value);
|
792
|
0
|
|
|
|
|
|
my $type = GetAtomType($t,$value);
|
793
|
0
|
|
|
|
|
|
my $name = value($sym);
|
794
|
0
|
0
|
|
|
|
|
if (is_str($type)) {
|
795
|
0
|
|
|
|
|
|
set_name_value($t,$name,$type);
|
796
|
|
|
|
|
|
|
}
|
797
|
|
|
|
|
|
|
else {
|
798
|
0
|
|
|
|
|
|
Report($t,"one sym accept more assign");
|
799
|
|
|
|
|
|
|
}
|
800
|
|
|
|
|
|
|
}
|
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
sub lint_my_our {
|
803
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
804
|
0
|
|
|
|
|
|
my ($array,$value) = flat($args);
|
805
|
0
|
|
|
|
|
|
lint_my_atom($t,$value);
|
806
|
0
|
|
|
|
|
|
my $type = GetAtomType($t,$value);
|
807
|
0
|
|
|
|
|
|
my $types = asplit(' ',$type);
|
808
|
0
|
|
|
|
|
|
my $syms = value($array);
|
809
|
0
|
|
|
|
|
|
my ($a,$b) = flat($syms);
|
810
|
0
|
0
|
|
|
|
|
if (len($types) != 2) {
|
811
|
0
|
|
|
|
|
|
Report($t,"my return value not two");
|
812
|
|
|
|
|
|
|
}
|
813
|
0
|
|
|
|
|
|
my $a_name = value($a);
|
814
|
0
|
|
|
|
|
|
my $b_name = value($b);
|
815
|
0
|
|
|
|
|
|
my $a_type = $types->[0];
|
816
|
0
|
|
|
|
|
|
my $b_type = $types->[1];
|
817
|
0
|
|
|
|
|
|
set_name_value($t,$a_name,$a_type);
|
818
|
0
|
|
|
|
|
|
set_name_value($t,$b_name,$b_type);
|
819
|
|
|
|
|
|
|
}
|
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
sub lint_my_ocall {
|
822
|
0
|
|
|
0
|
0
|
|
my ($t,$ocall) = @_;
|
823
|
0
|
|
|
|
|
|
my ($sym,$call) = flat($ocall);
|
824
|
0
|
|
|
|
|
|
my $type = get_name_value($t,$sym);
|
825
|
0
|
|
|
|
|
|
my $tree = $t->{'tree'};
|
826
|
0
|
0
|
|
|
|
|
if (not(exists $tree->{$type}{$call})) {
|
827
|
0
|
|
|
|
|
|
Report($t,"ocall |$call| not define!");
|
828
|
|
|
|
|
|
|
}
|
829
|
|
|
|
|
|
|
}
|
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
sub lint_my_call {
|
832
|
0
|
|
|
0
|
0
|
|
my ($t,$name,$args) = @_;
|
833
|
0
|
|
|
|
|
|
my $value = get_name_value($t,$name);
|
834
|
0
|
0
|
|
|
|
|
if (is_blank($args)) {
|
835
|
0
|
0
|
|
|
|
|
if (not(is_str($value))) {
|
836
|
0
|
|
|
|
|
|
Report($t,"call |$name| less argument");
|
837
|
|
|
|
|
|
|
}
|
838
|
|
|
|
|
|
|
}
|
839
|
|
|
|
|
|
|
else {
|
840
|
0
|
0
|
|
|
|
|
if (is_str($value)) {
|
841
|
0
|
|
|
|
|
|
Report($t,"call |$name| more argument");
|
842
|
|
|
|
|
|
|
}
|
843
|
0
|
|
|
|
|
|
my $call_str = name($value);
|
844
|
0
|
|
|
|
|
|
lint_my_atoms($t,$args);
|
845
|
0
|
|
|
|
|
|
my $args_str = get_args_type_str($t,$args);
|
846
|
0
|
0
|
|
|
|
|
if ($call_str ne $args_str) {
|
847
|
0
|
|
|
|
|
|
my $call_rule = pat_to_type_rule($t,$call_str);
|
848
|
0
|
0
|
|
|
|
|
if (not(match_type($t,$call_rule,$args_str))) {
|
849
|
0
|
|
|
|
|
|
say "|$call_str| != |$args_str|";
|
850
|
0
|
|
|
|
|
|
Report($t,"call |$name| args type not same!");
|
851
|
|
|
|
|
|
|
}
|
852
|
|
|
|
|
|
|
}
|
853
|
|
|
|
|
|
|
}
|
854
|
|
|
|
|
|
|
}
|
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
sub lint_my_for {
|
857
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
858
|
0
|
|
|
|
|
|
my ($iter_expr,$exprs) = match($args);
|
859
|
0
|
|
|
|
|
|
my ($name,$iter_atom) = flat($iter_expr);
|
860
|
0
|
|
|
|
|
|
my $type = get_iter_type($t,$iter_atom);
|
861
|
0
|
|
|
|
|
|
set_name_value($t,$name,$type);
|
862
|
0
|
|
|
|
|
|
return lint_my_block($t,$exprs);;
|
863
|
|
|
|
|
|
|
}
|
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
sub lint_my_set {
|
866
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
867
|
0
|
|
|
|
|
|
my ($sym,$value) = flat($args);
|
868
|
0
|
|
|
|
|
|
my $sym_type = GetAtomType($t,$sym);
|
869
|
0
|
|
|
|
|
|
my $value_type = GetAtomType($t,$value);
|
870
|
0
|
0
|
|
|
|
|
if ($sym_type ne $value_type) {
|
871
|
0
|
|
|
|
|
|
say "|$sym_type| != |$value_type|";
|
872
|
0
|
|
|
|
|
|
Report($t,"assign type not same with before!");
|
873
|
|
|
|
|
|
|
}
|
874
|
|
|
|
|
|
|
}
|
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
sub lint_my_sym {
|
877
|
0
|
|
|
0
|
0
|
|
my ($t,$name) = @_;
|
878
|
0
|
0
|
|
|
|
|
if (not(IsDefine($t,$name))) {
|
879
|
0
|
|
|
|
|
|
Report($t,"not define symbol: |$name|");
|
880
|
|
|
|
|
|
|
}
|
881
|
|
|
|
|
|
|
}
|
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
sub GetAtomType {
|
884
|
0
|
|
|
0
|
0
|
|
my ($t,$atom) = @_;
|
885
|
0
|
|
|
|
|
|
my ($name,$value) = flat($atom);
|
886
|
0
|
|
|
|
|
|
update_off($t,$atom);
|
887
|
0
|
0
|
|
|
|
|
if ($name ~~ ['Int','Str','Bool','Hash']) {
|
888
|
0
|
|
|
|
|
|
return $name;
|
889
|
|
|
|
|
|
|
}
|
890
|
0
|
0
|
|
|
|
|
if ($name ~~ ['Char','Lstr','String']) {
|
891
|
0
|
|
|
|
|
|
return 'Str';
|
892
|
|
|
|
|
|
|
}
|
893
|
0
|
0
|
|
|
|
|
if ($name eq 'Sym') {
|
894
|
0
|
|
|
|
|
|
return get_sym_type($t,$value);
|
895
|
|
|
|
|
|
|
}
|
896
|
0
|
0
|
|
|
|
|
if ($name eq ':ocall') {
|
897
|
0
|
|
|
|
|
|
return get_ocall_type($t,$value);
|
898
|
|
|
|
|
|
|
}
|
899
|
0
|
0
|
|
|
|
|
if ($name eq 'Array') {
|
900
|
0
|
|
|
|
|
|
return GetArrayType($t,$value);
|
901
|
|
|
|
|
|
|
}
|
902
|
0
|
0
|
|
|
|
|
if ($name eq 'Arange') {
|
903
|
0
|
|
|
|
|
|
return get_arange_type($t,$value);
|
904
|
|
|
|
|
|
|
}
|
905
|
0
|
0
|
|
|
|
|
if ($name eq 'Aindex') {
|
906
|
0
|
|
|
|
|
|
return get_aindex_type($t,$value);
|
907
|
|
|
|
|
|
|
}
|
908
|
0
|
|
|
|
|
|
return GetCallType($t,$name);
|
909
|
|
|
|
|
|
|
}
|
910
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
sub get_sym_type {
|
912
|
0
|
|
|
0
|
0
|
|
my ($t,$name) = @_;
|
913
|
0
|
|
|
|
|
|
my $value = get_name_value($t,$name);
|
914
|
0
|
0
|
|
|
|
|
if (is_str($value)) {
|
915
|
0
|
|
|
|
|
|
return $value;
|
916
|
|
|
|
|
|
|
}
|
917
|
0
|
|
|
|
|
|
return 'Fn';
|
918
|
|
|
|
|
|
|
}
|
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
sub get_ocall_type {
|
921
|
0
|
|
|
0
|
0
|
|
my ($t,$ocall) = @_;
|
922
|
0
|
|
|
|
|
|
my ($sym,$call) = flat($ocall);
|
923
|
0
|
|
|
|
|
|
my $type = get_name_value($t,$sym);
|
924
|
0
|
|
|
|
|
|
my $tree = $t->{'tree'};
|
925
|
0
|
0
|
|
|
|
|
if (not(exists $tree->{$type}{$call})) {
|
926
|
0
|
|
|
|
|
|
Report($t,"undefined call: |$call|");
|
927
|
|
|
|
|
|
|
}
|
928
|
0
|
|
|
|
|
|
return $tree->{$type}{$call};
|
929
|
|
|
|
|
|
|
}
|
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
sub GetArrayType {
|
932
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
933
|
0
|
0
|
|
|
|
|
if (is_blank($args)) {
|
934
|
0
|
|
|
|
|
|
return 'Strs';
|
935
|
|
|
|
|
|
|
}
|
936
|
0
|
|
|
|
|
|
my $sub_type = GetAtomType($t,first(atoms($args)));
|
937
|
0
|
0
|
|
|
|
|
if ($sub_type eq 'Int') {
|
938
|
0
|
|
|
|
|
|
return 'Ints';
|
939
|
|
|
|
|
|
|
}
|
940
|
0
|
|
|
|
|
|
return 'Strs';
|
941
|
|
|
|
|
|
|
}
|
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
sub get_iter_type {
|
944
|
0
|
|
|
0
|
0
|
|
my ($t,$atom) = @_;
|
945
|
0
|
|
|
|
|
|
my $type = GetAtomType($t,$atom);
|
946
|
0
|
0
|
|
|
|
|
if ($type eq 'Ints') {
|
947
|
0
|
|
|
|
|
|
return 'Int';
|
948
|
|
|
|
|
|
|
}
|
949
|
0
|
0
|
|
|
|
|
if ($type ~~ ['Strs','Table','Str']) {
|
950
|
0
|
|
|
|
|
|
return 'Str';
|
951
|
|
|
|
|
|
|
}
|
952
|
0
|
|
|
|
|
|
return 'Nil';
|
953
|
|
|
|
|
|
|
}
|
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
sub get_arange_type {
|
956
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
957
|
0
|
|
|
|
|
|
my $sym = first(atoms($args));
|
958
|
0
|
|
|
|
|
|
return GetAtomType($t,$sym);
|
959
|
|
|
|
|
|
|
}
|
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
sub get_aindex_type {
|
962
|
0
|
|
|
0
|
0
|
|
my ($t,$args) = @_;
|
963
|
0
|
|
|
|
|
|
my ($sym,$indexs) = match($args);
|
964
|
0
|
|
|
|
|
|
my $value = GetAtomType($t,$sym);
|
965
|
0
|
|
|
|
|
|
for my $index (@{atoms($indexs)}) {
|
|
0
|
|
|
|
|
|
|
966
|
0
|
|
|
|
|
|
my $type = GetAtomType($t,$index);
|
967
|
0
|
|
|
|
|
|
my $name = value($index);
|
968
|
0
|
|
|
|
|
|
$value = get_index_type($t,$value,$type,$name);
|
969
|
|
|
|
|
|
|
}
|
970
|
0
|
|
|
|
|
|
return $value;
|
971
|
|
|
|
|
|
|
}
|
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
sub get_index_type {
|
974
|
0
|
|
|
0
|
0
|
|
my ($t,$value,$type,$name) = @_;
|
975
|
0
|
|
|
|
|
|
my $type_str = add($value,$type);
|
976
|
0
|
|
|
|
|
|
given ($type_str) {
|
977
|
0
|
|
|
|
|
|
when ('StrInt') {
|
978
|
0
|
|
|
|
|
|
return 'Str';
|
979
|
|
|
|
|
|
|
}
|
980
|
0
|
|
|
|
|
|
when ('StrsInt') {
|
981
|
0
|
|
|
|
|
|
return 'Str';
|
982
|
|
|
|
|
|
|
}
|
983
|
0
|
|
|
|
|
|
when ('IntsInt') {
|
984
|
0
|
|
|
|
|
|
return 'Int';
|
985
|
|
|
|
|
|
|
}
|
986
|
0
|
|
|
|
|
|
when ('TableStr') {
|
987
|
0
|
|
|
|
|
|
return 'Str';
|
988
|
|
|
|
|
|
|
}
|
989
|
0
|
|
|
|
|
|
when ('TreeStr') {
|
990
|
0
|
|
|
|
|
|
return 'Table';
|
991
|
|
|
|
|
|
|
}
|
992
|
0
|
|
|
|
|
|
default {
|
993
|
0
|
|
|
|
|
|
my $tree = $t->{'tree'};
|
994
|
0
|
0
|
|
|
|
|
if (exists $tree->{$value}) {
|
995
|
0
|
|
|
|
|
|
my $table = $tree->{$value};
|
996
|
0
|
0
|
|
|
|
|
if (exists $table->{$name}) {
|
997
|
0
|
|
|
|
|
|
return $tree->{$value}{$name};
|
998
|
|
|
|
|
|
|
}
|
999
|
|
|
|
|
|
|
}
|
1000
|
|
|
|
|
|
|
}
|
1001
|
|
|
|
|
|
|
}
|
1002
|
0
|
|
|
|
|
|
return 'Nil';
|
1003
|
|
|
|
|
|
|
}
|
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
sub GetCallType {
|
1006
|
0
|
|
|
0
|
0
|
|
my ($t,$name) = @_;
|
1007
|
0
|
0
|
|
|
|
|
if ($name ~~ ['func','if','else','elif','given','when','then','my','use','package','const','for','while','return','struct','type']) {
|
1008
|
0
|
|
|
|
|
|
return 'Nil';
|
1009
|
|
|
|
|
|
|
}
|
1010
|
0
|
|
|
|
|
|
my $value = get_name_value($t,$name);
|
1011
|
0
|
0
|
|
|
|
|
if (is_str($value)) {
|
1012
|
0
|
|
|
|
|
|
return $value;
|
1013
|
|
|
|
|
|
|
}
|
1014
|
0
|
|
|
|
|
|
return value($value);
|
1015
|
|
|
|
|
|
|
}
|
1016
|
|
|
|
|
|
|
1;
|