| 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 |