diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-24 15:38:29 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-24 15:38:29 +0200 |
commit | ec7faebe81c6d4aad7f2927962fae5c9f414eb66 (patch) | |
tree | 7a382c8ddf815f1623a9bade35e68b63dbdf7797 /src | |
parent | 5d3bd237db051902161a919a2efb6ca25de449d9 (diff) | |
download | bdl-ec7faebe81c6d4aad7f2927962fae5c9f414eb66.tar.gz bdl-ec7faebe81c6d4aad7f2927962fae5c9f414eb66.zip |
Add funcall typechecking
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 61 |
1 files changed, 45 insertions, 16 deletions
@@ -143,6 +143,18 @@ find_type(TypeScope *scope, Str type) { | |||
143 | return NULL; | 143 | return NULL; |
144 | } | 144 | } |
145 | 145 | ||
146 | FunMap * | ||
147 | find_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 | |||
146 | void | 158 | void |
147 | graph_scope(Scope *scope, Arena a) { | 159 | graph_scope(Scope *scope, Arena a) { |
148 | if (!scope->symbols) { | 160 | if (!scope->symbols) { |
@@ -302,7 +314,7 @@ graph_symbols(Scope **scopes, Arena a) { | |||
302 | void | 314 | void |
303 | graph_types(TypeScope **scopes, Arena a) { | 315 | graph_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: { |