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 |