aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-24 11:46:43 +0200
committerBad Diode <bd@badd10de.dev>2024-06-24 11:46:43 +0200
commit9c73b54a747e5489b2d6f27947cd8216f5311d5e (patch)
tree1a6aa027e80336cd3418305bcb8402ef47bbedf2 /src
parent15e24115a2a117407157c993fe17b2d414dc0bf4 (diff)
downloadbdl-9c73b54a747e5489b2d6f27947cd8216f5311d5e.tar.gz
bdl-9c73b54a747e5489b2d6f27947cd8216f5311d5e.zip
Typecheck return values in the entire function body
Diffstat (limited to 'src')
-rw-r--r--src/main.c89
1 files changed, 81 insertions, 8 deletions
diff --git a/src/main.c b/src/main.c
index e93a538..acc2b46 100644
--- a/src/main.c
+++ b/src/main.c
@@ -201,6 +201,70 @@ emit_semantic_error(Analyzer *a, Node *n, Str msg) {
201 eprintln("%s:%d:%d: error: %s", a->file_name, n->line, n->col, msg); 201 eprintln("%s:%d:%d: error: %s", a->file_name, n->line, n->col, msg);
202} 202}
203 203
204bool
205typecheck_returns(Node *node, Str expected) {
206 if (!node) {
207 return true;
208 }
209
210 // Traverse the tree again.
211 switch (node->kind) {
212 case NODE_COND:
213 case NODE_MATCH: {
214 for (sz i = 0; i < array_size(node->match_cases); i++) {
215 Node *next = node->match_cases[i];
216 if (!typecheck_returns(next, expected)) {
217 return false;
218 }
219 }
220 } break;
221 case NODE_RETURN: {
222 return str_eq(node->type, expected);
223 } break;
224 case NODE_BLOCK: {
225 for (sz i = 0; i < array_size(node->elements); i++) {
226 Node *next = node->elements[i];
227 if (!typecheck_returns(next, expected)) {
228 return false;
229 }
230 }
231 } break;
232 case NODE_IF: {
233 if (node->cond_expr) {
234 if (!typecheck_returns(node->cond_expr, expected)) {
235 return false;
236 }
237 }
238 if (node->cond_else) {
239 if (!typecheck_returns(node->cond_else, expected)) {
240 return false;
241 }
242 }
243 } break;
244 case NODE_SET:
245 case NODE_LET: {
246 if (node->var_val) {
247 if (!typecheck_returns(node->var_val, expected)) {
248 return false;
249 }
250 }
251 } break;
252 default: {
253 if (node->left) {
254 if (!typecheck_returns(node->left, expected)) {
255 return false;
256 }
257 }
258 if (node->right) {
259 if (!typecheck_returns(node->right, expected)) {
260 return false;
261 }
262 }
263 } break;
264 }
265 return true;
266}
267
204Type 268Type
205type_inference(Analyzer *a, Node *node, TypeScope *scope) { 269type_inference(Analyzer *a, Node *node, TypeScope *scope) {
206 assert(a); 270 assert(a);
@@ -554,21 +618,30 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
554 ret_type = str_concat(ret_type, cstr(")"), a->storage); 618 ret_type = str_concat(ret_type, cstr(")"), a->storage);
555 node->fun_return = ret_type; 619 node->fun_return = ret_type;
556 620
557 node->type = cstr("nil");
558 if (node->func_body->kind == NODE_BLOCK) { 621 if (node->func_body->kind == NODE_BLOCK) {
559 node = node->func_body;
560 Type type; 622 Type type;
561 for (sz i = 0; i < array_size(node->elements); i++) { 623 for (sz i = 0; i < array_size(node->func_body->elements); i++) {
562 Node *expr = node->elements[i]; 624 Node *expr = node->func_body->elements[i];
563 type = type_inference(a, expr, scope); 625 type = type_inference(a, expr, scope);
564 } 626 }
565 node->type = type; 627 node->func_body->type = type;
566 // TODO: ensure ALL return statements match the function
567 // prototype.
568 } else { 628 } else {
569 type_inference(a, node->func_body, scope); 629 type_inference(a, node->func_body, scope);
570 } 630 }
571 return cstr("nil"); 631
632 // Ensure main body return matches the prototype.
633 if (!str_eq(node->func_body->type, ret_type)) {
634 emit_semantic_error(a, node, cstr("mismatched return types"));
635 }
636
637 // Ensure ALL return statements match the function prototype.
638 if (!typecheck_returns(node->func_body, ret_type)) {
639 emit_semantic_error(a, node, cstr("mismatched return types"));
640 }
641
642 // TODO: insert this into a functions map in the current scope? need
643 // the arity and return parameters for funcalls.
644 return node->type;
572 } break; 645 } break;
573 default: { 646 default: {
574 emit_semantic_error(a, node, 647 emit_semantic_error(a, node,