aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-23 21:59:35 +0200
committerBad Diode <bd@badd10de.dev>2024-06-23 21:59:35 +0200
commit55849f31e9ad0d2faadd7488ca25669737d74b8d (patch)
tree175187d3bf70eb9a50dd8b335460ffb52c5cfc98
parent25444d18759bb7dde28dc6cb7a1554a08a125e34 (diff)
downloadbdl-55849f31e9ad0d2faadd7488ca25669737d74b8d.tar.gz
bdl-55849f31e9ad0d2faadd7488ca25669737d74b8d.zip
Add wip function typechecking
-rw-r--r--src/main.c73
-rw-r--r--tests/semantics.bad18
2 files changed, 82 insertions, 9 deletions
diff --git a/src/main.c b/src/main.c
index d442b98..4cde055 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
31cond { 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. 113fun 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