| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "sema/sema.h" | ||
| 2 | #include "ast/magic.h" | ||
| 3 | #include "ast/values/object.h" | ||
| 4 | #include "builtin/operators.h" | ||
| 5 | #include "dependencies/fmt.h" | ||
| 6 | #include "parser/format_spec.h" | ||
| 7 | #include "utilities/guard.h" | ||
| 8 | #include "utilities/strings.h" | ||
| 9 | |||
| 10 | namespace lython { | ||
| 11 | Arrow* get_arrow( | ||
| 12 | SemanticAnalyser* self, ExprNode* fun, ExprNode* type, int depth, int& offset, ClassDef*& cls); | ||
| 13 | |||
| 14 | bool SemanticAnalyser::add_name(ExprNode* expr, ExprNode* value, ExprNode* type) { | ||
| 15 | 73 | auto* name = cast<Name>(expr); | |
| 16 | |||
| 17 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | if (name != nullptr) { |
| 18 | 73 | name->ctx = ExprContext::Store; | |
| 19 | 73 | bindings.add(name->id, value, type); | |
| 20 | 73 | return true; | |
| 21 | } | ||
| 22 | |||
| 23 | ✗ | return false; | |
| 24 | } | ||
| 25 | |||
| 26 | bool SemanticAnalyser::typecheck( | ||
| 27 | ExprNode* lhs, TypeExpr* lhs_t, ExprNode* rhs, TypeExpr* rhs_t, CodeLocation const& loc) { | ||
| 28 | |||
| 29 |
3/4✓ Branch 0 taken 452 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 452 times.
✗ Branch 3 not taken.
|
489 | if (lhs_t != nullptr && rhs_t != nullptr) { |
| 30 |
1/1✓ Branch 1 taken 452 times.
|
452 | lython::log(lython::LogLevel::Debug, |
| 31 | loc, | ||
| 32 | "lhs_t: {} kind {} rhs_t: {} kind:{}", | ||
| 33 | 452 | str(lhs_t), | |
| 34 |
1/1✓ Branch 1 taken 452 times.
|
452 | lhs_t->kind, |
| 35 | 452 | str(rhs_t), | |
| 36 |
1/1✓ Branch 1 taken 452 times.
|
452 | rhs_t->kind); |
| 37 | } | ||
| 38 | |||
| 39 | 489 | auto match = equal(lhs_t, rhs_t); | |
| 40 | |||
| 41 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 468 times.
|
489 | if (!match) { |
| 42 | SEMA_ERROR(lhs, TypeError, lhs, lhs_t, rhs, rhs_t, loc); | ||
| 43 | } | ||
| 44 | 489 | return match; | |
| 45 | } | ||
| 46 | |||
| 47 | bool SemanticAnalyser::is_type(TypeExpr* type, int depth, lython::CodeLocation const& loc) { | ||
| 48 | 241 | TypeExpr* value_t_t = exec(type, depth); | |
| 49 | |||
| 50 | 241 | return typecheck(type, // int | |
| 51 | value_t_t, // Type | ||
| 52 | nullptr, // | ||
| 53 | Type_t(), // Type | ||
| 54 | 241 | loc); | |
| 55 | } | ||
| 56 | |||
| 57 | Tuple<ClassDef*, FunctionDef*> | ||
| 58 | SemanticAnalyser::find_method(TypeExpr* class_type, String const& methodname, int depth) { | ||
| 59 | ✗ | ClassDef* cls = get_class(class_type, depth); | |
| 60 | |||
| 61 | ✗ | if (cls == nullptr) { | |
| 62 | ✗ | return std::make_tuple(nullptr, nullptr); | |
| 63 | } | ||
| 64 | |||
| 65 | ✗ | TypeExpr* op_type = nullptr; | |
| 66 | |||
| 67 | ✗ | return std::make_tuple(cls, cast<FunctionDef>(getattr(cls, methodname, op_type))); | |
| 68 | } | ||
| 69 | |||
| 70 | // classname.__and__ | ||
| 71 | String SemanticAnalyser::operator_function(TypeExpr* expr_t, StringRef op) { | ||
| 72 | 22 | auto* cls_ref = cast<Name>(expr_t); | |
| 73 | 22 | ClassDef* expr_cls = cast<ClassDef>(load_name(cls_ref)); | |
| 74 | |||
| 75 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 20 times.
|
22 | if (expr_cls != nullptr) { |
| 76 |
6/8✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 8 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 15 taken 4 times.
✓ Branch 16 taken 2 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
8 | return join(".", Array<String>{expr_cls->cls_namespace, String(StringView(op))}); |
| 77 | } | ||
| 78 | |||
| 79 |
1/1✓ Branch 2 taken 20 times.
|
20 | return ""; |
| 80 | 6 | } | |
| 81 | |||
| 82 | TypeExpr* SemanticAnalyser::boolop(BoolOp* n, int depth) { | ||
| 83 |
2/2✓ Branch 2 taken 10 times.
✓ Branch 5 taken 10 times.
|
10 | auto* bool_type = make_ref(n, "bool"); |
| 84 | 10 | bool and_implemented = false; | |
| 85 | 10 | bool rand_implemented = false; | |
| 86 | 10 | auto* return_t = bool_type; | |
| 87 | |||
| 88 |
1/1✓ Branch 1 taken 10 times.
|
10 | StringRef magic = operator_magic_name(n->op, false); |
| 89 |
1/1✓ Branch 1 taken 10 times.
|
10 | StringRef rmagic = operator_magic_name(n->op, true); |
| 90 | |||
| 91 | // TODO: what about inheritance ? | ||
| 92 | 10 | ExprNode* lhs = n->values[0]; | |
| 93 |
1/1✓ Branch 1 taken 10 times.
|
10 | TypeExpr* lhs_t = exec(lhs, depth); |
| 94 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 4 taken 10 times.
|
10 | String lhs_op = operator_function(lhs_t, magic); |
| 95 | |||
| 96 | 10 | ExprNode* rhs = nullptr; | |
| 97 | 10 | TypeExpr* rhs_t = nullptr; | |
| 98 | 10 | String rhs_op; | |
| 99 | |||
| 100 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 10 times.
|
22 | for (int i = 1; i < n->values.size(); i++) { |
| 101 | 12 | rhs = n->values[i]; | |
| 102 |
1/1✓ Branch 1 taken 12 times.
|
12 | rhs_t = exec(rhs, depth); |
| 103 | |||
| 104 |
5/7✓ Branch 1 taken 12 times.
✓ Branch 5 taken 12 times.
✓ Branch 8 taken 12 times.
✓ Branch 12 taken 36 times.
✓ Branch 13 taken 12 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
48 | String signature = join("-", Array<String>{str(n->op), str(lhs_t), str(rhs_t)}); |
| 105 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 4 taken 12 times.
|
12 | auto handler = get_native_bool_operation(signature); |
| 106 | |||
| 107 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | if (handler) { |
| 108 | 6 | n->native_operator = handler; | |
| 109 | } else { | ||
| 110 | // Not a native operator | ||
| 111 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
|
6 | int lhs_op_varid = bindings.get_varid(lhs_op); |
| 112 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
|
6 | if (lhs_op_varid > 0) { |
| 113 | // found the function we are calling | ||
| 114 | 1 | n->varid = lhs_op_varid; | |
| 115 | |||
| 116 |
1/1✓ Branch 2 taken 1 times.
|
1 | Arrow* operator_type = cast<Arrow>(bindings.get_type(lhs_op_varid)); |
| 117 | |||
| 118 | assert(operator_type, "Bool operator needs to be Callable"); | ||
| 119 | assert(operator_type->args.size() == 2, "Bool operator requires 2 arguments"); | ||
| 120 | |||
| 121 | typecheck(lhs, lhs_t, nullptr, operator_type->args[0], LOC); | ||
| 122 | typecheck(rhs, rhs_t, nullptr, operator_type->args[1], LOC); | ||
| 123 | typecheck(nullptr, operator_type->returns, nullptr, make_ref(n, "bool"), LOC); | ||
| 124 | } else { | ||
| 125 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
|
5 | int rhs_op_varid = bindings.get_varid(rhs_op); |
| 126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (rhs_op_varid > 0) { |
| 127 | // found the function we are calling | ||
| 128 | ✗ | n->varid = rhs_op_varid; | |
| 129 | |||
| 130 | ✗ | Arrow* operator_type = cast<Arrow>(bindings.get_type(rhs_op_varid)); | |
| 131 | |||
| 132 | assert(operator_type, "Bool operator needs to be Callable"); | ||
| 133 | assert(operator_type->args.size() == 2, "Bool operator requires 2 arguments"); | ||
| 134 | |||
| 135 | typecheck(lhs, lhs_t, nullptr, operator_type->args[1], LOC); | ||
| 136 | typecheck(rhs, rhs_t, nullptr, operator_type->args[0], LOC); | ||
| 137 | typecheck(nullptr, operator_type->returns, nullptr, make_ref(n, "bool"), LOC); | ||
| 138 | } | ||
| 139 | |||
| 140 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (lhs_op_varid == -1 && rhs_op_varid == -1) { |
| 141 | SEMA_ERROR(n, UnsupportedOperand, str(n->op), lhs_t, rhs_t); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | 12 | lhs_t = rhs_t; | |
| 147 | 12 | lhs = rhs; | |
| 148 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 4 taken 12 times.
|
12 | lhs_op = operator_function(lhs_t, magic); |
| 149 | |||
| 150 | /* | ||
| 151 | // | ||
| 152 | // TODO: we could create a builtin file that define | ||
| 153 | // bool as a class that has the __and__ attribute | ||
| 154 | // that would harmonize this code | ||
| 155 | // | ||
| 156 | // if not a bool we need to check for | ||
| 157 | // * __and__ inside the lhs | ||
| 158 | // * __rand__ inside the rhs | ||
| 159 | if (!equal(lhs_t, bool_type)) { | ||
| 160 | |||
| 161 | ClassDef* cls = nullptr; | ||
| 162 | FunctionDef* fun = nullptr; | ||
| 163 | |||
| 164 | std::tie(cls, fun) = find_method(lhs_t, magic); | ||
| 165 | |||
| 166 | if (fun == nullptr) { | ||
| 167 | SEMA_ERROR(UnsupportedOperand(str(n->op), lhs_t, rhs_t)); | ||
| 168 | return nullptr; | ||
| 169 | } | ||
| 170 | |||
| 171 | // This is a standard call now | ||
| 172 | auto arrow_expr = exec(fun, depth); | ||
| 173 | auto arrow = cast<Arrow>(arrow_expr); | ||
| 174 | |||
| 175 | // Generate the Call Arrow | ||
| 176 | auto got = n->new_object<Arrow>(); | ||
| 177 | got->args.push_back(make_ref(got, str(cls->name))); // lhs_t | ||
| 178 | got->args.push_back(rhs_t); | ||
| 179 | got->returns = arrow->returns; | ||
| 180 | |||
| 181 | typecheck(n, got, nullptr, arrow, LOC); | ||
| 182 | lhs_t = arrow->returns; | ||
| 183 | } | ||
| 184 | */ | ||
| 185 | 12 | } | |
| 186 | |||
| 187 | 10 | return return_t; | |
| 188 | 22 | } | |
| 189 | TypeExpr* SemanticAnalyser::namedexpr(NamedExpr* n, int depth) { | ||
| 190 | 2 | auto* value_t = exec(n->value, depth); | |
| 191 | 2 | add_name(n->target, n->value, value_t); | |
| 192 | 2 | return value_t; | |
| 193 | } | ||
| 194 | |||
| 195 | TypeExpr* SemanticAnalyser::resolve_variable(ExprNode* node) { | ||
| 196 | |||
| 197 | 37 | Name* name = cast<Name>(node); | |
| 198 | |||
| 199 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 20 times.
|
37 | if (name != nullptr) { |
| 200 | assert(name->varid >= 0, "Type need to be resolved"); | ||
| 201 | 17 | return static_cast<TypeExpr*>(bindings.get_value(name->varid)); | |
| 202 | } | ||
| 203 | |||
| 204 | 20 | return nullptr; | |
| 205 | } | ||
| 206 | |||
| 207 | TypeExpr* SemanticAnalyser::compare(Compare* n, int depth) { | ||
| 208 | |||
| 209 |
1/1✓ Branch 1 taken 35 times.
|
35 | auto* prev_t = exec(n->left, depth); |
| 210 | 35 | auto* prev = n->left; | |
| 211 | |||
| 212 |
2/2✓ Branch 1 taken 45 times.
✓ Branch 2 taken 35 times.
|
80 | for (int i = 0; i < n->ops.size(); i++) { |
| 213 | 45 | auto op = n->ops[i]; | |
| 214 | 45 | auto* cmp = n->comparators[i]; | |
| 215 |
1/1✓ Branch 1 taken 45 times.
|
45 | auto* cmp_t = exec(cmp, depth); |
| 216 | |||
| 217 | // Check if we have a native function to handle this | ||
| 218 |
5/7✓ Branch 1 taken 45 times.
✓ Branch 5 taken 45 times.
✓ Branch 8 taken 45 times.
✓ Branch 12 taken 135 times.
✓ Branch 13 taken 45 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
180 | String signature = join(String("-"), Array<String>{str(op), str(prev_t), str(cmp_t)}); |
| 219 | |||
| 220 | // TODO: get return type | ||
| 221 |
2/2✓ Branch 1 taken 45 times.
✓ Branch 4 taken 45 times.
|
45 | auto handler = get_native_cmp_operation(signature); |
| 222 |
1/1✓ Branch 1 taken 45 times.
|
45 | n->native_operator.push_back(handler); |
| 223 | |||
| 224 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23 times.
|
45 | if (!handler) { |
| 225 | SEMA_ERROR(n, UnsupportedOperand, str(op), prev_t, cmp_t); | ||
| 226 | } | ||
| 227 | // | ||
| 228 | // prev <op> cmp | ||
| 229 | |||
| 230 | // TODO: typecheck op | ||
| 231 | // op: (prev_t -> cmp_t -> bool) | ||
| 232 | |||
| 233 | // -- | ||
| 234 | 45 | prev = cmp; | |
| 235 | 45 | prev_t = cmp_t; | |
| 236 | 45 | } | |
| 237 | |||
| 238 |
2/2✓ Branch 2 taken 35 times.
✓ Branch 5 taken 35 times.
|
35 | return make_ref(n, "bool"); |
| 239 | 45 | } | |
| 240 | |||
| 241 | TypeExpr* SemanticAnalyser::binop(BinOp* n, int depth) { | ||
| 242 | |||
| 243 |
1/1✓ Branch 1 taken 37 times.
|
37 | auto* lhs_t = exec(n->left, depth); |
| 244 |
1/1✓ Branch 1 taken 37 times.
|
37 | auto* rhs_t = exec(n->right, depth); |
| 245 | |||
| 246 | typecheck(n->left, lhs_t, n->right, rhs_t, LOC); | ||
| 247 | |||
| 248 |
1/1✓ Branch 1 taken 37 times.
|
37 | TypeExpr* type = resolve_variable(lhs_t); |
| 249 |
1/1✓ Branch 1 taken 37 times.
|
37 | BuiltinType* blt = cast<BuiltinType>(type); |
| 250 | |||
| 251 | // Builtin type, all the operations are known | ||
| 252 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 20 times.
|
37 | if (blt) { |
| 253 |
6/9✓ Branch 1 taken 17 times.
✓ Branch 5 taken 17 times.
✓ Branch 8 taken 17 times.
✓ Branch 12 taken 51 times.
✓ Branch 13 taken 17 times.
✓ Branch 15 taken 17 times.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
|
68 | String signature = join(String("-"), Array<String>{str(n->op), str(lhs_t), str(rhs_t)}); |
| 254 | |||
| 255 | kwdebug("signature: {}", signature); | ||
| 256 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 4 taken 17 times.
|
17 | n->native_operator = get_native_binary_operation(signature); |
| 257 | |||
| 258 | // FIXME: get return type | ||
| 259 | 17 | return lhs_t; | |
| 260 | 17 | } else { | |
| 261 | // TODO: Not a builtin type, so it is user defined | ||
| 262 | // need to check for a magic method that overload the right operator | ||
| 263 | |||
| 264 | // Get the return value of the custom operator | ||
| 265 | 20 | return lhs_t; | |
| 266 | } | ||
| 267 | |||
| 268 | // TODO: check that op is defined for those types | ||
| 269 | // use the op return type here | ||
| 270 | return lhs_t; | ||
| 271 | 17 | } | |
| 272 | TypeExpr* SemanticAnalyser::unaryop(UnaryOp* n, int depth) { | ||
| 273 |
1/1✓ Branch 1 taken 11 times.
|
11 | auto* expr_t = exec(n->operand, depth); |
| 274 | |||
| 275 |
5/7✓ Branch 1 taken 11 times.
✓ Branch 5 taken 11 times.
✓ Branch 8 taken 11 times.
✓ Branch 12 taken 22 times.
✓ Branch 13 taken 11 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
33 | String signature = join("-", Array<String>{str(n->op), str(expr_t)}); |
| 276 | |||
| 277 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 4 taken 11 times.
|
11 | UnaryOp::NativeUnaryOp handler = get_native_unary_operation(signature); |
| 278 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
|
11 | if (!handler) { |
| 279 | SEMA_ERROR(n, UnsupportedOperand, str(n->op), expr_t, nullptr); | ||
| 280 | } | ||
| 281 | |||
| 282 | // assert(handler != nullptr, "Unary operation require native handler"); | ||
| 283 | 11 | n->native_operator = handler; | |
| 284 | |||
| 285 | // TODO: fetch native operator | ||
| 286 | // TODO: check that op is defined for this type | ||
| 287 | // use the op return type here | ||
| 288 | 11 | return expr_t; | |
| 289 | 22 | } | |
| 290 | TypeExpr* SemanticAnalyser::lambda(Lambda* n, int depth) { | ||
| 291 | 2 | Scope scope(bindings); | |
| 292 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* funtype = n->new_object<Arrow>(); |
| 293 |
1/1✓ Branch 1 taken 2 times.
|
2 | add_arguments(n->args, funtype, nullptr, depth); |
| 294 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* type = exec(n->body, depth); |
| 295 | 2 | funtype->returns = type; | |
| 296 | 2 | return funtype; | |
| 297 | 2 | } | |
| 298 | TypeExpr* SemanticAnalyser::ifexp(IfExp* n, int depth) { | ||
| 299 | 3 | auto* test_t = exec(n->test, depth); | |
| 300 | |||
| 301 | typecheck(n->test, test_t, nullptr, make_ref(n, "bool"), LOC); | ||
| 302 | 3 | auto* body_t = exec(n->body, depth); | |
| 303 | 3 | auto* orelse_t = exec(n->orelse, depth); | |
| 304 | |||
| 305 | typecheck(nullptr, body_t, nullptr, orelse_t, LOC); | ||
| 306 | 3 | return body_t; | |
| 307 | } | ||
| 308 | TypeExpr* SemanticAnalyser::dictexpr(DictExpr* n, int depth) { | ||
| 309 | 5 | TypeExpr* key_t = nullptr; | |
| 310 | 5 | TypeExpr* val_t = nullptr; | |
| 311 | |||
| 312 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 5 times.
|
15 | for (int i = 0; i < n->keys.size(); i++) { |
| 313 | 10 | auto* key_type = exec(n->keys[i], depth); | |
| 314 | 10 | auto* val_type = exec(n->values[i], depth); | |
| 315 | |||
| 316 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
10 | if (key_t != nullptr && val_t != nullptr) { |
| 317 | typecheck(n->keys[i], key_type, nullptr, key_t, LOC); | ||
| 318 | typecheck(n->values[i], val_type, nullptr, val_t, LOC); | ||
| 319 | 3 | } else { | |
| 320 | 7 | key_t = key_type; | |
| 321 | 7 | val_t = val_type; | |
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | 5 | DictType* type = n->new_object<DictType>(); | |
| 326 | 5 | type->key = key_t; | |
| 327 | 5 | type->value = val_t; | |
| 328 | 5 | return type; | |
| 329 | } | ||
| 330 | TypeExpr* SemanticAnalyser::setexpr(SetExpr* n, int depth) { | ||
| 331 | 5 | TypeExpr* val_t = nullptr; | |
| 332 | |||
| 333 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 5 times.
|
15 | for (int i = 0; i < n->elts.size(); i++) { |
| 334 | 10 | auto* val_type = exec(n->elts[i], depth); | |
| 335 | |||
| 336 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
|
10 | if (val_t != nullptr) { |
| 337 | typecheck(n->elts[i], val_type, nullptr, val_t, LOC); | ||
| 338 | } else { | ||
| 339 | 7 | val_t = val_type; | |
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | 5 | SetType* type = n->new_object<SetType>(); | |
| 344 | 5 | type->value = val_t; | |
| 345 | 5 | return type; | |
| 346 | } | ||
| 347 | TypeExpr* SemanticAnalyser::listcomp(ListComp* n, int depth) { | ||
| 348 | 2 | Scope scope(bindings); | |
| 349 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto& gen: n->generators) { |
| 350 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(gen.target, depth); |
| 351 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(gen.iter, depth); |
| 352 | |||
| 353 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto* if_: gen.ifs) { |
| 354 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(if_, depth); |
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 358 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* val_type = exec(n->elt, depth); |
| 359 | |||
| 360 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* type = n->new_object<ArrayType>(); |
| 361 | 2 | type->value = val_type; | |
| 362 | 2 | return type; | |
| 363 | 2 | } | |
| 364 | TypeExpr* SemanticAnalyser::generateexpr(GeneratorExp* n, int depth) { | ||
| 365 | 2 | Scope scope(bindings); | |
| 366 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto& gen: n->generators) { |
| 367 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(gen.target, depth); |
| 368 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(gen.iter, depth); |
| 369 | |||
| 370 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto* if_: gen.ifs) { |
| 371 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(if_, depth); |
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* val_type = exec(n->elt, depth); |
| 376 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* type = n->new_object<ArrayType>(); |
| 377 | 2 | type->value = val_type; | |
| 378 | 2 | return type; | |
| 379 | 2 | } | |
| 380 | TypeExpr* SemanticAnalyser::setcomp(SetComp* n, int depth) { | ||
| 381 | 2 | Scope scope(bindings); | |
| 382 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto& gen: n->generators) { |
| 383 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(gen.target, depth); |
| 384 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(gen.iter, depth); |
| 385 | |||
| 386 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto* if_: gen.ifs) { |
| 387 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(if_, depth); |
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* val_type = exec(n->elt, depth); |
| 392 | |||
| 393 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* type = n->new_object<ArrayType>(); |
| 394 | 2 | type->value = val_type; | |
| 395 | 2 | return type; | |
| 396 | 2 | } | |
| 397 | |||
| 398 | TypeExpr* SemanticAnalyser::dictcomp(DictComp* n, int depth) { | ||
| 399 | 2 | Scope scope(bindings); | |
| 400 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto& gen: n->generators) { |
| 401 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(gen.target, depth); |
| 402 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(gen.iter, depth); |
| 403 | |||
| 404 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto* if_: gen.ifs) { |
| 405 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(if_, depth); |
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* key_type = exec(n->key, depth); |
| 410 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* val_type = exec(n->value, depth); |
| 411 | |||
| 412 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* type = n->new_object<DictType>(); |
| 413 | 2 | type->key = key_type; | |
| 414 | 2 | type->value = val_type; | |
| 415 | 2 | return type; | |
| 416 | 2 | } | |
| 417 | TypeExpr* SemanticAnalyser::await(Await* n, int depth) { return exec(n->value, depth); } | ||
| 418 | TypeExpr* SemanticAnalyser::yield(Yield* n, int depth) { | ||
| 419 | 6 | get_context().yield = true; | |
| 420 | |||
| 421 |
1/1✓ Branch 1 taken 6 times.
|
6 | auto r = exec<TypeExpr*>(n->value, depth); |
| 422 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
|
6 | if (r.has_value()) { |
| 423 | 2 | return r.value(); | |
| 424 | } | ||
| 425 | 4 | return nullptr; | |
| 426 | 6 | } | |
| 427 | TypeExpr* SemanticAnalyser::yieldfrom(YieldFrom* n, int depth) { return exec(n->value, depth); } | ||
| 428 | |||
| 429 | // def fun(a: int, b:int) -> float: | ||
| 430 | // pass | ||
| 431 | // | ||
| 432 | // Arrow1: (int, int) -> float | ||
| 433 | // | ||
| 434 | // Arrow2: (typeof(arg1), typeof(arg2)) -> .. | ||
| 435 | // | ||
| 436 | // <fun>(arg1 arg2 ...) | ||
| 437 | // | ||
| 438 | |||
| 439 | Node* SemanticAnalyser::load_name(Name_t* n) { | ||
| 440 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 38 times.
|
45 | if (n == nullptr) { |
| 441 | 7 | return nullptr; | |
| 442 | } | ||
| 443 | |||
| 444 | 38 | Node* result = nullptr; | |
| 445 | 38 | int varid = 0; | |
| 446 | |||
| 447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (n->dynamic) { |
| 448 | // Local variables | Arguments | ||
| 449 | assert(n->offset != -1, "Reference should have a reverse lookup offset"); | ||
| 450 | ✗ | varid = int(bindings.bindings.size()) - n->offset; | |
| 451 | ✗ | result = bindings.get_value(varid); | |
| 452 | } else { | ||
| 453 | // Global variables | ||
| 454 | 38 | result = bindings.get_value(n->varid); | |
| 455 | } | ||
| 456 | |||
| 457 | 38 | return result; | |
| 458 | } | ||
| 459 | |||
| 460 | ClassDef* SemanticAnalyser::get_class(ExprNode* classref, int depth) { | ||
| 461 | 29 | auto* cls_name = cast<Name>(classref); | |
| 462 | |||
| 463 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 23 times.
|
29 | if (!cls_name) { |
| 464 | 6 | return nullptr; | |
| 465 | } | ||
| 466 | |||
| 467 | 23 | cls_name->ctx = ExprContext::Load; | |
| 468 | // assert(cls_name->ctx == ExprContext::Load, "Reference to the class should be loaded"); | ||
| 469 | 23 | auto* cls = cast<ClassDef>(load_name(cls_name)); | |
| 470 | |||
| 471 | 23 | return cls; | |
| 472 | } | ||
| 473 | |||
| 474 | Arrow* | ||
| 475 | SemanticAnalyser::get_arrow(ExprNode* fun, ExprNode* type, int depth, int& offset, ClassDef*& cls) { | ||
| 476 | |||
| 477 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 79 times.
|
91 | if (type == nullptr) { |
| 478 | 12 | return nullptr; | |
| 479 | } | ||
| 480 | |||
| 481 |
2/3✓ Branch 0 taken 71 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
79 | switch (type->kind) { |
| 482 | 71 | case NodeKind::Arrow: { | |
| 483 | 71 | offset = 0; | |
| 484 | 71 | return cast<Arrow>(type); | |
| 485 | } | ||
| 486 | 8 | case NodeKind::BuiltinType: { | |
| 487 |
3/4✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
|
8 | if (!equal(type, Type_t())) { |
| 488 | ✗ | return nullptr; | |
| 489 | } | ||
| 490 | |||
| 491 | // Fetch the class type inside the binding | ||
| 492 |
1/1✓ Branch 1 taken 8 times.
|
8 | cls = get_class(fun, depth); |
| 493 | |||
| 494 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (cls == nullptr) { |
| 495 | kwwarn("Could not resolve class"); | ||
| 496 | ✗ | return nullptr; | |
| 497 | } | ||
| 498 | 8 | TypeExpr* arrow = nullptr; | |
| 499 | |||
| 500 | // The methods were added to the context outside of the class itself | ||
| 501 | // here we need to resolve the method which is inside the context | ||
| 502 | |||
| 503 | // NOTE: we should call __new__ here implictly | ||
| 504 | // | ||
| 505 | |||
| 506 |
3/3✓ Branch 2 taken 8 times.
✓ Branch 6 taken 8 times.
✓ Branch 9 taken 8 times.
|
8 | String ctor_name = String(cls->name) + String(".__init__"); |
| 507 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
|
8 | int ctorvarid = bindings.get_varid(ctor_name); |
| 508 | 8 | Node* ctor = bindings.get_value(ctorvarid); | |
| 509 | |||
| 510 | // Now we can switch the function being called from being the class | ||
| 511 | // to being the constructor of the class | ||
| 512 | assert(fun->kind == NodeKind::Name, "Expect a reference to the class"); | ||
| 513 | |||
| 514 | // --update the ref to point to the constructor if we found it-- | ||
| 515 | // We should not do that, we need the class definition to know | ||
| 516 | // the size of the object | ||
| 517 | /* | ||
| 518 | Name* fun_ref = cast<Name>(fun); | ||
| 519 | if (fun_ref != nullptr && ctorvarid != -1) { | ||
| 520 | fun_ref->varid = ctorvarid; | ||
| 521 | fun_ref->size = int(bindings.bindings.size()) - fun_ref->varid; | ||
| 522 | fun_ref->dynamic = bindings.is_dynamic(fun_ref->varid); | ||
| 523 | } else { | ||
| 524 | kwwarn("Constructor was not found"); | ||
| 525 | } | ||
| 526 | */ | ||
| 527 | |||
| 528 |
1/1✓ Branch 1 taken 8 times.
|
8 | FunctionDef* init = cast<FunctionDef>(ctor); |
| 529 | // auto init = getattr(cls, "__init__", arrow); | ||
| 530 | 8 | offset = 1; | |
| 531 | |||
| 532 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (init == nullptr) { |
| 533 | kwdebug("Use default ctor"); | ||
| 534 |
1/1✓ Branch 1 taken 4 times.
|
4 | auto* cls_ref = make_ref(fun, cls->name); |
| 535 |
1/1✓ Branch 1 taken 4 times.
|
4 | Arrow* arrow = fun->new_object<Arrow>(); |
| 536 |
1/1✓ Branch 1 taken 4 times.
|
4 | arrow->add_arg_type(cls_ref); |
| 537 | 4 | arrow->returns = cls_ref; | |
| 538 | 4 | return arrow; | |
| 539 | } else { | ||
| 540 | // ctor should already have been sema'ed | ||
| 541 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (init->type != nullptr) { |
| 542 | 4 | return init->type; | |
| 543 | } | ||
| 544 | |||
| 545 | // if not then we are doing it right now and this is a circle | ||
| 546 | SEMA_ERROR(fun, RecursiveDefinition, "", fun, cls); | ||
| 547 | ✗ | return nullptr; | |
| 548 | } | ||
| 549 | 8 | } | |
| 550 | ✗ | default: break; | |
| 551 | } | ||
| 552 | ✗ | return nullptr; | |
| 553 | } | ||
| 554 | |||
| 555 | TypeExpr* SemanticAnalyser::call(Call* n, int depth) { | ||
| 556 | // Get the type of the function | ||
| 557 |
1/1✓ Branch 1 taken 91 times.
|
91 | auto* type = exec(n->func, depth); |
| 558 | |||
| 559 | 91 | int offset = 0; | |
| 560 | 91 | ClassDef* cls = nullptr; | |
| 561 |
1/1✓ Branch 1 taken 91 times.
|
91 | auto* arrow = get_arrow(n->func, type, depth, offset, cls); |
| 562 | |||
| 563 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 79 times.
|
91 | if (arrow == nullptr) { |
| 564 | SEMA_ERROR(n, TypeError, fmt::format("{} is not callable", str(n->func))); | ||
| 565 | } | ||
| 566 | |||
| 567 | // Sort kwargs to make them positional | ||
| 568 | // Get Arguments and generate an arrow from it | ||
| 569 | |||
| 570 | // Create the matching Arrow type for this call | ||
| 571 |
1/1✓ Branch 1 taken 91 times.
|
91 | Arrow* got = n->new_object<Arrow>(); |
| 572 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 12 times.
|
91 | if (arrow != nullptr) { |
| 573 |
1/1✓ Branch 2 taken 79 times.
|
79 | got->args.reserve(arrow->arg_count()); |
| 574 | } | ||
| 575 | |||
| 576 | // Method, insert the self argument since it is implicit | ||
| 577 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 83 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
91 | if (offset == 1 && cls) { |
| 578 |
3/3✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
✓ Branch 7 taken 8 times.
|
8 | got->add_arg_type(make_ref(got, str(cls->name))); |
| 579 | } | ||
| 580 | |||
| 581 |
2/2✓ Branch 5 taken 51 times.
✓ Branch 6 taken 91 times.
|
142 | for (auto& arg: n->args) { |
| 582 |
2/2✓ Branch 1 taken 51 times.
✓ Branch 4 taken 51 times.
|
51 | got->add_arg_type(exec(arg, depth)); |
| 583 | } | ||
| 584 | |||
| 585 | 91 | Dict<StringRef, ExprNode*> kwargs; | |
| 586 |
2/2✓ Branch 4 taken 7 times.
✓ Branch 5 taken 91 times.
|
98 | for (auto& kw: n->keywords) { |
| 587 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
|
7 | kwargs[kw.arg] = exec(kw.value, depth); |
| 588 | } | ||
| 589 | |||
| 590 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 12 times.
|
91 | if (arrow != nullptr) { |
| 591 |
2/2✓ Branch 2 taken 32 times.
✓ Branch 3 taken 79 times.
|
111 | for (int i = int(got->arg_count()); i < arrow->names.size(); i++) { |
| 592 |
1/1✓ Branch 2 taken 32 times.
|
32 | auto name = arrow->names[i]; |
| 593 | |||
| 594 |
1/1✓ Branch 1 taken 32 times.
|
32 | auto item = kwargs.find(name); |
| 595 |
2/2✓ Branch 2 taken 30 times.
✓ Branch 3 taken 2 times.
|
32 | if (item == kwargs.end()) { |
| 596 |
1/1✓ Branch 1 taken 30 times.
|
30 | auto value = got->defaults[name]; |
| 597 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
|
30 | if (value) { |
| 598 | SEMA_ERROR(n, TypeError, fmt::format("Arguement {} is not set", name)); | ||
| 599 | } | ||
| 600 | // Got default use the expected type | ||
| 601 |
1/1✓ Branch 2 taken 30 times.
|
30 | got->add_arg_type(arrow->args[i]); |
| 602 | 30 | continue; | |
| 603 | 30 | } | |
| 604 | |||
| 605 |
1/1✓ Branch 2 taken 2 times.
|
2 | got->add_arg_type(item->second); |
| 606 | 32 | } | |
| 607 | } | ||
| 608 | |||
| 609 | // FIXME: we do not know the returns so we just use the one we have | ||
| 610 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 12 times.
|
91 | if (arrow != nullptr) { |
| 611 | 79 | if (got->arg_count() != arrow->arg_count()) { | |
| 612 | // we do not really that check | ||
| 613 | // SEMA_ERROR(TypeError(" missing {} required positional arguments")); | ||
| 614 | // | ||
| 615 | } | ||
| 616 | |||
| 617 | 79 | got->returns = arrow->returns; | |
| 618 | typecheck(n, got, n->func, arrow, LOC); | ||
| 619 | } | ||
| 620 | |||
| 621 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 12 times.
|
91 | if (arrow != nullptr) { |
| 622 | 79 | return arrow->returns; | |
| 623 | } | ||
| 624 | 12 | return nullptr; | |
| 625 | 91 | } | |
| 626 | TypeExpr* SemanticAnalyser::joinedstr(JoinedStr* n, int depth) { | ||
| 627 |
2/2✓ Branch 5 taken 7 times.
✓ Branch 6 taken 3 times.
|
10 | for (auto* value: n->values) { |
| 628 |
1/1✓ Branch 1 taken 7 times.
|
7 | exec(value, depth); |
| 629 | } | ||
| 630 |
2/2✓ Branch 2 taken 3 times.
✓ Branch 5 taken 3 times.
|
3 | return make_ref(n, "str"); |
| 631 | } | ||
| 632 | TypeExpr* SemanticAnalyser::formattedvalue(FormattedValue* n, int depth) { | ||
| 633 | 3 | TypeExpr* vtype = exec(n->value, depth); | |
| 634 | |||
| 635 | // Objects are able to define their own format specifiers to replace the standard ones | ||
| 636 | // [[fill]align][sign][#][0][minimumwidth][.precision][type] | ||
| 637 | // < + # 0 [0-9]* .[0-9]* b e | ||
| 638 | // > - c E | ||
| 639 | // = ' ' d f | ||
| 640 | // ^ o F | ||
| 641 | // x g | ||
| 642 | // X G | ||
| 643 | // n n | ||
| 644 | // None % | ||
| 645 | // | ||
| 646 | // Conversion flag | ||
| 647 | // !r {0!s:20} | ||
| 648 | // !s {0!r:20} | ||
| 649 | // | ||
| 650 | // class object: | ||
| 651 | // def __format__(self, format_spec): | ||
| 652 | // return format(str(self), format_spec) | ||
| 653 | // | ||
| 654 | // https://peps.python.org/pep-3101/ | ||
| 655 | |||
| 656 | // Here checking the type of the format spec is probably not the priority | ||
| 657 | // but validating the format spec | ||
| 658 | // the sinple case is if there is a single format_spec | ||
| 659 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
|
3 | if (n->format_spec->values.size() == 1) { |
| 660 | 1 | Constant* cst = cast<Constant>(n->format_spec->values[0]); | |
| 661 | |||
| 662 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (cst != nullptr) { |
| 663 |
1/1✓ Branch 2 taken 1 times.
|
1 | String strspec = cst->value.get<String>(); |
| 664 |
1/1✓ Branch 1 taken 1 times.
|
1 | FormatSpecifier spec = FormatSpecifier::parse(strspec); |
| 665 | |||
| 666 | // FIXME: this should a SEMA error | ||
| 667 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!spec.valid) { |
| 668 | kwdebug("Format spec is not valid; parsed {} unparsed string: `{}`", // | ||
| 669 | spec.__repr__(), // | ||
| 670 | spec.unparsed // | ||
| 671 | ); | ||
| 672 | } | ||
| 673 | |||
| 674 |
1/1✓ Branch 1 taken 1 times.
|
1 | if (spec.is_float()) { |
| 675 | // TODO | ||
| 676 | // check that vtype is double or float | ||
| 677 | } | ||
| 678 | |||
| 679 |
1/1✓ Branch 1 taken 1 times.
|
1 | if (spec.is_integer()) { |
| 680 | // TODO | ||
| 681 | // check that vtype is an integer | ||
| 682 | } | ||
| 683 | 1 | } | |
| 684 | } | ||
| 685 | |||
| 686 | // I think if there is more that means the spec is dynamic | ||
| 687 | // then we are limited in our ability to validate it | ||
| 688 | // we probably can extract the type it if it is defined the rest | ||
| 689 | // will remain undefined | ||
| 690 |
2/2✓ Branch 5 taken 5 times.
✓ Branch 6 taken 3 times.
|
8 | for (auto* value: n->format_spec->values) { |
| 691 |
1/1✓ Branch 1 taken 5 times.
|
5 | Constant* cst = cast<Constant>(value); |
| 692 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if (cst != nullptr) { |
| 693 | // Partial format spec | ||
| 694 | } else { | ||
| 695 | // Can we use the type here to guess which | ||
| 696 | // part of the format spec this will fill out ? | ||
| 697 |
1/1✓ Branch 1 taken 2 times.
|
2 | TypeExpr* etype = exec(value, depth); |
| 698 | } | ||
| 699 | } | ||
| 700 | |||
| 701 | 3 | return nullptr; | |
| 702 | } | ||
| 703 | TypeExpr* SemanticAnalyser::constant(Constant* n, int depth) { | ||
| 704 |
5/13✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 163 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 27 times.
✓ Branch 11 taken 20 times.
✓ Branch 12 taken 20 times.
✓ Branch 13 taken 2 times.
|
232 | switch (n->value.type()) { |
| 705 | ✗ | case ConstantValue::Ti8: return make_ref(n, "i8"); | |
| 706 | ✗ | case ConstantValue::Ti16: return make_ref(n, "i16"); | |
| 707 |
2/2✓ Branch 2 taken 163 times.
✓ Branch 5 taken 163 times.
|
163 | case ConstantValue::Ti32: return make_ref(n, "i32"); |
| 708 | ✗ | case ConstantValue::Ti64: return make_ref(n, "i64"); | |
| 709 | |||
| 710 | ✗ | case ConstantValue::Tu8: return make_ref(n, "u8"); | |
| 711 | ✗ | case ConstantValue::Tu16: return make_ref(n, "u16"); | |
| 712 | ✗ | case ConstantValue::Tu32: return make_ref(n, "u32"); | |
| 713 | ✗ | case ConstantValue::Tu64: return make_ref(n, "u64"); | |
| 714 | |||
| 715 | ✗ | case ConstantValue::Tf32: return make_ref(n, "f32"); | |
| 716 |
2/2✓ Branch 2 taken 27 times.
✓ Branch 5 taken 27 times.
|
27 | case ConstantValue::Tf64: return make_ref(n, "f64"); |
| 717 |
2/2✓ Branch 2 taken 20 times.
✓ Branch 5 taken 20 times.
|
20 | case ConstantValue::TString: return make_ref(n, "str"); |
| 718 |
2/2✓ Branch 2 taken 20 times.
✓ Branch 5 taken 20 times.
|
20 | case ConstantValue::TBool: return make_ref(n, "bool"); |
| 719 | 2 | default: return nullptr; | |
| 720 | } | ||
| 721 | |||
| 722 | return nullptr; | ||
| 723 | } | ||
| 724 | |||
| 725 | // This is only called when loading | ||
| 726 | TypeExpr* SemanticAnalyser::attribute(Attribute* n, int depth) { | ||
| 727 | // <value>.<name> | ||
| 728 | 10 | auto* type_t = exec(n->value, depth); | |
| 729 | 10 | auto* class_t = get_class(type_t, depth); | |
| 730 | |||
| 731 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
|
10 | if (class_t == nullptr) { |
| 732 | // class was not found, this is probably because the lookup | ||
| 733 | // of the value failed, it should have produced a precise error | ||
| 734 | // so we do not have to | ||
| 735 | // SEMA_ERROR(NameError(n->value, str(n->value))); | ||
| 736 | 6 | return nullptr; | |
| 737 | } | ||
| 738 | |||
| 739 |
1/1✓ Branch 1 taken 4 times.
|
4 | n->attrid = class_t->get_attribute(n->attr); |
| 740 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (n->attrid == -1) { |
| 741 | SEMA_ERROR(n, AttributeError, class_t, n->attr); | ||
| 742 | 1 | return nullptr; | |
| 743 | } | ||
| 744 | |||
| 745 | 3 | ClassDef::Attr& attr = class_t->attributes[n->attrid]; | |
| 746 | |||
| 747 | if (attr.type != nullptr && is_type(attr.type, depth, LOC)) { | ||
| 748 | 3 | return attr.type; | |
| 749 | } | ||
| 750 | ✗ | return nullptr; | |
| 751 | } | ||
| 752 | |||
| 753 | TypeExpr* SemanticAnalyser::attribute_assign(Attribute* n, int depth, TypeExpr* expected) { | ||
| 754 | // self: Ref[class_t] | ||
| 755 | 11 | auto* type_t = exec(n->value, depth); | |
| 756 | 11 | auto* class_t = get_class(type_t, depth); | |
| 757 | |||
| 758 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (class_t == nullptr) { |
| 759 | SEMA_ERROR(n, NameError, n->value, str(n->value)); | ||
| 760 | ✗ | return nullptr; | |
| 761 | } | ||
| 762 | |||
| 763 |
1/1✓ Branch 1 taken 11 times.
|
11 | n->attrid = class_t->get_attribute(n->attr); |
| 764 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
|
11 | if (n->attrid == -1) { |
| 765 | SEMA_ERROR(n, AttributeError, class_t, n->attr); | ||
| 766 | 1 | return nullptr; | |
| 767 | } | ||
| 768 | |||
| 769 | // Update attribute type when we are in an assignment | ||
| 770 | 10 | ClassDef::Attr& attr = class_t->attributes[n->attrid]; | |
| 771 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
10 | if (n->attrid > 0 && attr.type == nullptr) { |
| 772 | ✗ | attr.type = expected; | |
| 773 | } | ||
| 774 | |||
| 775 | if (attr.type != nullptr && is_type(attr.type, depth, LOC)) { | ||
| 776 | 10 | return attr.type; | |
| 777 | } | ||
| 778 | ✗ | return nullptr; | |
| 779 | } | ||
| 780 | |||
| 781 | TypeExpr* SemanticAnalyser::subscript(Subscript* n, int depth) { | ||
| 782 | 5 | auto* class_t = exec(n->value, depth); | |
| 783 | 5 | exec(n->slice, depth); | |
| 784 | // check that __getitem__ is defined in class_t | ||
| 785 | 5 | return nullptr; | |
| 786 | } | ||
| 787 | TypeExpr* SemanticAnalyser::starred(Starred* n, int depth) { | ||
| 788 | // value should be of an expandable type | ||
| 789 | 2 | auto* value_t = exec(n->value, depth); | |
| 790 | 2 | return nullptr; | |
| 791 | } | ||
| 792 | TypeExpr* SemanticAnalyser::name(Name* n, int depth) { | ||
| 793 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 706 times.
|
742 | if (n->ctx == ExprContext::Store) { |
| 794 |
1/1✓ Branch 1 taken 36 times.
|
36 | auto id = bindings.add(n->id, n, nullptr); |
| 795 | 36 | n->varid = id; | |
| 796 | 36 | n->size = int(bindings.bindings.size()); | |
| 797 | |||
| 798 | kwdebug("Storing value for {} ({})", n->id, n->varid); | ||
| 799 | } else { | ||
| 800 | // Both delete & Load requires the variable to be defined first | ||
| 801 |
2/2✓ Branch 1 taken 706 times.
✓ Branch 4 taken 706 times.
|
706 | n->varid = bindings.get_varid(n->id); |
| 802 | 706 | n->size = int(bindings.bindings.size()); | |
| 803 | 706 | n->offset = int(bindings.bindings.size()) - n->varid; | |
| 804 | 706 | n->dynamic = bindings.is_dynamic(n->varid); | |
| 805 | |||
| 806 |
2/2✓ Branch 0 taken 239 times.
✓ Branch 1 taken 467 times.
|
706 | if (n->varid == -1) { |
| 807 | kwdebug("Value {} not found", n->id); | ||
| 808 | SEMA_ERROR(n, NameError, n, n->id); | ||
| 809 | } | ||
| 810 | } | ||
| 811 | |||
| 812 | // assert(n->varid != -1, "Should have been founds"); | ||
| 813 | |||
| 814 | 742 | auto* t = bindings.get_type(n->varid); | |
| 815 |
2/2✓ Branch 0 taken 327 times.
✓ Branch 1 taken 415 times.
|
742 | if (t == nullptr) { |
| 816 | kwdebug("Value {} does not have a type", n->id); | ||
| 817 | } else { | ||
| 818 | kwdebug("Loading value {}: {} of type {}", n->id, n->varid, str(t)); | ||
| 819 | } | ||
| 820 | 742 | return t; | |
| 821 | } | ||
| 822 | |||
| 823 | TypeExpr* SemanticAnalyser::comment(Comment* n, int depth) { return nullptr; } | ||
| 824 | |||
| 825 | TypeExpr* SemanticAnalyser::listexpr(ListExpr* n, int depth) { | ||
| 826 | 5 | TypeExpr* val_t = nullptr; | |
| 827 | |||
| 828 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 5 times.
|
17 | for (int i = 0; i < n->elts.size(); i++) { |
| 829 | 12 | auto* val_type = exec(n->elts[i], depth); | |
| 830 | |||
| 831 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | if (val_type == nullptr) { |
| 832 | // FIXME Could not find tyep for n->elts[i] | ||
| 833 | } else if (val_t == nullptr && is_type(val_type, depth, LOC)) { | ||
| 834 | 3 | val_t = val_type; | |
| 835 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | } else if (val_t != nullptr) { |
| 836 | typecheck(n->elts[i], val_type, nullptr, val_t, LOC); | ||
| 837 | } | ||
| 838 | } | ||
| 839 | |||
| 840 | 5 | ArrayType* type = n->new_object<ArrayType>(); | |
| 841 | 5 | type->value = val_t; | |
| 842 | 5 | return type; | |
| 843 | } | ||
| 844 | TypeExpr* SemanticAnalyser::tupleexpr(TupleExpr* n, int depth) { | ||
| 845 | 17 | TupleType* type = n->new_object<TupleType>(); | |
| 846 | 17 | type->types.reserve(n->elts.size()); | |
| 847 | |||
| 848 |
2/2✓ Branch 1 taken 44 times.
✓ Branch 2 taken 17 times.
|
61 | for (int i = 0; i < n->elts.size(); i++) { |
| 849 |
1/1✓ Branch 2 taken 44 times.
|
44 | TypeExpr* val_t = exec(n->elts[i], depth); |
| 850 | |||
| 851 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 21 times.
|
44 | if (val_t == nullptr) { |
| 852 | // FIXME Could not find tyep for n->elts[i] | ||
| 853 | |||
| 854 | } else if (!is_type(val_t, depth, LOC)) { | ||
| 855 | ✗ | val_t = nullptr; | |
| 856 | } | ||
| 857 | |||
| 858 |
1/1✓ Branch 1 taken 44 times.
|
44 | type->types.push_back(val_t); |
| 859 | } | ||
| 860 | |||
| 861 | 17 | return type; | |
| 862 | } | ||
| 863 | TypeExpr* SemanticAnalyser::slice(Slice* n, int depth) { | ||
| 864 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec<TypeExpr*>(n->lower, depth); |
| 865 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec<TypeExpr*>(n->upper, depth); |
| 866 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec<TypeExpr*>(n->step, depth); |
| 867 | 4 | return nullptr; | |
| 868 | } | ||
| 869 | |||
| 870 | // name : annotation = value | ||
| 871 | // void SemanticAnalyser::add_argument( | ||
| 872 | // Identifier const& name, TypeExpr* annotation, ExprNode* value, Arrow* arrow, int depth) { | ||
| 873 | |||
| 874 | // TypeExpr* value_t = exec(value, depth); | ||
| 875 | |||
| 876 | // } | ||
| 877 | |||
| 878 | void SemanticAnalyser::add_arguments(Arguments& args, Arrow* arrow, ClassDef* def, int depth) { | ||
| 879 | 135 | TypeExpr* class_t = nullptr; | |
| 880 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 121 times.
|
135 | if (def != nullptr) { |
| 881 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 4 taken 14 times.
|
14 | class_t = make_ref(arrow, str(def->name)); |
| 882 | } | ||
| 883 | |||
| 884 | auto resolve_argument = [&](TypeExpr* annotation, ExprNode* value) -> TypeExpr* { | ||
| 885 | 111 | TypeExpr* value_t = nullptr; | |
| 886 | 111 | bool value_t_valid = false; | |
| 887 | 111 | bool ann_valid = false; | |
| 888 | |||
| 889 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 102 times.
|
111 | if (value != nullptr) { |
| 890 | 9 | value_t = exec(value, depth); // Infer the type of the value | |
| 891 | |||
| 892 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
|
9 | if (value_t == nullptr) { |
| 893 | // FXIME: Could not find type for value | ||
| 894 | } else { | ||
| 895 | value_t_valid = is_type(value_t, depth, LOC); | ||
| 896 | } | ||
| 897 | } | ||
| 898 | |||
| 899 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 27 times.
|
111 | if (annotation != nullptr) { |
| 900 | ann_valid = is_type(annotation, depth, LOC); | ||
| 901 | } | ||
| 902 | |||
| 903 |
4/4✓ Branch 0 taken 79 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 74 times.
|
111 | if (ann_valid && value_t_valid) { |
| 904 | typecheck(nullptr, annotation, value, value_t, LOC); | ||
| 905 | } | ||
| 906 | |||
| 907 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 32 times.
|
111 | if (ann_valid) { |
| 908 | 79 | return annotation; | |
| 909 | } | ||
| 910 | |||
| 911 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (value_t_valid) { |
| 912 | ✗ | return value_t; | |
| 913 | } | ||
| 914 | |||
| 915 | 32 | return nullptr; | |
| 916 | 135 | }; | |
| 917 | |||
| 918 |
2/2✓ Branch 1 taken 109 times.
✓ Branch 2 taken 135 times.
|
244 | for (int i = 0, n = int(args.args.size()); i < n; i++) { |
| 919 |
1/1✓ Branch 2 taken 109 times.
|
109 | Arg arg = args.args[i]; |
| 920 | |||
| 921 | 109 | ExprNode* value = nullptr; | |
| 922 |
2/2✓ Branch 1 taken 84 times.
✓ Branch 2 taken 25 times.
|
109 | ExprNode* annotation = arg.annotation.has_value() ? arg.annotation.value() : nullptr; |
| 923 | |||
| 924 | 109 | int d = int(args.defaults.size()) - (n - i); | |
| 925 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 102 times.
|
109 | if (d >= 0) { |
| 926 | 7 | value = args.defaults[d]; | |
| 927 |
1/1✓ Branch 1 taken 7 times.
|
7 | arrow->defaults[arg.arg] = true; |
| 928 | } | ||
| 929 | |||
| 930 |
1/1✓ Branch 1 taken 109 times.
|
109 | TypeExpr* type = resolve_argument(annotation, value); |
| 931 | |||
| 932 | // if it is a method populate the type of self | ||
| 933 | // TODO: fix for staticmethod & class methods | ||
| 934 |
4/4✓ Branch 0 taken 27 times.
✓ Branch 1 taken 82 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 13 times.
|
109 | if (class_t != nullptr && i == 0) { |
| 935 | kwdebug("Insert class type"); | ||
| 936 | 14 | type = class_t; | |
| 937 | } | ||
| 938 | |||
| 939 | // we could populate the default value here | ||
| 940 | // but we would not want sema to think this is a constant | ||
| 941 |
1/1✓ Branch 1 taken 109 times.
|
109 | bindings.add(arg.arg, nullptr, type); |
| 942 | |||
| 943 |
1/2✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
|
109 | if (arrow != nullptr) { |
| 944 |
1/1✓ Branch 1 taken 109 times.
|
109 | arrow->names.push_back(arg.arg); |
| 945 | |||
| 946 |
2/3✓ Branch 1 taken 109 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 109 times.
|
109 | if (!arrow->add_arg_type(type)) { |
| 947 | SEMA_ERROR( | ||
| 948 | arrow, TypeError, fmt::format("Cannot have a function type refer to itself")); | ||
| 949 | } | ||
| 950 | } | ||
| 951 | 109 | } | |
| 952 | |||
| 953 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 135 times.
|
137 | for (int i = 0, n = int(args.kwonlyargs.size()); i < n; i++) { |
| 954 |
1/1✓ Branch 2 taken 2 times.
|
2 | auto arg = args.kwonlyargs[i]; |
| 955 | |||
| 956 | 2 | ExprNode* value = nullptr; | |
| 957 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | ExprNode* annotation = arg.annotation.has_value() ? arg.annotation.value() : nullptr; |
| 958 | |||
| 959 | 2 | int d = int(args.kw_defaults.size()) - (n - i); | |
| 960 | |||
| 961 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (d >= 0) { |
| 962 | 2 | value = args.kw_defaults[d]; | |
| 963 |
1/1✓ Branch 1 taken 2 times.
|
2 | arrow->defaults[arg.arg] = true; |
| 964 | } | ||
| 965 | |||
| 966 |
1/1✓ Branch 1 taken 2 times.
|
2 | TypeExpr* type = resolve_argument(annotation, value); |
| 967 | |||
| 968 |
1/1✓ Branch 1 taken 2 times.
|
2 | bindings.add(arg.arg, nullptr, type); |
| 969 | |||
| 970 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (arrow != nullptr) { |
| 971 |
1/1✓ Branch 1 taken 2 times.
|
2 | arrow->names.push_back(arg.arg); |
| 972 |
2/3✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!arrow->add_arg_type(type)) { |
| 973 | SEMA_ERROR( | ||
| 974 | arrow, TypeError, fmt::format("Cannot have a function type refer to itself")); | ||
| 975 | } | ||
| 976 | } | ||
| 977 | 2 | } | |
| 978 | 135 | } | |
| 979 | |||
| 980 | Arrow* SemanticAnalyser::functiondef_arrow(FunctionDef* n, StmtNode* class_t, int depth) { | ||
| 981 | 127 | Arrow* type = n->new_object<Arrow>(); | |
| 982 | |||
| 983 | { | ||
| 984 |
1/1✓ Branch 1 taken 127 times.
|
127 | PopGuard ctx(semactx, SemaContext{false, true}); |
| 985 | |||
| 986 |
2/2✓ Branch 1 taken 55 times.
✓ Branch 2 taken 72 times.
|
127 | if (n->returns.has_value()) { |
| 987 | 55 | auto* return_t = n->returns.value(); | |
| 988 | |||
| 989 | if (is_type(return_t, depth, LOC)) { | ||
| 990 | 55 | type->returns = n->returns.value(); | |
| 991 | } | ||
| 992 | } | ||
| 993 | |||
| 994 | // The arguments will be rolled back | ||
| 995 | |||
| 996 |
2/2✓ Branch 1 taken 127 times.
✓ Branch 4 taken 127 times.
|
127 | add_arguments(n->args, type, cast<ClassDef>(class_t), depth); |
| 997 | // -- | ||
| 998 | 127 | } | |
| 999 | |||
| 1000 | 127 | return type; | |
| 1001 | } | ||
| 1002 | |||
| 1003 | String SemanticAnalyser::generate_function_name(FunctionDef* n) { | ||
| 1004 | // Generate the function name | ||
| 1005 |
1/1✓ Branch 2 taken 127 times.
|
127 | String funname = String(n->name); |
| 1006 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 119 times.
|
127 | if (namespaces.size() > 0) { |
| 1007 |
3/4✓ Branch 2 taken 8 times.
✓ Branch 5 taken 8 times.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
|
8 | String cls_namespace = join(".", namespaces); |
| 1008 |
1/1✓ Branch 1 taken 8 times.
|
8 | funname = fmtstr("{}.{}", cls_namespace, funname); |
| 1009 | 8 | } | |
| 1010 | |||
| 1011 | 127 | return funname; | |
| 1012 | ✗ | } | |
| 1013 | |||
| 1014 | Array<TypeExpr*> SemanticAnalyser::exec_body(Array<StmtNode*>& body, int depth) { | ||
| 1015 | |||
| 1016 | 127 | Array<TypeExpr*> types; | |
| 1017 |
2/2✓ Branch 5 taken 162 times.
✓ Branch 6 taken 127 times.
|
289 | for (auto* stmt: body) { |
| 1018 |
1/1✓ Branch 1 taken 162 times.
|
162 | TypeExpr* tp = exec(stmt, depth); |
| 1019 |
2/2✓ Branch 0 taken 137 times.
✓ Branch 1 taken 25 times.
|
162 | if (tp != nullptr) { |
| 1020 |
1/1✓ Branch 1 taken 137 times.
|
137 | types.push_back(tp); |
| 1021 | } | ||
| 1022 | } | ||
| 1023 | 127 | return types; | |
| 1024 | ✗ | } | |
| 1025 | |||
| 1026 | TypeExpr* SemanticAnalyser::functiondef(FunctionDef* n, int depth) { | ||
| 1027 | // if sema was already done on the function | ||
| 1028 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
|
127 | if (n->type) { |
| 1029 | kwinfo("Send cached type {}", str(n->type)); | ||
| 1030 | ✗ | return n->type; | |
| 1031 | } | ||
| 1032 | |||
| 1033 |
1/1✓ Branch 1 taken 127 times.
|
127 | String funname = generate_function_name(n); |
| 1034 | |||
| 1035 |
2/2✓ Branch 1 taken 127 times.
✓ Branch 4 taken 127 times.
|
127 | PopGuard _(namespaces, str(n->name)); |
| 1036 |
1/1✓ Branch 1 taken 127 times.
|
127 | PopGuard nested_stmt(nested, (StmtNode*)n); |
| 1037 | 127 | StmtNode* lst = nested_stmt.last(1, nullptr); | |
| 1038 | |||
| 1039 | // Insert the function into the global context | ||
| 1040 | // the arrow type is not created right away to prevent | ||
| 1041 | // circular typing | ||
| 1042 |
2/2✓ Branch 1 taken 127 times.
✓ Branch 4 taken 127 times.
|
127 | auto id = bindings.add(funname, n, nullptr); |
| 1043 | |||
| 1044 | // Enter function context | ||
| 1045 | 127 | Scope scope(bindings); | |
| 1046 | |||
| 1047 | // Create the function type from the arguments | ||
| 1048 | // this will also add the arguments to the context | ||
| 1049 |
1/1✓ Branch 1 taken 127 times.
|
127 | Arrow* fun_type = functiondef_arrow(n, lst, depth); |
| 1050 | 127 | TypeExpr* return_t = fun_type->returns; | |
| 1051 | |||
| 1052 | // Update the function type at the very end | ||
| 1053 | 127 | bindings.set_type(id, fun_type); | |
| 1054 | |||
| 1055 | // Infer return type from the body | ||
| 1056 |
1/1✓ Branch 2 taken 127 times.
|
127 | PopGuard ctx(semactx, SemaContext()); |
| 1057 |
1/1✓ Branch 1 taken 127 times.
|
127 | auto return_effective = exec_body(n->body, depth); |
| 1058 | |||
| 1059 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 72 times.
|
127 | if (return_t != nullptr) { |
| 1060 | // Annotated type takes precedence | ||
| 1061 |
1/1✓ Branch 2 taken 55 times.
|
55 | typecheck(nullptr, // lhs |
| 1062 | return_t, // lhs_t | ||
| 1063 | nullptr, // rhs | ||
| 1064 | oneof(return_effective), // rhs_t | ||
| 1065 | LOC); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | // do decorator last since we need to know our function signature to | ||
| 1069 | // typecheck them | ||
| 1070 |
2/2✓ Branch 4 taken 6 times.
✓ Branch 5 taken 127 times.
|
133 | for (auto decorator: n->decorator_list) { |
| 1071 |
1/1✓ Branch 1 taken 6 times.
|
6 | auto* deco_t = exec(decorator.expr, depth); |
| 1072 | // TODO check the signature here | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | 127 | n->type = fun_type; | |
| 1076 | 127 | n->generator = get_context().yield; | |
| 1077 | 127 | return fun_type; | |
| 1078 | 127 | } | |
| 1079 | |||
| 1080 | void SemanticAnalyser::record_attributes(ClassDef* n, | ||
| 1081 | Array<StmtNode*> const& body, | ||
| 1082 | Array<StmtNode*>& methods, | ||
| 1083 | FunctionDef** ctor, | ||
| 1084 | int depth) { | ||
| 1085 | |||
| 1086 |
2/2✓ Branch 5 taken 23 times.
✓ Branch 6 taken 17 times.
|
40 | for (auto& stmt: n->body) { |
| 1087 | 23 | Scope scope(bindings); | |
| 1088 | |||
| 1089 | // Assignment | ||
| 1090 | 23 | ExprNode* target = nullptr; | |
| 1091 | 23 | TypeExpr* target_t = nullptr; | |
| 1092 | |||
| 1093 | 23 | ExprNode* value = nullptr; | |
| 1094 | 23 | TypeExpr* value_t = nullptr; | |
| 1095 | |||
| 1096 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 8 times.
|
23 | switch (stmt->kind) { |
| 1097 | 8 | case NodeKind::FunctionDef: { | |
| 1098 | // Look for special functions | ||
| 1099 |
1/1✓ Branch 1 taken 8 times.
|
8 | auto* fun = cast<FunctionDef>(stmt); |
| 1100 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
|
8 | n->insert_method(fun->name, fun); |
| 1101 | |||
| 1102 |
3/3✓ Branch 1 taken 8 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 2 times.
|
8 | if (str(fun->name) == "__init__") { |
| 1103 | kwinfo("Found ctor"); | ||
| 1104 | 6 | ctor[0] = fun; | |
| 1105 | } else { | ||
| 1106 |
1/1✓ Branch 1 taken 2 times.
|
2 | methods.push_back(stmt); |
| 1107 | } | ||
| 1108 | 8 | continue; | |
| 1109 | 8 | } | |
| 1110 | 2 | case NodeKind::Assign: { | |
| 1111 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* assn = cast<Assign>(stmt); |
| 1112 | 2 | target = assn->targets[0]; | |
| 1113 | 2 | value = assn->value; | |
| 1114 | 2 | break; | |
| 1115 | } | ||
| 1116 | 5 | case NodeKind::AnnAssign: { | |
| 1117 |
1/1✓ Branch 1 taken 5 times.
|
5 | auto* ann = cast<AnnAssign>(stmt); |
| 1118 | 5 | target = ann->target; | |
| 1119 | 5 | value = ann->value.fold(nullptr); | |
| 1120 | target_t = is_type(ann->annotation, depth, LOC) ? ann->annotation : nullptr; | ||
| 1121 | 5 | break; | |
| 1122 | } | ||
| 1123 | default: kwdebug("Unhandled statement {}", str(stmt->kind)); continue; | ||
| 1124 | 8 | } | |
| 1125 | |||
| 1126 |
1/1✓ Branch 1 taken 7 times.
|
7 | auto* name = cast<Name>(target); |
| 1127 | |||
| 1128 | // Not a variable, move on | ||
| 1129 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (name == nullptr) { |
| 1130 | ✗ | continue; | |
| 1131 | } | ||
| 1132 | |||
| 1133 | // try to deduce type fo the value | ||
| 1134 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (value != nullptr) { |
| 1135 |
1/1✓ Branch 1 taken 7 times.
|
7 | value_t = exec(value, depth); |
| 1136 | |||
| 1137 | if (!is_type(value_t, depth, LOC)) { | ||
| 1138 | ✗ | value_t = nullptr; | |
| 1139 | } | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | // if both types are available do a type check | ||
| 1143 |
3/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
7 | if (target_t != nullptr && value_t != nullptr) { |
| 1144 | typecheck(target, target_t, value, value_t, LOC); | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | // insert attribute using the annotation first | ||
| 1148 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 7 times.
✓ Branch 6 taken 7 times.
|
7 | n->insert_attribute(name->id, stmt, target_t != nullptr ? target_t : value_t); |
| 1149 | 23 | } | |
| 1150 | 17 | } | |
| 1151 | |||
| 1152 | void SemanticAnalyser::record_ctor_attributes(ClassDef* n, FunctionDef* ctor, int depth) { | ||
| 1153 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if (ctor->args.args.empty()) { |
| 1154 | kwerror("__init__ without self"); | ||
| 1155 | ✗ | return; | |
| 1156 | } | ||
| 1157 | |||
| 1158 | kwinfo("Looking for attributes inside the ctor"); | ||
| 1159 |
1/1✓ Branch 2 taken 6 times.
|
6 | auto self = ctor->args.args[0].arg; |
| 1160 | |||
| 1161 | // we need the arguments in the scope so we can look them up | ||
| 1162 |
1/1✓ Branch 1 taken 6 times.
|
6 | Arrow arrow; |
| 1163 | |||
| 1164 | 6 | Scope _(bindings); | |
| 1165 |
1/1✓ Branch 1 taken 6 times.
|
6 | add_arguments(ctor->args, &arrow, n, depth); |
| 1166 | |||
| 1167 |
2/2✓ Branch 5 taken 8 times.
✓ Branch 6 taken 6 times.
|
14 | for (auto* stmt: ctor->body) { |
| 1168 | 8 | ExprNode* attr_expr = nullptr; | |
| 1169 | 8 | ExprNode* value = nullptr; | |
| 1170 | 8 | TypeExpr* type = nullptr; | |
| 1171 | |||
| 1172 |
1/3✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
8 | switch (stmt->kind) { |
| 1173 | 8 | case NodeKind::Assign: { | |
| 1174 |
1/1✓ Branch 1 taken 8 times.
|
8 | auto* assn = cast<Assign>(stmt); |
| 1175 | 8 | attr_expr = assn->targets[0]; | |
| 1176 | 8 | value = assn->value; | |
| 1177 | 8 | break; | |
| 1178 | } | ||
| 1179 | ✗ | case NodeKind::AnnAssign: { | |
| 1180 | ✗ | auto* ann = cast<AnnAssign>(stmt); | |
| 1181 | ✗ | attr_expr = ann->target; | |
| 1182 | ✗ | value = ann->value.has_value() ? ann->value.value() : nullptr; | |
| 1183 | ✗ | type = ann->annotation; | |
| 1184 | ✗ | break; | |
| 1185 | } | ||
| 1186 | ✗ | default: break; | |
| 1187 | } | ||
| 1188 | |||
| 1189 | // if stmt is a comment | ||
| 1190 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (attr_expr == nullptr) { |
| 1191 | ✗ | continue; | |
| 1192 | } | ||
| 1193 | |||
| 1194 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (attr_expr->kind != NodeKind::Attribute) { |
| 1195 | ✗ | continue; | |
| 1196 | } | ||
| 1197 | |||
| 1198 |
1/1✓ Branch 1 taken 8 times.
|
8 | auto* attr = cast<Attribute>(attr_expr); |
| 1199 |
1/1✓ Branch 1 taken 8 times.
|
8 | auto* name = cast<Name>(attr->value); |
| 1200 | |||
| 1201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (name == nullptr) { |
| 1202 | ✗ | continue; | |
| 1203 | } | ||
| 1204 | |||
| 1205 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if (name->id != self) { |
| 1206 | ✗ | continue; | |
| 1207 | } | ||
| 1208 | |||
| 1209 | // | ||
| 1210 | // TODO: think about this, sema will reexecute that | ||
| 1211 | // the type should be added else where because we are inside a function | ||
| 1212 | // and we are processing only a subset of statements | ||
| 1213 | // | ||
| 1214 | // TODO: maybe we should nto rely on `sema->exec(ctor, depth)` | ||
| 1215 | // | ||
| 1216 | // Try to guess the attribute type | ||
| 1217 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | if (type == nullptr && value != nullptr) { |
| 1218 |
1/1✓ Branch 1 taken 8 times.
|
8 | type = exec(value, depth); |
| 1219 | |||
| 1220 | if (!is_type(type, depth, LOC)) { | ||
| 1221 | ✗ | type = nullptr; | |
| 1222 | } | ||
| 1223 | } | ||
| 1224 | |||
| 1225 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
|
8 | n->insert_attribute(attr->attr, stmt, type); |
| 1226 | } | ||
| 1227 | 6 | } | |
| 1228 | |||
| 1229 | TypeExpr* SemanticAnalyser::classdef(ClassDef* n, int depth) { | ||
| 1230 |
1/1✓ Branch 1 taken 17 times.
|
17 | PopGuard _(nested, n); |
| 1231 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 4 taken 17 times.
|
17 | PopGuard _n(namespaces, str(n->name)); |
| 1232 | |||
| 1233 | // a class is a new type | ||
| 1234 | // the type of a class is type | ||
| 1235 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 4 taken 17 times.
|
17 | int id = bindings.add(n->name, n, Type_t()); |
| 1236 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 4 taken 17 times.
|
17 | Name* class_t = make_ref(n, str(n->name), id); |
| 1237 | |||
| 1238 | // TODO: go through bases and add their elements | ||
| 1239 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 17 times.
|
19 | for (auto* base: n->bases) { |
| 1240 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(base, depth); |
| 1241 | } | ||
| 1242 | |||
| 1243 | // | ||
| 1244 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 17 times.
|
19 | for (auto& kw: n->keywords) { |
| 1245 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(kw.value, depth); |
| 1246 | } | ||
| 1247 | |||
| 1248 | 17 | Array<StmtNode*> methods; | |
| 1249 | 17 | FunctionDef* ctor = nullptr; | |
| 1250 | |||
| 1251 | // we insert methods as regular functions | ||
| 1252 | // this makes the structure flat and makes lookup O(1) | ||
| 1253 | // instead of possible O(n) if the method is netested n times | ||
| 1254 | |||
| 1255 |
2/2✓ Branch 2 taken 17 times.
✓ Branch 5 taken 17 times.
|
17 | String cls_namespace = join(".", namespaces); |
| 1256 |
1/1✓ Branch 1 taken 17 times.
|
17 | n->cls_namespace = cls_namespace; |
| 1257 | |||
| 1258 | // Do a first pass to look for special methods such as __init__ | ||
| 1259 | // the attributes here are also static | ||
| 1260 |
1/1✓ Branch 1 taken 17 times.
|
17 | record_attributes(n, n->body, methods, &ctor, depth); |
| 1261 | // ----------------------------- | ||
| 1262 | |||
| 1263 | // get __init__ and do a pass to insert its attribute to the class | ||
| 1264 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 11 times.
|
17 | if (ctor != nullptr) { |
| 1265 | // Traverse body to look for our attributes | ||
| 1266 |
1/1✓ Branch 1 taken 6 times.
|
6 | record_ctor_attributes(n, ctor, depth); |
| 1267 | |||
| 1268 | // add the constructor to the context | ||
| 1269 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
|
6 | auto* ctor_t = cast<Arrow>(exec(ctor, depth)); |
| 1270 | |||
| 1271 | // Fix ctor type | ||
| 1272 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
6 | if (ctor_t != nullptr && ctor_t->arg_count() > 0) { |
| 1273 |
1/1✓ Branch 1 taken 6 times.
|
6 | ctor_t->set_arg_type(0, class_t); |
| 1274 | 6 | ctor_t->returns = class_t; | |
| 1275 | } | ||
| 1276 | } | ||
| 1277 | // ----------------------------- | ||
| 1278 | |||
| 1279 | // Process the remaining methods; | ||
| 1280 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 17 times.
|
19 | for (auto& stmt: methods) { |
| 1281 | |||
| 1282 | // fun_t is the arrow that is saved in the context | ||
| 1283 | // populate self type | ||
| 1284 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto* fun = cast<FunctionDef>(stmt); |
| 1285 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
|
2 | auto* fun_t = cast<Arrow>(exec(stmt, depth)); |
| 1286 | |||
| 1287 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | if (fun_t != nullptr && fun_t->arg_count() > 0) { |
| 1288 |
1/1✓ Branch 1 taken 2 times.
|
2 | fun_t->set_arg_type(0, class_t); |
| 1289 | } | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | // ---- | ||
| 1293 | |||
| 1294 |
2/2✓ Branch 4 taken 4 times.
✓ Branch 5 taken 17 times.
|
21 | for (auto deco: n->decorator_list) { |
| 1295 |
1/1✓ Branch 1 taken 4 times.
|
4 | auto* deco_t = exec(deco.expr, depth); |
| 1296 | // TODO: check signature here | ||
| 1297 | } | ||
| 1298 | |||
| 1299 |
1/1✓ Branch 1 taken 17 times.
|
34 | return Type_t(); |
| 1300 | 17 | } | |
| 1301 | |||
| 1302 | TypeExpr* SemanticAnalyser::invalidstmt(InvalidStatement_t* n, int depth) { | ||
| 1303 | // ignore it, parser already showed this error | ||
| 1304 | 1 | return None_t(); | |
| 1305 | } | ||
| 1306 | TypeExpr* SemanticAnalyser::returnstmt(Return* n, int depth) { | ||
| 1307 |
1/1✓ Branch 1 taken 114 times.
|
114 | auto v = exec<TypeExpr*>(n->value, depth); |
| 1308 |
2/2✓ Branch 1 taken 89 times.
✓ Branch 2 taken 25 times.
|
114 | if (v.has_value()) { |
| 1309 | 89 | return v.value(); | |
| 1310 | } | ||
| 1311 |
1/1✓ Branch 1 taken 25 times.
|
25 | return None_t(); |
| 1312 | 114 | } | |
| 1313 | TypeExpr* SemanticAnalyser::deletestmt(Delete* n, int depth) { | ||
| 1314 |
2/2✓ Branch 5 taken 4 times.
✓ Branch 6 taken 2 times.
|
6 | for (auto* target: n->targets) { |
| 1315 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec(target, depth); |
| 1316 | } | ||
| 1317 | 2 | return nullptr; | |
| 1318 | } | ||
| 1319 | TypeExpr* SemanticAnalyser::assign(Assign* n, int depth) { | ||
| 1320 | 68 | auto* type = exec(n->value, depth); | |
| 1321 | |||
| 1322 | // TODO: check if the assigned name already exist or not | ||
| 1323 | // | ||
| 1324 |
1/2✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
|
68 | if (n->targets.size() == 1) { |
| 1325 | 68 | auto* target = n->targets[0]; | |
| 1326 | |||
| 1327 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 16 times.
|
68 | if (target->kind == NodeKind::Name) { |
| 1328 | 52 | add_name(target, n->value, type); | |
| 1329 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
|
16 | } else if (target->kind == NodeKind::Attribute) { |
| 1330 | // Deduce the type of the attribute from the value | ||
| 1331 | 11 | auto* target_t = attribute_assign(cast<Attribute>(n->targets[0]), depth, type); | |
| 1332 | |||
| 1333 | typecheck(target, target_t, n->value, type, LOC); | ||
| 1334 | } else { | ||
| 1335 | kwerror("Assignment to an unsupported expression {}", str(target->kind)); | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | } else { | ||
| 1339 | ✗ | auto* types = cast<TupleType>(type); | |
| 1340 | ✗ | if (types == nullptr) { | |
| 1341 | // TODO: unexpected type | ||
| 1342 | ✗ | return type; | |
| 1343 | } | ||
| 1344 | |||
| 1345 | ✗ | if (types->types.size() != n->targets.size()) { | |
| 1346 | // TODO: Add type mismatch | ||
| 1347 | ✗ | return type; | |
| 1348 | } | ||
| 1349 | |||
| 1350 | ✗ | for (auto i = 0; i < types->types.size(); i++) { | |
| 1351 | ✗ | auto* target = n->targets[0]; | |
| 1352 | ✗ | auto* name = cast<Name>(target); | |
| 1353 | ✗ | auto* type = types->types[0]; | |
| 1354 | |||
| 1355 | ✗ | add_name(n->targets[0], n->value, type); | |
| 1356 | } | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | 68 | return type; | |
| 1360 | } | ||
| 1361 | TypeExpr* SemanticAnalyser::augassign(AugAssign* n, int depth) { | ||
| 1362 |
1/1✓ Branch 1 taken 14 times.
|
14 | auto* expected_type = exec(n->target, depth); |
| 1363 |
1/1✓ Branch 1 taken 14 times.
|
14 | auto* type = exec(n->value, depth); |
| 1364 | |||
| 1365 |
5/7✓ Branch 1 taken 14 times.
✓ Branch 5 taken 14 times.
✓ Branch 8 taken 14 times.
✓ Branch 12 taken 42 times.
✓ Branch 13 taken 14 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
56 | String signature = join("-", Array<String>{str(n->op), str(expected_type), str(type)}); |
| 1366 | |||
| 1367 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 4 taken 14 times.
|
14 | auto handler = get_native_binary_operation(signature); |
| 1368 | 14 | n->native_operator = handler; | |
| 1369 | |||
| 1370 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
|
14 | if (handler == nullptr) { |
| 1371 | SEMA_ERROR(n, UnsupportedOperand, str(n->op), expected_type, type); | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | typecheck(n->value, type, n->target, expected_type, LOC); | ||
| 1375 | 14 | return type; | |
| 1376 | 28 | } | |
| 1377 | |||
| 1378 | //! Annotation takes priority over the deduced type | ||
| 1379 | //! this enbles users to use annotation to debug | ||
| 1380 | TypeExpr* SemanticAnalyser::annassign(AnnAssign* n, int depth) { | ||
| 1381 | 19 | TypeExpr* constraint = n->annotation; | |
| 1382 | bool ann_valid = is_type(n->annotation, depth, LOC); | ||
| 1383 | |||
| 1384 | 19 | ExprNode* value = n->value.fold(nullptr); | |
| 1385 |
1/1✓ Branch 1 taken 19 times.
|
19 | TypeExpr* value_t = exec<TypeExpr*>(n->value, depth).fold(nullptr); |
| 1386 | |||
| 1387 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | if (value != nullptr) { |
| 1388 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | if (value_t == nullptr) { |
| 1389 | // FIXME could not find type for value | ||
| 1390 | } else if (!is_type(value_t, depth, LOC)) { | ||
| 1391 | ✗ | value_t = nullptr; | |
| 1392 | } | ||
| 1393 | } | ||
| 1394 | |||
| 1395 |
2/4✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
|
19 | if (constraint != nullptr && value_t != nullptr) { |
| 1396 | // if we were able to deduce a type from the expression | ||
| 1397 | // make sure it matches the annotation constraint | ||
| 1398 | 19 | typecheck(n->target, // a | |
| 1399 | constraint, // int | ||
| 1400 | value, // 1 | ||
| 1401 | value_t, // int | ||
| 1402 | LOC); | ||
| 1403 | } | ||
| 1404 | |||
| 1405 |
3/4✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 15 times.
|
19 | if (value_t != nullptr && !ann_valid) { |
| 1406 | 4 | constraint = value_t; | |
| 1407 | kwinfo("Could fix annotation here was {} should be {}", str(n->annotation), str(value_t)); | ||
| 1408 | |||
| 1409 | // FIX annotation | ||
| 1410 | if (false) { | ||
| 1411 | n->annotation = value_t; | ||
| 1412 | } | ||
| 1413 | } | ||
| 1414 | |||
| 1415 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | if (n->target->kind == NodeKind::Name) { |
| 1416 |
1/1✓ Branch 1 taken 19 times.
|
19 | add_name(n->target, value, constraint); |
| 1417 | ✗ | } else if (n->target->kind == NodeKind::Attribute) { | |
| 1418 | // if it is an attribute make sure to update its type | ||
| 1419 | ✗ | auto* attr_t = attribute_assign(cast<Attribute>(n->target), depth, constraint); | |
| 1420 | |||
| 1421 | // if attr has no type it will be added | ||
| 1422 | // if attr has a type then we need to check that the assignment type | ||
| 1423 | // matches | ||
| 1424 | typecheck(n->target, attr_t, nullptr, constraint, LOC); | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | 19 | return constraint; | |
| 1428 | } | ||
| 1429 | TypeExpr* SemanticAnalyser::forstmt(For* n, int depth) { | ||
| 1430 |
1/1✓ Branch 1 taken 4 times.
|
4 | auto* iter_t = exec(n->iter, depth); |
| 1431 | |||
| 1432 | // TODO: use iter_t to set target types | ||
| 1433 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec(n->target, depth); |
| 1434 | |||
| 1435 | // TODO: check consistency of return types | ||
| 1436 |
1/1✓ Branch 1 taken 4 times.
|
4 | auto return_t1 = exec<TypeExpr*>(n->body, depth); |
| 1437 |
1/1✓ Branch 1 taken 4 times.
|
4 | auto return_t2 = exec<TypeExpr*>(n->orelse, depth); |
| 1438 | |||
| 1439 |
1/1✓ Branch 1 taken 4 times.
|
8 | return oneof(return_t1); |
| 1440 | 4 | } | |
| 1441 | TypeExpr* SemanticAnalyser::whilestmt(While* n, int depth) { | ||
| 1442 |
1/1✓ Branch 1 taken 7 times.
|
7 | exec(n->test, depth); |
| 1443 |
1/1✓ Branch 1 taken 7 times.
|
7 | exec<TypeExpr*>(n->body, depth); |
| 1444 |
1/1✓ Branch 1 taken 7 times.
|
7 | auto types = exec<TypeExpr*>(n->orelse, depth); |
| 1445 |
1/1✓ Branch 1 taken 7 times.
|
14 | return oneof(types); |
| 1446 | 7 | } | |
| 1447 | TypeExpr* SemanticAnalyser::ifstmt(If* n, int depth) { | ||
| 1448 |
1/1✓ Branch 1 taken 8 times.
|
8 | exec(n->test, depth); |
| 1449 |
1/1✓ Branch 1 taken 8 times.
|
8 | auto types = exec<TypeExpr*>(n->body, depth); |
| 1450 | |||
| 1451 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
|
10 | for (int i = 0; i < n->tests.size(); i++) { |
| 1452 |
1/1✓ Branch 2 taken 2 times.
|
2 | exec(n->tests[i], depth); |
| 1453 |
1/1✓ Branch 2 taken 2 times.
|
2 | exec<TypeExpr*>(n->bodies[i], depth); |
| 1454 | } | ||
| 1455 | |||
| 1456 |
1/1✓ Branch 1 taken 8 times.
|
16 | return oneof(types); |
| 1457 | 8 | } | |
| 1458 | TypeExpr* SemanticAnalyser::with(With* n, int depth) { | ||
| 1459 |
2/2✓ Branch 5 taken 8 times.
✓ Branch 6 taken 4 times.
|
12 | for (auto& item: n->items) { |
| 1460 |
1/1✓ Branch 1 taken 8 times.
|
8 | auto* type = exec(item.context_expr, depth); |
| 1461 | |||
| 1462 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | if (item.optional_vars.has_value()) { |
| 1463 | 8 | auto* expr = item.optional_vars.value(); | |
| 1464 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (expr->kind == NodeKind::Name) { |
| 1465 |
1/1✓ Branch 1 taken 8 times.
|
8 | auto* name = cast<Name>(expr); |
| 1466 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (name != nullptr) { |
| 1467 |
1/1✓ Branch 1 taken 8 times.
|
8 | name->varid = bindings.add(name->id, expr, type); |
| 1468 | } | ||
| 1469 | } else { | ||
| 1470 | // FIXME: is this even possible ? | ||
| 1471 | ✗ | exec(item.optional_vars.value(), depth); | |
| 1472 | } | ||
| 1473 | } | ||
| 1474 | } | ||
| 1475 | |||
| 1476 |
1/1✓ Branch 1 taken 4 times.
|
4 | auto types = exec<TypeExpr*>(n->body, depth); |
| 1477 |
1/1✓ Branch 1 taken 4 times.
|
8 | return oneof(types); |
| 1478 | 4 | } | |
| 1479 | TypeExpr* SemanticAnalyser::raise(Raise* n, int depth) { | ||
| 1480 | // TODO: | ||
| 1481 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec<TypeExpr*>(n->exc, depth); |
| 1482 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec<TypeExpr*>(n->cause, depth); |
| 1483 | 4 | return nullptr; | |
| 1484 | } | ||
| 1485 | TypeExpr* SemanticAnalyser::trystmt(Try* n, int depth) { | ||
| 1486 | |||
| 1487 | 2 | Array<TypeExpr*> return_t1; | |
| 1488 | 2 | Array<TypeExpr*> return_t2; | |
| 1489 | 2 | Array<TypeExpr*> return_t3; | |
| 1490 | 2 | Array<TypeExpr*> return_t4; | |
| 1491 | |||
| 1492 |
1/1✓ Branch 1 taken 2 times.
|
2 | return_t1 = exec<TypeExpr*>(n->body, depth); |
| 1493 | |||
| 1494 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (ExceptHandler& handler: n->handlers) { |
| 1495 | 2 | Scope _(bindings); | |
| 1496 | |||
| 1497 | 2 | TypeExpr* exception_type = nullptr; | |
| 1498 | |||
| 1499 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (handler.type.has_value()) { |
| 1500 | 2 | exception_type = handler.type.value(); | |
| 1501 | |||
| 1502 |
1/1✓ Branch 1 taken 2 times.
|
2 | TypeExpr* type = exec(exception_type, depth); |
| 1503 | typecheck(exception_type, type, nullptr, make_ref(n, "Type"), LOC); | ||
| 1504 | } | ||
| 1505 | |||
| 1506 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (handler.name.has_value()) { |
| 1507 |
1/1✓ Branch 2 taken 2 times.
|
2 | bindings.add(handler.name.value(), nullptr, exception_type); |
| 1508 | } | ||
| 1509 | |||
| 1510 |
1/1✓ Branch 1 taken 2 times.
|
2 | return_t2 = exec<TypeExpr*>(handler.body, depth); |
| 1511 | 2 | } | |
| 1512 | |||
| 1513 |
1/1✓ Branch 1 taken 2 times.
|
2 | return_t3 = exec<TypeExpr*>(n->orelse, depth); |
| 1514 |
1/1✓ Branch 1 taken 2 times.
|
2 | return_t4 = exec<TypeExpr*>(n->orelse, depth); |
| 1515 | |||
| 1516 | // TODO: | ||
| 1517 |
1/1✓ Branch 1 taken 2 times.
|
4 | return oneof(return_t1); |
| 1518 | 2 | } | |
| 1519 | TypeExpr* SemanticAnalyser::assertstmt(Assert* n, int depth) { | ||
| 1520 | // TODO: | ||
| 1521 | // we need to build the AssertionError exception | ||
| 1522 | 8 | exec(n->test, depth); | |
| 1523 |
1/1✓ Branch 1 taken 8 times.
|
8 | exec<TypeExpr*>(n->msg, depth + 1); |
| 1524 | 8 | return nullptr; | |
| 1525 | } | ||
| 1526 | |||
| 1527 | // This means the binding lookup for variable should stop before the global scope :/ | ||
| 1528 | TypeExpr* SemanticAnalyser::global(Global* n, int depth) { | ||
| 1529 |
2/2✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
|
2 | for (auto& name: n->names) { |
| 1530 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 4 taken 1 times.
|
1 | auto varid = bindings.get_varid(name); |
| 1531 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (varid == -1) { |
| 1532 | SEMA_ERROR(n, NameError, n, name); | ||
| 1533 | } | ||
| 1534 | } | ||
| 1535 | 1 | return nullptr; | |
| 1536 | } | ||
| 1537 | TypeExpr* SemanticAnalyser::nonlocal(Nonlocal* n, int depth) { | ||
| 1538 |
2/2✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
|
2 | for (auto& name: n->names) { |
| 1539 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 4 taken 1 times.
|
1 | auto varid = bindings.get_varid(name); |
| 1540 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (varid == -1) { |
| 1541 | SEMA_ERROR(n, NameError, n, name); | ||
| 1542 | } | ||
| 1543 | } | ||
| 1544 | 1 | return nullptr; | |
| 1545 | } | ||
| 1546 | TypeExpr* SemanticAnalyser::exprstmt(Expr* n, int depth) { return exec(n->value, depth); } | ||
| 1547 | TypeExpr* SemanticAnalyser::pass(Pass* n, int depth) { return None_t(); } | ||
| 1548 | TypeExpr* SemanticAnalyser::breakstmt(Break* n, int depth) { | ||
| 1549 | // check that we are inside a loop | ||
| 1550 | 2 | return nullptr; | |
| 1551 | } | ||
| 1552 | TypeExpr* SemanticAnalyser::continuestmt(Continue* n, int depth) { | ||
| 1553 | // check that we are inside a loop | ||
| 1554 | 2 | return nullptr; | |
| 1555 | } | ||
| 1556 | TypeExpr* SemanticAnalyser::match(Match* n, int depth) { | ||
| 1557 |
1/1✓ Branch 1 taken 6 times.
|
6 | exec(n->subject, depth); |
| 1558 | |||
| 1559 | 6 | Array<TypeExpr*> types; | |
| 1560 |
2/2✓ Branch 4 taken 18 times.
✓ Branch 5 taken 6 times.
|
24 | for (auto& b: n->cases) { |
| 1561 |
1/1✓ Branch 1 taken 18 times.
|
18 | exec(b.pattern, depth + 1); |
| 1562 |
1/1✓ Branch 1 taken 18 times.
|
18 | exec<TypeExpr*>(b.guard, depth + 1); |
| 1563 |
1/1✓ Branch 1 taken 18 times.
|
18 | types = exec<TypeExpr*>(b.body, depth + 1); |
| 1564 | } | ||
| 1565 | |||
| 1566 |
1/1✓ Branch 1 taken 6 times.
|
12 | return oneof(types); |
| 1567 | 6 | } | |
| 1568 | TypeExpr* SemanticAnalyser::inlinestmt(Inline* n, int depth) { | ||
| 1569 |
1/1✓ Branch 1 taken 2 times.
|
2 | auto types = exec<TypeExpr*>(n->body, depth); |
| 1570 |
1/1✓ Branch 1 taken 2 times.
|
4 | return oneof(types); |
| 1571 | 2 | } | |
| 1572 | |||
| 1573 | TypeExpr* SemanticAnalyser::matchvalue(MatchValue* n, int depth) { | ||
| 1574 | 18 | exec(n->value, depth); | |
| 1575 | 18 | return nullptr; | |
| 1576 | } | ||
| 1577 | TypeExpr* SemanticAnalyser::matchsingleton(MatchSingleton* n, int depth) { return nullptr; } | ||
| 1578 | TypeExpr* SemanticAnalyser::matchsequence(MatchSequence* n, int depth) { | ||
| 1579 |
2/2✓ Branch 5 taken 8 times.
✓ Branch 6 taken 6 times.
|
14 | for (auto* elt: n->patterns) { |
| 1580 |
1/1✓ Branch 1 taken 8 times.
|
8 | exec(elt, depth); |
| 1581 | } | ||
| 1582 | 6 | return nullptr; | |
| 1583 | } | ||
| 1584 | TypeExpr* SemanticAnalyser::matchmapping(MatchMapping* n, int depth) { | ||
| 1585 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 4 times.
|
6 | for (auto* pat: n->patterns) { |
| 1586 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(pat, depth); |
| 1587 | } | ||
| 1588 | 4 | return nullptr; | |
| 1589 | } | ||
| 1590 | TypeExpr* SemanticAnalyser::matchclass(MatchClass* n, int depth) { | ||
| 1591 | 2 | exec(n->cls, depth); | |
| 1592 |
2/2✓ Branch 5 taken 4 times.
✓ Branch 6 taken 2 times.
|
6 | for (auto* pat: n->patterns) { |
| 1593 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec(pat, depth); |
| 1594 | } | ||
| 1595 |
2/2✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
|
4 | for (auto* pat: n->kwd_patterns) { |
| 1596 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec(pat, depth); |
| 1597 | } | ||
| 1598 | 2 | return nullptr; | |
| 1599 | } | ||
| 1600 | TypeExpr* SemanticAnalyser::matchstar(MatchStar* n, int depth) { | ||
| 1601 | // TODO: need to get the type from the target | ||
| 1602 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (n->name.has_value()) { |
| 1603 | 2 | bindings.add(n->name.value(), n, nullptr); | |
| 1604 | } | ||
| 1605 | 2 | return nullptr; | |
| 1606 | } | ||
| 1607 | TypeExpr* SemanticAnalyser::matchas(MatchAs* n, int depth) { | ||
| 1608 | // TODO: need to get the type from the target | ||
| 1609 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (n->name.has_value()) { |
| 1610 | 2 | bindings.add(n->name.value(), n, nullptr); | |
| 1611 | } | ||
| 1612 |
1/1✓ Branch 1 taken 2 times.
|
2 | exec<TypeExpr*>(n->pattern, depth); |
| 1613 | 2 | return nullptr; | |
| 1614 | } | ||
| 1615 | TypeExpr* SemanticAnalyser::matchor(MatchOr* n, int depth) { | ||
| 1616 |
2/2✓ Branch 5 taken 4 times.
✓ Branch 6 taken 2 times.
|
6 | for (auto* pat: n->patterns) { |
| 1617 |
1/1✓ Branch 1 taken 4 times.
|
4 | exec(pat, depth); |
| 1618 | } | ||
| 1619 | 2 | return nullptr; | |
| 1620 | } | ||
| 1621 | |||
| 1622 | TypeExpr* SemanticAnalyser::dicttype(DictType* n, int depth) { return Type_t(); } | ||
| 1623 | TypeExpr* SemanticAnalyser::arraytype(ArrayType* n, int depth) { return Type_t(); } | ||
| 1624 | TypeExpr* SemanticAnalyser::arrow(Arrow* n, int depth) { return Type_t(); } | ||
| 1625 | TypeExpr* SemanticAnalyser::builtintype(BuiltinType* n, int depth) { return Type_t(); } | ||
| 1626 | TypeExpr* SemanticAnalyser::tupletype(TupleType* n, int depth) { return Type_t(); } | ||
| 1627 | TypeExpr* SemanticAnalyser::settype(SetType* n, int depth) { return Type_t(); } | ||
| 1628 | TypeExpr* SemanticAnalyser::classtype(ClassType* n, int depth) { return Type_t(); } | ||
| 1629 | |||
| 1630 | TypeExpr* SemanticAnalyser::module(Module* stmt, int depth) { | ||
| 1631 | // TODO: Add a forward pass that simply add functions & variables | ||
| 1632 | // to the context so the SEMA can look everything up | ||
| 1633 |
1/1✓ Branch 1 taken 234 times.
|
234 | exec<TypeExpr*>(stmt->body, depth); |
| 1634 | 234 | return nullptr; | |
| 1635 | }; | ||
| 1636 | |||
| 1637 | TypeExpr* SemanticAnalyser::interactive(Interactive* n, int depth) { return nullptr; } | ||
| 1638 | TypeExpr* SemanticAnalyser::functiontype(FunctionType* n, int depth) { return Type_t(); } | ||
| 1639 | TypeExpr* SemanticAnalyser::expression(Expression* n, int depth) { return exec(n->body, depth); } | ||
| 1640 | |||
| 1641 | bool SemanticAnalyser::has_errors() const { return !errors.empty(); } | ||
| 1642 | void SemanticAnalyser::show_diagnostic(std::ostream& out, class AbstractLexer* lexer) { | ||
| 1643 | 170 | SemaErrorPrinter printer(std::cout, lexer); | |
| 1644 | |||
| 1645 |
2/2✓ Branch 5 taken 136 times.
✓ Branch 6 taken 170 times.
|
306 | for (auto& diag: errors) { |
| 1646 |
1/1✓ Branch 1 taken 136 times.
|
136 | std::cout << " "; |
| 1647 |
1/1✓ Branch 2 taken 136 times.
|
136 | printer.print(*diag.get()); |
| 1648 |
1/1✓ Branch 1 taken 136 times.
|
136 | std::cout << "\n"; |
| 1649 | } | ||
| 1650 | 170 | } | |
| 1651 | } // namespace lython | ||
| 1652 |