diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-23 21:18:44 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-23 21:18:44 +0200 |
commit | 25444d18759bb7dde28dc6cb7a1554a08a125e34 (patch) | |
tree | 8e934c5e72bf124e6a558acc1dfa2607740652a1 /src/main.c | |
parent | 42046a947e1ad636a1ee23be58ce0be2d8abbab2 (diff) | |
download | bdl-25444d18759bb7dde28dc6cb7a1554a08a125e34.tar.gz bdl-25444d18759bb7dde28dc6cb7a1554a08a125e34.zip |
Add non-exhaustive typechecking for cond/match expr
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 48 |
1 files changed, 47 insertions, 1 deletions
@@ -304,6 +304,51 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
304 | node->type = cstr("nil"); | 304 | node->type = cstr("nil"); |
305 | return node->type; | 305 | return node->type; |
306 | } break; | 306 | } break; |
307 | case NODE_COND: | ||
308 | case NODE_MATCH: { | ||
309 | if (node->match_expr) { | ||
310 | type_inference(a, node->match_expr, scope); | ||
311 | } | ||
312 | Type previous = cstr(""); | ||
313 | for (sz i = 0; i < array_size(node->match_cases); i++) { | ||
314 | Node *expr = node->match_cases[i]; | ||
315 | Type next = type_inference(a, expr, scope); | ||
316 | if (i != 0 && !str_eq(next, previous)) { | ||
317 | emit_semantic_error( | ||
318 | a, node, | ||
319 | cstr("non-matching types for case expressions")); | ||
320 | return cstr(""); | ||
321 | } | ||
322 | previous = next; | ||
323 | } | ||
324 | // TODO: proper typecheck matchcase expressions here... | ||
325 | node->type = previous; | ||
326 | return node->type; | ||
327 | } break; | ||
328 | case NODE_CASE_MATCH: { | ||
329 | if (node->case_value) { | ||
330 | type_inference(a, node->case_value, scope); | ||
331 | } | ||
332 | if (node->case_expr->kind != NODE_BLOCK) { | ||
333 | scope = typescope_alloc(a, scope); | ||
334 | } | ||
335 | node->type = type_inference(a, node->case_expr, scope); | ||
336 | return node->type; | ||
337 | } break; | ||
338 | case NODE_CASE_COND: { | ||
339 | if (node->case_value) { | ||
340 | Type cond = type_inference(a, node->case_value, scope); | ||
341 | if (!str_eq(cond, cstr("bool"))) { | ||
342 | emit_semantic_error(a, node, | ||
343 | cstr("non-boolean case condition")); | ||
344 | } | ||
345 | } | ||
346 | if (node->case_expr->kind != NODE_BLOCK) { | ||
347 | scope = typescope_alloc(a, scope); | ||
348 | } | ||
349 | node->type = type_inference(a, node->case_expr, scope); | ||
350 | return node->type; | ||
351 | } break; | ||
307 | case NODE_TRUE: | 352 | case NODE_TRUE: |
308 | case NODE_FALSE: { | 353 | case NODE_FALSE: { |
309 | node->type = cstr("bool"); | 354 | node->type = cstr("bool"); |
@@ -564,7 +609,8 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) { | |||
564 | symmap_insert(&map->val.fields, field_name, s, a->storage); | 609 | symmap_insert(&map->val.fields, field_name, s, a->storage); |
565 | } | 610 | } |
566 | } break; | 611 | } break; |
567 | case NODE_CASE: { | 612 | case NODE_CASE_MATCH: |
613 | case NODE_CASE_COND: { | ||
568 | analyzer_symbols(a, node->case_value, scope); | 614 | analyzer_symbols(a, node->case_value, scope); |
569 | if (node->case_expr) { | 615 | if (node->case_expr) { |
570 | if (node->case_expr->kind != NODE_BLOCK) { | 616 | if (node->case_expr->kind != NODE_BLOCK) { |