Line | Branch | Exec | Source |
---|---|---|---|
1 | #include "ast/magic.h" | ||
2 | #include "ast/nodes.h" | ||
3 | #include "ast/visitor.h" | ||
4 | #include "compatibility/compatibility.h" | ||
5 | #include "dependencies/fmt.h" | ||
6 | #include "lexer/unlex.h" | ||
7 | #include "logging/logging.h" | ||
8 | #include "parser/parsing_error.h" | ||
9 | #include "utilities/strings.h" | ||
10 | |||
11 | namespace lython { | ||
12 | |||
13 | struct CircleTrait { | ||
14 | using Trace = std::true_type; | ||
15 | using StmtRet = bool; | ||
16 | using ExprRet = bool; | ||
17 | using ModRet = bool; | ||
18 | using PatRet = bool; | ||
19 | |||
20 | enum | ||
21 | { MaxRecursionDepth = LY_MAX_VISITOR_RECURSION_DEPTH }; | ||
22 | }; | ||
23 | |||
24 | #define ReturnType bool | ||
25 | |||
26 | // Circle should not happen | ||
27 | // Weird things can happen during sema where we create/resolve types | ||
28 | // this is here so we can do a sanity check and prevent stack overflows while debugging | ||
29 | struct Circle: BaseVisitor<Circle, true, CircleTrait> { | ||
30 | using Super = BaseVisitor<Circle, true, CircleTrait>; | ||
31 | Array<Node const*> visited; | ||
32 | |||
33 | bool in(Node const* obj, int depth) { | ||
34 |
2/2✓ Branch 0 taken 195 times.
✓ Branch 1 taken 564 times.
|
759 | if (obj == nullptr) { |
35 | 195 | return false; | |
36 | } | ||
37 | |||
38 |
2/2✓ Branch 5 taken 971 times.
✓ Branch 6 taken 564 times.
|
1535 | for (Node const* item: visited) { |
39 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 971 times.
|
971 | if (item == obj) { |
40 | kwtrace(depth, "Duplicate is: {}", meta::type_name(item->class_id)); | ||
41 | ✗ | return true; | |
42 | } | ||
43 | } | ||
44 | |||
45 | 564 | visited.push_back(obj); | |
46 | 564 | return false; | |
47 | } | ||
48 | |||
49 | ReturnType exec(ModNode_t* mod, int depth) { | ||
50 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (in(mod, depth)) { |
51 | ✗ | return true; | |
52 | } | ||
53 | |||
54 | 1 | return Super::exec(mod, depth); | |
55 | } | ||
56 | ReturnType exec(Pattern_t* pat, int depth) { | ||
57 | ✗ | if (in(pat, depth)) { | |
58 | ✗ | return true; | |
59 | } | ||
60 | |||
61 | ✗ | return Super::exec(pat, depth); | |
62 | } | ||
63 | ReturnType exec(ExprNode_t* expr, int depth) { | ||
64 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 747 times.
|
747 | if (in(expr, depth)) { |
65 | ✗ | return true; | |
66 | } | ||
67 | |||
68 | 747 | return Super::exec(expr, depth); | |
69 | } | ||
70 | ReturnType exec(StmtNode_t* stmt, int depth) { | ||
71 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
|
11 | if (in(stmt, depth)) { |
72 | ✗ | return true; | |
73 | } | ||
74 | |||
75 | 11 | return Super::exec(stmt, depth); | |
76 | } | ||
77 | |||
78 | template <typename T> | ||
79 | bool any_of(Array<T> const& elts, int depth) { | ||
80 | // std::any_of produce so much asm crap in gcc-12 & clang-15 | ||
81 | // zig++ generates fine code though | ||
82 | // msvc generates the worst code by far | ||
83 |
2/2✓ Branch 5 taken 13 times.
✓ Branch 6 taken 9 times.
|
44 | for (auto const& elt: elts) { // NOLINT |
84 |
2/3✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
|
26 | if (exec(elt, depth)) |
85 | ✗ | return true; | |
86 | } | ||
87 | 18 | return false; | |
88 | } | ||
89 | |||
90 | ReturnType exec_body(Array<StmtNode*> const& body, int depth) { return any_of(body, depth); } | ||
91 | |||
92 | ReturnType excepthandler(ExceptHandler const& self, int depth) { | ||
93 | ✗ | if (self.type.has_value()) { | |
94 | ✗ | if (exec(self.type.value(), depth)) | |
95 | ✗ | return true; | |
96 | } | ||
97 | |||
98 | ✗ | return exec(self.comment, depth) || exec_body(self.body, depth + 1); | |
99 | } | ||
100 | |||
101 | ReturnType matchcase(MatchCase const& self, int depth) { | ||
102 | ✗ | if (exec(self.pattern, depth)) { | |
103 | ✗ | return true; | |
104 | } | ||
105 | |||
106 | ✗ | if (self.guard.has_value()) { | |
107 | ✗ | if (exec(self.guard.value(), depth)) | |
108 | ✗ | return true; | |
109 | } | ||
110 | |||
111 | ✗ | return exec(self.comment, depth) || exec_body(self.body, depth + 1); | |
112 | } | ||
113 | |||
114 | bool comprehension(Comprehension const& self, int depth); | ||
115 | bool arguments(Arguments const& self, int depth); | ||
116 | bool withitem(WithItem const& self, int depth); | ||
117 | bool alias(Alias const& self, int depth); | ||
118 | bool keyword(Keyword const& self, int depth); | ||
119 | |||
120 | bool arg(Arg const& self, int depth) { | ||
121 | if (self.annotation.has_value()) { | ||
122 | if (exec(self.annotation.value(), depth)) { | ||
123 | return true; | ||
124 | } | ||
125 | } | ||
126 | return false; | ||
127 | } | ||
128 | |||
129 | #define FUNCTION_GEN(name, fun, rtype) rtype fun(const name* node, int depth); | ||
130 | |||
131 | #define X(name, _) | ||
132 | #define SECTION(name) | ||
133 | #define EXPR(name, fun) FUNCTION_GEN(name, fun, ReturnType) | ||
134 | #define STMT(name, fun) FUNCTION_GEN(name, fun, ReturnType) | ||
135 | #define MOD(name, fun) FUNCTION_GEN(name, fun, ReturnType) | ||
136 | #define MATCH(name, fun) FUNCTION_GEN(name, fun, ReturnType) | ||
137 | |||
138 | NODEKIND_ENUM(X, SECTION, EXPR, STMT, MOD, MATCH) | ||
139 | |||
140 | #undef X | ||
141 | #undef SECTION | ||
142 | #undef EXPR | ||
143 | #undef STMT | ||
144 | #undef MOD | ||
145 | #undef MATCH | ||
146 | |||
147 | #undef FUNCTION_GEN | ||
148 | } LY_ALIGN(32); | ||
149 | |||
150 | ReturnType Circle::attribute(Attribute const* self, int depth) { return exec(self->value, depth); } | ||
151 | |||
152 | ReturnType Circle::subscript(Subscript const* self, int depth) { | ||
153 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
1 | return exec(self->value, depth) || exec(self->slice, depth); |
154 | } | ||
155 | |||
156 | ReturnType Circle::starred(Starred const* self, int depth) { return exec(self->value, depth); } | ||
157 | |||
158 | ReturnType Circle::module(Module const* self, int depth) { return exec_body(self->body, depth); } | ||
159 | |||
160 | ReturnType Circle::raise(Raise const* self, int depth) { | ||
161 | ✗ | if (self->exc.has_value()) { | |
162 | ✗ | if (exec(self->exc.value(), depth)) | |
163 | ✗ | return true; | |
164 | } | ||
165 | |||
166 | ✗ | if (self->cause.has_value()) { | |
167 | ✗ | if (exec(self->cause.value(), depth)) { | |
168 | ✗ | return true; | |
169 | } | ||
170 | } | ||
171 | ✗ | return false; | |
172 | } | ||
173 | |||
174 | ReturnType Circle::assertstmt(Assert const* self, int depth) { | ||
175 | ✗ | if (exec(self->test, depth)) { | |
176 | ✗ | return true; | |
177 | } | ||
178 | |||
179 | ✗ | if (self->msg.has_value()) { | |
180 | ✗ | if (exec(self->msg.value(), depth)) { | |
181 | ✗ | return true; | |
182 | } | ||
183 | } | ||
184 | |||
185 | ✗ | return false; | |
186 | } | ||
187 | |||
188 | ReturnType Circle::with(With const* self, int depth) { | ||
189 | ✗ | for (auto const& item: self->items) { | |
190 | ✗ | if (exec(item.context_expr, depth)) { | |
191 | ✗ | return true; | |
192 | } | ||
193 | |||
194 | ✗ | if (item.optional_vars.has_value()) { | |
195 | ✗ | if (exec(item.optional_vars.value(), depth)) { | |
196 | ✗ | return true; | |
197 | } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | ✗ | return exec(self->comment, depth) || exec_body(self->body, depth + 1); | |
202 | } | ||
203 | |||
204 | ReturnType Circle::import(Import const* self, int depth) { return false; } | ||
205 | |||
206 | ReturnType Circle::importfrom(ImportFrom const* self, int depth) { return false; } | ||
207 | |||
208 | ReturnType Circle::slice(Slice const* self, int depth) { | ||
209 | ✗ | if (self->lower.has_value()) { | |
210 | ✗ | if (exec(self->lower.value(), depth)) { | |
211 | ✗ | return true; | |
212 | } | ||
213 | } | ||
214 | |||
215 | ✗ | if (self->upper.has_value()) { | |
216 | ✗ | if (exec(self->upper.value(), depth)) | |
217 | ✗ | return true; | |
218 | } | ||
219 | |||
220 | ✗ | if (self->step.has_value()) { | |
221 | ✗ | if (exec(self->step.value(), depth)) | |
222 | ✗ | return true; | |
223 | } | ||
224 | ✗ | return false; | |
225 | } | ||
226 | |||
227 | ReturnType Circle::tupleexpr(TupleExpr const* self, int depth) { return any_of(self->elts, depth); } | ||
228 | |||
229 | ReturnType Circle::listexpr(ListExpr const* self, int depth) { return any_of(self->elts, depth); } | ||
230 | |||
231 | ReturnType Circle::setexpr(SetExpr const* self, int depth) { return any_of(self->elts, depth); } | ||
232 | |||
233 | ReturnType Circle::dictexpr(DictExpr const* self, int depth) { | ||
234 | ✗ | for (int i = 0; i < self->keys.size(); i++) { | |
235 | ✗ | if (exec(self->keys[i], depth) || exec(self->values[i], depth)) { | |
236 | ✗ | return true; | |
237 | } | ||
238 | } | ||
239 | ✗ | return false; | |
240 | } | ||
241 | |||
242 | ReturnType Circle::matchvalue(MatchValue const* self, int depth) { | ||
243 | ✗ | return exec(self->value, depth); | |
244 | } | ||
245 | |||
246 | ReturnType Circle::matchsingleton(MatchSingleton const* self, int depth) { return false; } | ||
247 | |||
248 | ReturnType Circle::matchsequence(MatchSequence const* self, int depth) { | ||
249 | ✗ | return any_of(self->patterns, depth); | |
250 | } | ||
251 | |||
252 | ReturnType Circle::matchmapping(MatchMapping const* self, int depth) { | ||
253 | ✗ | for (int i = 0; i < self->keys.size(); i++) { | |
254 | ✗ | if (exec(self->keys[i], depth) || exec(self->patterns[i], depth)) { | |
255 | ✗ | return true; | |
256 | } | ||
257 | } | ||
258 | ✗ | return false; | |
259 | } | ||
260 | |||
261 | ReturnType Circle::matchclass(MatchClass const* self, int depth) { | ||
262 | ✗ | return exec(self->cls, depth) || // | |
263 | ✗ | any_of(self->patterns, depth) || // | |
264 | ✗ | any_of(self->kwd_patterns, depth); | |
265 | } | ||
266 | |||
267 | ReturnType Circle::matchstar(MatchStar const* self, int depth) { return false; } | ||
268 | |||
269 | ReturnType Circle::matchas(MatchAs const* self, int depth) { | ||
270 | ✗ | if (self->pattern.has_value()) { | |
271 | ✗ | if (exec(self->pattern.value(), depth)) { | |
272 | ✗ | return true; | |
273 | } | ||
274 | } | ||
275 | ✗ | return false; | |
276 | } | ||
277 | |||
278 | ReturnType Circle::matchor(MatchOr const* self, int depth) { return any_of(self->patterns, depth); } | ||
279 | |||
280 | ReturnType Circle::ifstmt(If const* self, int depth) { | ||
281 | |||
282 | ✗ | if (exec(self->test, depth) || exec(self->comment, depth) || exec_body(self->body, depth + 1)) { | |
283 | ✗ | return true; | |
284 | } | ||
285 | |||
286 | ✗ | for (int i = 0; i < self->tests.size(); i++) { | |
287 | ✗ | auto const& eliftest = self->tests[i]; | |
288 | ✗ | auto const& elifbody = self->bodies[i]; | |
289 | |||
290 | ✗ | if (exec(eliftest, depth) || exec(self->tests_comment[i], depth) || | |
291 | ✗ | exec_body(elifbody, depth + 1)) { | |
292 | ✗ | return true; | |
293 | } | ||
294 | } | ||
295 | |||
296 | ✗ | if (!self->orelse.empty()) { | |
297 | ✗ | if (exec(self->else_comment, depth) || exec_body(self->orelse, depth + 1)) { | |
298 | ✗ | return true; | |
299 | } | ||
300 | } | ||
301 | ✗ | return false; | |
302 | } | ||
303 | |||
304 | ReturnType Circle::match(Match const* self, int depth) { | ||
305 | ✗ | if (exec(self->subject, depth) || exec(self->comment, depth)) { | |
306 | ✗ | return true; | |
307 | } | ||
308 | |||
309 | ✗ | for (auto& case_: self->cases) { // NOLINT | |
310 | ✗ | if (matchcase(case_, depth + 1)) { | |
311 | ✗ | return true; | |
312 | } | ||
313 | } | ||
314 | ✗ | return false; | |
315 | } | ||
316 | |||
317 | ReturnType Circle::lambda(Lambda const* self, int depth) { | ||
318 | ✗ | return arguments(self->args, depth) || exec(self->body, depth); | |
319 | } | ||
320 | |||
321 | ReturnType Circle::ifexp(IfExp const* self, int depth) { | ||
322 | ✗ | return exec(self->body, depth) || exec(self->test, depth) || exec(self->orelse, depth); | |
323 | } | ||
324 | |||
325 | ReturnType Circle::listcomp(ListComp const* self, int depth) { | ||
326 | ✗ | if (exec(self->elt, depth)) { | |
327 | ✗ | return true; | |
328 | } | ||
329 | |||
330 | ✗ | for (int i = 0; i < self->generators.size(); i++) { | |
331 | ✗ | if (comprehension(self->generators[i], depth)) { | |
332 | ✗ | return true; | |
333 | } | ||
334 | } | ||
335 | ✗ | return false; | |
336 | } | ||
337 | |||
338 | ReturnType Circle::setcomp(SetComp const* self, int depth) { | ||
339 | ✗ | if (exec(self->elt, depth)) { | |
340 | ✗ | return true; | |
341 | } | ||
342 | |||
343 | ✗ | for (int i = 0; i < self->generators.size(); i++) { | |
344 | ✗ | if (comprehension(self->generators[i], depth)) { | |
345 | ✗ | return true; | |
346 | } | ||
347 | } | ||
348 | ✗ | return false; | |
349 | } | ||
350 | |||
351 | ReturnType Circle::generateexpr(GeneratorExp const* self, int depth) { | ||
352 | ✗ | if (exec(self->elt, depth)) { | |
353 | ✗ | return true; | |
354 | } | ||
355 | |||
356 | ✗ | for (int i = 0; i < self->generators.size(); i++) { | |
357 | ✗ | if (comprehension(self->generators[i], depth)) { | |
358 | ✗ | return true; | |
359 | } | ||
360 | } | ||
361 | ✗ | return false; | |
362 | } | ||
363 | |||
364 | ReturnType Circle::dictcomp(DictComp const* self, int depth) { | ||
365 | |||
366 | ✗ | if (exec(self->key, depth) || exec(self->value, depth)) { | |
367 | ✗ | return true; | |
368 | } | ||
369 | |||
370 | ✗ | for (int i = 0; i < self->generators.size(); i++) { | |
371 | ✗ | if (comprehension(self->generators[i], depth)) { | |
372 | ✗ | return true; | |
373 | } | ||
374 | } | ||
375 | ✗ | return false; | |
376 | } | ||
377 | |||
378 | ReturnType Circle::await(Await const* self, int depth) { return exec(self->value, depth); } | ||
379 | |||
380 | ReturnType Circle::yield(Yield const* self, int depth) { | ||
381 | ✗ | return self->value.has_value() && exec(self->value.value(), depth); | |
382 | } | ||
383 | |||
384 | ReturnType Circle::yieldfrom(YieldFrom const* self, int depth) { return exec(self->value, depth); } | ||
385 | |||
386 | ReturnType Circle::call(Call const* self, int depth) { | ||
387 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
|
4 | if (exec(self->func, depth) || any_of(self->args, depth)) { |
388 | ✗ | return true; | |
389 | } | ||
390 | |||
391 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | for (int i = 0; i < self->keywords.size(); i++) { |
392 | ✗ | auto const& key = self->keywords[i]; | |
393 | |||
394 | ✗ | if (exec(key.value, depth)) { | |
395 | ✗ | return true; | |
396 | } | ||
397 | } | ||
398 | |||
399 | 4 | return false; | |
400 | } | ||
401 | |||
402 | ReturnType Circle::constant(Constant const* self, int depth) { return false; } | ||
403 | |||
404 | ReturnType Circle::namedexpr(NamedExpr const* self, int depth) { | ||
405 | ✗ | return exec(self->target, depth) || exec(self->value, depth); | |
406 | } | ||
407 | |||
408 | ReturnType Circle::classdef(ClassDef const* self, int depth) { | ||
409 |
1/2✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
|
1 | for (auto decorator: self->decorator_list) { |
410 | ✗ | if (exec(decorator.expr, depth) || exec(decorator.comment, depth)) { | |
411 | ✗ | return true; | |
412 | } | ||
413 | } | ||
414 | |||
415 |
1/4✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
|
1 | for (auto kw: self->keywords) { // NOLINT |
416 | ✗ | if (exec(kw.value, depth)) { | |
417 | ✗ | return true; | |
418 | } | ||
419 | ✗ | } | |
420 | |||
421 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
|
1 | if (any_of(self->bases, depth) || exec(self->comment, depth)) { |
422 | ✗ | return true; | |
423 | } | ||
424 | |||
425 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
|
1 | if (self->docstring.has_value() && exec(self->docstring.value().comment, depth)) { |
426 | ✗ | return true; | |
427 | } | ||
428 | |||
429 |
2/2✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
|
2 | for (auto& stmt: self->body) { // NOLINT |
430 |
5/8✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
|
1 | if (exec(stmt, depth + 1) || exec(stmt->comment, depth)) { |
431 | ✗ | return true; | |
432 | } | ||
433 | } | ||
434 | 1 | return false; | |
435 | } | ||
436 | |||
437 | ReturnType Circle::functiondef(FunctionDef const* self, int depth) { | ||
438 |
1/2✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
|
2 | for (auto decorator: self->decorator_list) { |
439 | ✗ | if (exec(decorator.expr, depth) || exec(decorator.comment, depth)) { | |
440 | ✗ | return true; | |
441 | } | ||
442 | } | ||
443 | |||
444 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (arguments(self->args, depth)) { |
445 | ✗ | return true; | |
446 | } | ||
447 | |||
448 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
|
2 | if (self->returns.has_value() && exec(self->returns.value(), depth)) { |
449 | ✗ | return true; | |
450 | } | ||
451 | |||
452 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (exec(self->comment, depth)) { |
453 | ✗ | return true; | |
454 | } | ||
455 | |||
456 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
|
2 | if (self->docstring.has_value() && exec(self->docstring.value().comment, depth)) { |
457 | ✗ | return true; | |
458 | } | ||
459 | |||
460 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | return exec_body(self->body, depth + 1) || exec(self->type, depth); |
461 | } | ||
462 | |||
463 | ReturnType Circle::inlinestmt(Inline const* self, int depth) { | ||
464 | ✗ | return exec_body(self->body, depth); | |
465 | } | ||
466 | |||
467 | ReturnType Circle::forstmt(For const* self, int depth) { | ||
468 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
|
1 | if (exec(self->target, depth) || exec(self->iter, depth) || exec(self->comment, depth)) { |
469 | ✗ | return true; | |
470 | } | ||
471 | |||
472 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (exec_body(self->body, depth + 1)) { |
473 | ✗ | return true; | |
474 | } | ||
475 | |||
476 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!self->orelse.empty()) { |
477 | ✗ | if (exec(self->else_comment, depth) || exec_body(self->orelse, depth + 1)) { | |
478 | ✗ | return true; | |
479 | } | ||
480 | } | ||
481 | |||
482 | 1 | return false; | |
483 | } | ||
484 | |||
485 | ReturnType Circle::trystmt(Try const* self, int depth) { | ||
486 | ✗ | if (exec(self->comment, depth) || exec_body(self->body, depth + 1)) { | |
487 | ✗ | return true; | |
488 | } | ||
489 | |||
490 | ✗ | for (auto const& handler: self->handlers) { | |
491 | ✗ | if (excepthandler(handler, depth)) { | |
492 | ✗ | return true; | |
493 | } | ||
494 | } | ||
495 | |||
496 | ✗ | if (!self->orelse.empty()) { | |
497 | ✗ | if (exec(self->else_comment, depth) || exec_body(self->orelse, depth + 1)) { | |
498 | ✗ | return true; | |
499 | } | ||
500 | } | ||
501 | |||
502 | ✗ | if (!self->finalbody.empty()) { | |
503 | |||
504 | ✗ | if (exec(self->finally_comment, depth) || exec_body(self->finalbody, depth + 1)) { | |
505 | ✗ | return true; | |
506 | } | ||
507 | } | ||
508 | |||
509 | ✗ | return false; | |
510 | } | ||
511 | |||
512 | ReturnType Circle::compare(Compare const* self, int depth) { | ||
513 | ✗ | if (exec(self->left, depth)) { | |
514 | ✗ | return true; | |
515 | } | ||
516 | |||
517 | ✗ | int n = int(self->comparators.size()); | |
518 | ✗ | for (int i = 0; i < self->ops.size(); i++) { | |
519 | |||
520 | ✗ | if (i < n && exec(self->comparators[i], depth)) { | |
521 | ✗ | return true; | |
522 | } | ||
523 | } | ||
524 | |||
525 | ✗ | return false; | |
526 | } | ||
527 | |||
528 | ReturnType Circle::binop(BinOp const* self, int depth) { | ||
529 | ✗ | return exec(self->left, depth) || exec(self->right, depth); | |
530 | } | ||
531 | |||
532 | ReturnType Circle::invalidstmt(InvalidStatement const* self, int depth) { return false; } | ||
533 | |||
534 | ReturnType Circle::boolop(BoolOp const* self, int depth) { | ||
535 | |||
536 | ✗ | int m = self->opcount + 1; | |
537 | ✗ | int n = int(self->values.size()); | |
538 | |||
539 | ✗ | for (int i = 0; i < m; i++) { | |
540 | |||
541 | ✗ | if (i < n && exec(self->values[i], depth)) { | |
542 | ✗ | return true; | |
543 | } | ||
544 | } | ||
545 | |||
546 | ✗ | return false; | |
547 | } | ||
548 | |||
549 | ReturnType Circle::unaryop(UnaryOp const* self, int depth) { return exec(self->operand, depth); } | ||
550 | |||
551 | ReturnType Circle::whilestmt(While const* self, int depth) { | ||
552 | ✗ | if (exec(self->test, depth) || exec(self->comment, depth) || exec_body(self->body, depth + 1)) { | |
553 | ✗ | return true; | |
554 | } | ||
555 | |||
556 | ✗ | if (!self->orelse.empty()) { | |
557 | ✗ | return exec(self->else_comment, depth) || exec_body(self->orelse, depth + 1); | |
558 | } | ||
559 | |||
560 | ✗ | return false; | |
561 | } | ||
562 | |||
563 | ReturnType Circle::returnstmt(Return const* self, int depth) { | ||
564 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (self->value.has_value()) { |
565 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (exec(self->value.value(), depth)) { |
566 | ✗ | return true; | |
567 | } | ||
568 | } | ||
569 | |||
570 | 1 | return false; | |
571 | } | ||
572 | |||
573 | ReturnType Circle::deletestmt(Delete const* self, int depth) { | ||
574 | ✗ | for (int i = 0; i < self->targets.size(); i++) { | |
575 | ✗ | if (exec(self->targets[i], depth)) { | |
576 | ✗ | return true; | |
577 | } | ||
578 | } | ||
579 | ✗ | return false; | |
580 | } | ||
581 | |||
582 | ReturnType Circle::augassign(AugAssign const* self, int depth) { | ||
583 | ✗ | return exec(self->target, depth) || exec(self->value, depth); | |
584 | } | ||
585 | |||
586 | ReturnType Circle::assign(Assign const* self, int depth) { | ||
587 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
|
1 | return exec(self->targets[0], depth) || exec(self->value, depth); |
588 | } | ||
589 | |||
590 | ReturnType Circle::annassign(AnnAssign const* self, int depth) { | ||
591 | ✗ | if (exec(self->target, depth) || exec(self->annotation, depth)) { | |
592 | ✗ | return true; | |
593 | } | ||
594 | |||
595 | ✗ | if (self->value.has_value()) { | |
596 | ✗ | if (exec(self->value.value(), depth)) { | |
597 | ✗ | return true; | |
598 | } | ||
599 | } | ||
600 | |||
601 | ✗ | return false; | |
602 | } | ||
603 | |||
604 | ReturnType Circle::pass(Pass const* self, int depth) { return false; } | ||
605 | |||
606 | ReturnType Circle::breakstmt(Break const* self, int depth) { return false; } | ||
607 | |||
608 | ReturnType Circle::continuestmt(Continue const* self, int depth) { return false; } | ||
609 | |||
610 | ReturnType Circle::exprstmt(Expr const* self, int depth) { | ||
611 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (self->value != nullptr) |
612 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if (exec(self->value, depth)) { |
613 | ✗ | return true; | |
614 | } | ||
615 | |||
616 | 3 | return false; | |
617 | } | ||
618 | |||
619 | ReturnType Circle::global(Global const* self, int depth) { return false; } | ||
620 | |||
621 | ReturnType Circle::nonlocal(Nonlocal const* self, int depth) { return false; } | ||
622 | |||
623 | ReturnType Circle::arrow(Arrow const* self, int depth) { | ||
624 |
2/2✓ Branch 5 taken 293 times.
✓ Branch 6 taken 216 times.
|
509 | for (ExprNode* node: self->args) { |
625 |
2/3✓ Branch 1 taken 293 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 293 times.
|
293 | if (exec(node, depth)) { |
626 | ✗ | return true; | |
627 | } | ||
628 | } | ||
629 | 216 | return exec(self->returns, depth); | |
630 | } | ||
631 | |||
632 | ReturnType Circle::dicttype(DictType const* self, int depth) { | ||
633 | ✗ | return exec(self->key, depth) || exec(self->value, depth); | |
634 | } | ||
635 | |||
636 | ReturnType Circle::settype(SetType const* self, int depth) { return false; } | ||
637 | |||
638 | ReturnType Circle::name(Name const* self, int depth) { return false; } | ||
639 | |||
640 | ReturnType Circle::arraytype(ArrayType const* self, int depth) { return exec(self->value, depth); } | ||
641 | |||
642 | ReturnType Circle::tupletype(TupleType const* self, int depth) { | ||
643 | ✗ | return any_of(self->types, depth); | |
644 | } | ||
645 | |||
646 | ReturnType Circle::builtintype(BuiltinType const* self, int depth) { return false; } | ||
647 | |||
648 | ReturnType Circle::joinedstr(JoinedStr const* self, int depth) { return false; } | ||
649 | |||
650 | ReturnType Circle::formattedvalue(FormattedValue const* self, int depth) { return false; } | ||
651 | |||
652 | ReturnType Circle::classtype(ClassType const* self, int depth) { return false; } | ||
653 | |||
654 | // Helper | ||
655 | // ================================================== | ||
656 | |||
657 | bool Circle::comprehension(Comprehension const& self, int depth) { | ||
658 | |||
659 | ✗ | return exec(self.target, depth) || // | |
660 | ✗ | exec(self.iter, depth) || // | |
661 | ✗ | any_of(self.ifs, depth); | |
662 | } | ||
663 | |||
664 | bool Circle::keyword(Keyword const& self, int depth) { | ||
665 | ✗ | return (self.value != nullptr) && exec(self.value, depth); | |
666 | } | ||
667 | |||
668 | bool Circle::alias(Alias const& self, int depth) { return false; } | ||
669 | |||
670 | ReturnType Circle::functiontype(FunctionType const* self, int depth) { return false; } | ||
671 | |||
672 | ReturnType Circle::expression(Expression const* self, int depth) { return false; } | ||
673 | |||
674 | ReturnType Circle::interactive(Interactive const* self, int depth) { return false; } | ||
675 | |||
676 | bool Circle::withitem(WithItem const& self, int depth) { | ||
677 | ✗ | if (exec(self.context_expr, depth)) { | |
678 | ✗ | return true; | |
679 | } | ||
680 | |||
681 | ✗ | if (self.optional_vars.has_value()) { | |
682 | |||
683 | ✗ | if (exec(self.optional_vars.value(), depth)) { | |
684 | ✗ | return true; | |
685 | } | ||
686 | } | ||
687 | |||
688 | ✗ | return false; | |
689 | } | ||
690 | |||
691 | ReturnType Circle::comment(Comment const* n, int depth) { return false; } | ||
692 | |||
693 | bool Circle::arguments(Arguments const& self, int depth) { | ||
694 | 2 | int i = 0; | |
695 | |||
696 |
2/2✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
|
4 | for (auto const& arg: self.args) { |
697 |
2/8✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
|
2 | if (arg.annotation.has_value() && exec(arg.annotation.value(), depth)) { |
698 | ✗ | return true; | |
699 | } | ||
700 | |||
701 | 2 | auto default_offset = self.args.size() - 1 - i; | |
702 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
2 | if (!self.defaults.empty() && default_offset < self.defaults.size()) { |
703 | ✗ | if (exec(self.defaults[default_offset], depth)) { | |
704 | ✗ | return true; | |
705 | } | ||
706 | } | ||
707 | |||
708 | 2 | i += 1; | |
709 | } | ||
710 | |||
711 | 2 | i = 0; | |
712 |
1/2✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | for (auto const& kw: self.kwonlyargs) { |
713 | ✗ | if (kw.annotation.has_value()) { | |
714 | ✗ | if (exec(kw.annotation.value(), depth)) { | |
715 | ✗ | return true; | |
716 | } | ||
717 | } | ||
718 | |||
719 | ✗ | auto default_offset = self.kwonlyargs.size() - 1 - i; | |
720 | ✗ | if (!self.kw_defaults.empty() && default_offset < self.kw_defaults.size()) { | |
721 | ✗ | if (exec(self.kw_defaults[default_offset], depth)) { | |
722 | ✗ | return true; | |
723 | } | ||
724 | } | ||
725 | |||
726 | ✗ | i += 1; | |
727 | } | ||
728 | |||
729 | 2 | return false; | |
730 | } | ||
731 | |||
732 | bool has_circle(ExprNode const* obj) { return Circle().exec(obj, 0); } | ||
733 | bool has_circle(Pattern const* obj) { return Circle().exec(obj, 0); } | ||
734 | bool has_circle(StmtNode const* obj) { return Circle().exec(obj, 0); } | ||
735 | bool has_circle(ModNode const* obj) { return Circle().exec(obj, 0); } | ||
736 | |||
737 | } // namespace lython | ||
738 |