diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-23 21:59:35 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-23 21:59:35 +0200 |
commit | 55849f31e9ad0d2faadd7488ca25669737d74b8d (patch) | |
tree | 175187d3bf70eb9a50dd8b335460ffb52c5cfc98 | |
parent | 25444d18759bb7dde28dc6cb7a1554a08a125e34 (diff) | |
download | bdl-55849f31e9ad0d2faadd7488ca25669737d74b8d.tar.gz bdl-55849f31e9ad0d2faadd7488ca25669737d74b8d.zip |
Add wip function typechecking
-rw-r--r-- | src/main.c | 73 | ||||
-rw-r--r-- | tests/semantics.bad | 18 |
2 files changed, 82 insertions, 9 deletions
@@ -448,6 +448,15 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
448 | node->type = cstr("str"); | 448 | node->type = cstr("str"); |
449 | return node->type; | 449 | return node->type; |
450 | } break; | 450 | } break; |
451 | case NODE_TYPE: { | ||
452 | TypeMap *type = find_type(scope, node->value.str); | ||
453 | if (!type) { | ||
454 | emit_semantic_error(a, node, cstr("unknown type")); | ||
455 | return cstr(""); | ||
456 | } | ||
457 | node->type = type->val; | ||
458 | return node->type; | ||
459 | } break; | ||
451 | case NODE_SYMBOL: { | 460 | case NODE_SYMBOL: { |
452 | TypeMap *type = find_type(scope, node->value.str); | 461 | TypeMap *type = find_type(scope, node->value.str); |
453 | if (type) { | 462 | if (type) { |
@@ -481,6 +490,70 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
481 | node->type = type; | 490 | node->type = type; |
482 | return node->type; | 491 | return node->type; |
483 | } break; | 492 | } break; |
493 | case NODE_RETURN: { | ||
494 | Type type; | ||
495 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
496 | Node *expr = node->elements[i]; | ||
497 | type = type_inference(a, expr, scope); | ||
498 | } | ||
499 | // TODO: this is incorrect, must return the inferred type, but what | ||
500 | // to do if we have multiple? This only considers single return | ||
501 | // values for now... | ||
502 | node->type = type; | ||
503 | return type; | ||
504 | } break; | ||
505 | case NODE_FUN: { | ||
506 | // TODO: we may want to do this and register a special table with | ||
507 | // function and formals... | ||
508 | // if (scope->parent != NULL) { | ||
509 | // // Str symbol = node->func_name->value.str; | ||
510 | // // if (symmap_lookup(&scope->symbols, symbol) != NULL) { | ||
511 | // // eprintln( | ||
512 | // // "%s:%d:%d: error: symbol '%s' already exists in " | ||
513 | // // "current " | ||
514 | // // "scope", | ||
515 | // // a->file_name, node->func_name->line, | ||
516 | // // node->func_name->col, symbol); | ||
517 | // // return; | ||
518 | // // } | ||
519 | // // symmap_insert(&scope->symbols, symbol, | ||
520 | // // (Symbol){.kind = SYM_FUN, .name = symbol}, | ||
521 | // // a->storage); | ||
522 | // } | ||
523 | |||
524 | node->type = cstr("nil"); | ||
525 | scope = typescope_alloc(a, scope); | ||
526 | for (sz i = 0; i < array_size(node->func_params); i++) { | ||
527 | Node *param = node->func_params[i]; | ||
528 | Str symbol = param->param_name->value.str; | ||
529 | Type type = param->param_type->value.str; | ||
530 | param->param_name->type = | ||
531 | type_inference(a, param->param_type, scope); | ||
532 | param->type = param->param_name->type; | ||
533 | typemap_insert(&scope->types, symbol, type, a->storage); | ||
534 | } | ||
535 | |||
536 | for (sz i = 0; i < array_size(node->func_ret); i++) { | ||
537 | Node *ret = node->func_ret[i]; | ||
538 | ret->type = type_inference(a, ret, scope); | ||
539 | } | ||
540 | |||
541 | node->type = cstr("nil"); | ||
542 | if (node->func_body->kind == NODE_BLOCK) { | ||
543 | node = node->func_body; | ||
544 | Type type; | ||
545 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
546 | Node *expr = node->elements[i]; | ||
547 | type = type_inference(a, expr, scope); | ||
548 | } | ||
549 | node->type = type; | ||
550 | // TODO: ensure ALL return statements match the function | ||
551 | // prototype. | ||
552 | } else { | ||
553 | type_inference(a, node->func_body, scope); | ||
554 | } | ||
555 | return cstr("nil"); | ||
556 | } break; | ||
484 | default: { | 557 | default: { |
485 | emit_semantic_error(a, node, | 558 | emit_semantic_error(a, node, |
486 | cstr("type inference not implemented for this " | 559 | cstr("type inference not implemented for this " |
diff --git a/tests/semantics.bad b/tests/semantics.bad index 5b5c971..47c4b88 100644 --- a/tests/semantics.bad +++ b/tests/semantics.bad | |||
@@ -28,10 +28,10 @@ | |||
28 | 28 | ||
29 | ; set single = 32 | 29 | ; set single = 32 |
30 | 30 | ||
31 | cond { | 31 | ; cond { |
32 | 1 == 2 = "hello" | 32 | ; 1 == 2 = "hello" |
33 | else = "dong" | 33 | ; else = "dong" |
34 | } | 34 | ; } |
35 | 35 | ||
36 | ; enum test { | 36 | ; enum test { |
37 | ; a = 1 | 37 | ; a = 1 |
@@ -48,7 +48,7 @@ cond { | |||
48 | 48 | ||
49 | ; fun nested(): u32 { | 49 | ; fun nested(): u32 { |
50 | ; fun adder(a: u32, b: u32): u32 a + b | 50 | ; fun adder(a: u32, b: u32): u32 a + b |
51 | ; if (1 + 1) { | 51 | ; if (1 + 1 == 2) { |
52 | ; { | 52 | ; { |
53 | ; let b = 32 | 53 | ; let b = 32 |
54 | ; } | 54 | ; } |
@@ -110,10 +110,10 @@ cond { | |||
110 | ; 1 + 1 + c | 110 | ; 1 + 1 + c |
111 | ; } | 111 | ; } |
112 | 112 | ||
113 | ; This should err. | 113 | fun foo(a: int b: str): (f32, f64) { |
114 | ; fun foo(): nil { | 114 | return(1.0, 2.0) |
115 | ; 1 | 115 | } |
116 | ; } | 116 | |
117 | ; let b = a | 117 | ; let b = a |
118 | ; let a = a | 118 | ; let a = a |
119 | ; set a = 10 | 119 | ; set a = 10 |