aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-24 15:38:29 +0200
committerBad Diode <bd@badd10de.dev>2024-06-24 15:38:29 +0200
commitec7faebe81c6d4aad7f2927962fae5c9f414eb66 (patch)
tree7a382c8ddf815f1623a9bade35e68b63dbdf7797
parent5d3bd237db051902161a919a2efb6ca25de449d9 (diff)
downloadbdl-ec7faebe81c6d4aad7f2927962fae5c9f414eb66.tar.gz
bdl-ec7faebe81c6d4aad7f2927962fae5c9f414eb66.zip
Add funcall typechecking
-rw-r--r--src/main.c61
-rw-r--r--tests/semantics.bad60
2 files changed, 79 insertions, 42 deletions
diff --git a/src/main.c b/src/main.c
index 72ea88b..88d49ed 100644
--- a/src/main.c
+++ b/src/main.c
@@ -143,6 +143,18 @@ find_type(TypeScope *scope, Str type) {
143 return NULL; 143 return NULL;
144} 144}
145 145
146FunMap *
147find_fun(TypeScope *scope, Str type) {
148 while (scope != NULL) {
149 FunMap *val = funmap_lookup(&scope->funcs, type);
150 if (val != NULL) {
151 return val;
152 }
153 scope = scope->parent;
154 }
155 return NULL;
156}
157
146void 158void
147graph_scope(Scope *scope, Arena a) { 159graph_scope(Scope *scope, Arena a) {
148 if (!scope->symbols) { 160 if (!scope->symbols) {
@@ -302,7 +314,7 @@ graph_symbols(Scope **scopes, Arena a) {
302void 314void
303graph_types(TypeScope **scopes, Arena a) { 315graph_types(TypeScope **scopes, Arena a) {
304 if (scopes == NULL) return; 316 if (scopes == NULL) return;
305 println("digraph symbols {"); 317 println("digraph types {");
306 println("rankdir=LR;"); 318 println("rankdir=LR;");
307 println("ranksep=\"0.95 equally\";"); 319 println("ranksep=\"0.95 equally\";");
308 println("nodesep=\"0.5 equally\";"); 320 println("nodesep=\"0.5 equally\";");
@@ -664,19 +676,38 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
664 return node->type; 676 return node->type;
665 } break; 677 } break;
666 case NODE_FUNCALL: { 678 case NODE_FUNCALL: {
667 // TODO: ... 679 Str symbol = node->value.str;
668 // Str symbol = node->value.str; 680 FunMap *fun = find_fun(scope, symbol);
669 // if (find_symbol(scope, symbol) == NULL) { 681 if (!fun) {
670 // eprintln( 682 eprintln(
671 // "%s:%d:%d: error: symbol '%s' doesn't exists in current " 683 "%s:%d:%d: error: function '%s' doesn't exist in current "
672 // " scope ", 684 " scope ",
673 // a->file_name, node->line, node->col, symbol); 685 a->file_name, node->line, node->col, symbol);
674 // return; 686 return cstr("");
675 // } 687 }
676 // for (sz i = 0; i < array_size(node->elements); i++) { 688 // Check that actual parameters typecheck
677 // Node *expr = node->elements[i]; 689 Type args = cstr("");
678 // analyzer_symbols(a, expr, scope); 690 for (sz i = 0; i < array_size(node->elements); i++) {
679 // } 691 Node *expr = node->elements[i];
692 Type type = type_inference(a, expr, scope);
693 args = str_concat(args, type, a->storage);
694 if (i != array_size(node->elements) - 1) {
695 args = str_concat(args, cstr(","), a->storage);
696 }
697 }
698 if (!args.size) {
699 args = cstr("nil");
700 }
701 Str expected = fun->val.param_type;
702 bool err = !str_eq(args, expected);
703 if (err) {
704 eprintln(
705 "%s:%d:%d: error: mismatched parameter types: %s expected "
706 "%s",
707 a->file_name, node->line, node->col, args, expected);
708 }
709 node->type = fun->val.return_type;
710 return node->type;
680 } break; 711 } break;
681 case NODE_BLOCK: { 712 case NODE_BLOCK: {
682 scope = typescope_alloc(a, scope); 713 scope = typescope_alloc(a, scope);
@@ -794,8 +825,6 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
794 typecheck_returns(a, node->func_body, ret_type); 825 typecheck_returns(a, node->func_body, ret_type);
795 826
796 // TODO: should return statements be allowed on let blocks? 827 // TODO: should return statements be allowed on let blocks?
797 // TODO: insert this into a functions map in the current scope? need
798 // the arity and return parameters for funcalls.
799 return node->type; 828 return node->type;
800 } break; 829 } break;
801 default: { 830 default: {
diff --git a/tests/semantics.bad b/tests/semantics.bad
index 3305222..3479915 100644
--- a/tests/semantics.bad
+++ b/tests/semantics.bad
@@ -1,23 +1,31 @@
1; let a:f32 = (1.0 + 2.0 * 2.0) / 2.0 1fun add10(a: int, b: str): int {
2 2 a + 10
3let annotated:int = (1 + 2 * 2) / 2
4let numbers = 1
5let symbols = numbers
6let arith = 1 + 2 * 4
7let cmp = 1 <= 2
8let logic = !true && false || (1 <= 2)
9let bits = 0xff & 0b00001111
10let block = {
11 let a = 1 + 2
12 a + 3
13} 3}
14 4
15let maybe = if (1 == 2) { 5fun foo(): int {
16 32 6 add10(1, "hello")
17} else {
18 44
19} 7}
20 8
9; let a:f32 = (1.0 + 2.0 * 2.0) / 2.0
10
11; let annotated:int = (1 + 2 * 2) / 2
12; let numbers = 1
13; let symbols = numbers
14; let arith = 1 + 2 * 4
15; let cmp = 1 <= 2
16; let logic = !true && false || (1 <= 2)
17; let bits = 0xff & 0b00001111
18; let block = {
19; let a = 1 + 2
20; a + 3
21; }
22
23; let maybe = if (1 == 2) {
24; 32
25; } else {
26; 44
27; }
28
21; let single = if (true) { 29; let single = if (true) {
22; 123 30; 123
23; } 31; }
@@ -112,16 +120,16 @@ fun nested(): int {
112; let c = 1 120; let c = 1
113; 1 + 1 + c 121; 1 + 1 + c
114; } 122; }
115fun foo(a: int b: str): (f64, f64) { 123; fun foo(a: int b: str): (f64, f64) {
116 fun bar(): nil { 124; fun bar(): nil {
117 println("ding") 125; println("ding")
118 } 126; }
119 if (a == 1) { 127; if (a == 1) {
120 ; return("test", b) 128; ; return("test", b)
121 return(3.0, 4.0) 129; return (3.0, 4.0)
122 } 130; }
123 return(1.0, 2.0) 131; return (1.0, 2.0)
124} 132; }
125 133
126; let b = a 134; let b = a
127; let a = a 135; let a = a