From 85875d2d946b8c139d5a7b78242cf91cbe0c997f Mon Sep 17 00:00:00 2001 From: bog Date: Sat, 17 Feb 2024 23:35:58 +0100 Subject: [PATCH] :sparkles: function overloading. --- lang/src/compiler.c | 33 +++++++++---- lang/src/sym_table.c | 101 ++++++++++++++++++++++++++++++++++++--- lang/src/sym_table.h | 9 +++- lang/src/type_checker.c | 27 +++++++---- lang/src/type_resolver.c | 12 +++-- lang/tests/sym_table.c | 12 ++--- tests/fun.gux | 13 ++++- 7 files changed, 171 insertions(+), 36 deletions(-) diff --git a/lang/src/compiler.c b/lang/src/compiler.c index 3a9dde9..02674b9 100644 --- a/lang/src/compiler.c +++ b/lang/src/compiler.c @@ -126,8 +126,15 @@ int compiler_compile(struct compiler* self, compiler_compile(self, arg, program); } - struct sym* entry = sym_table_try_by_name(&self->sym_table, - target->value); + struct sym* entry = sym_table_fetch_fun(&self->sym_table, + target->value, + args); + if (!entry) + { + entry = sym_table_fetch(&self->sym_table, + target->value, + NULL); + } assert(entry); @@ -247,8 +254,16 @@ int compiler_compile(struct compiler* self, case NODE_ASSIGN: { struct node* ident = node->children.data[0]; struct node* expr = node->children.data[1]; - struct sym* entry = sym_table_try_by_name(&self->sym_table, - ident->value); + + struct type type; + type_init(&type, TYPE_VOID); + compiler_get_type(self, expr, &type); + + struct sym* entry = sym_table_fetch(&self->sym_table, + ident->value, + &type); + type_free(&type); + assert(entry); if (compiler_compile(self, expr, program) != 0) @@ -260,8 +275,9 @@ int compiler_compile(struct compiler* self, } break; case NODE_IDENT: { - struct sym* entry = sym_table_try_by_name(&self->sym_table, - node->value); + struct sym* entry = sym_table_fetch(&self->sym_table, + node->value, + NULL); if (!entry) { @@ -301,8 +317,9 @@ int compiler_compile(struct compiler* self, sym_table_declare(&self->sym_table, node->value, ty, node->type == NODE_VARDECL); - struct sym* entry = sym_table_try_by_name(&self->sym_table, - node->value); + struct sym* entry = sym_table_fetch(&self->sym_table, + node->value, + ty); assert(entry); diff --git a/lang/src/sym_table.c b/lang/src/sym_table.c index 94e6829..b5e45fe 100644 --- a/lang/src/sym_table.c +++ b/lang/src/sym_table.c @@ -1,5 +1,6 @@ #include "sym_table.h" #include "commons.h" +#include "type_resolver.h" #include "vec.h" void sym_table_init(struct sym_table* self, struct sym_table* prev) @@ -69,7 +70,9 @@ void sym_table_pop_table(struct sym_table* self) self->root = next; } -struct sym* sym_table_try_by_name(struct sym_table* self, char* const name) +struct sym* sym_table_fetch(struct sym_table* self, + char* const name, + struct type* type) { assert(self); @@ -81,7 +84,8 @@ struct sym* sym_table_try_by_name(struct sym_table* self, char* const name) { struct sym* sym = table->syms.data[i]; - if (strcmp(sym->name, name) == 0) + if (strcmp(sym->name, name) == 0 + && (type == NULL || type_equals(type, sym->type))) { return sym; } @@ -92,7 +96,88 @@ struct sym* sym_table_try_by_name(struct sym_table* self, char* const name) if (self->prev) { - return sym_table_try_by_name(self->prev, name); + return sym_table_fetch(self->prev, name, NULL); + } + + return NULL; +} + +struct sym* sym_table_fetch_fun(struct sym_table* self, + char* const name, + struct node* args) +{ + struct vec args_ty; + vec_init(&args_ty, 1); + + struct type_resolver resolver; + type_resolver_init(&resolver, self); + + for (size_t i=0; i < args->children.size; i++) + { + struct node* child = args->children.data[i]; + struct type* arg_type = malloc(sizeof(struct type)); + type_init(arg_type, TYPE_VOID); + + type_resolver_resolve(&resolver, child, arg_type); + vec_push(&args_ty, arg_type); + } + + type_resolver_free(&resolver); + + struct table* table = self->root; + + while (table) + { + for (size_t i=0; isyms.size; i++) + { + struct sym* sym = table->syms.data[i]; + + if (strcmp(sym->name, name) == 0 + && args_ty.size == sym->type->subtypes.size - 1) + { + int same = 1; + + for (size_t j=0; jtype->subtypes.data[1 + j]; + + if (!type_equals(arg, sub)) + { + same = 0; + break; + } + } + + if (same) + { + for (size_t k=0; kprev; + } + + for (size_t i=0; iprev) + { + return sym_table_fetch(self->prev, name, NULL); } return NULL; @@ -120,9 +205,10 @@ int sym_table_declare(struct sym_table* self, assert(self); assert(strcmp(name, "") != 0); - struct sym* s = sym_table_try_by_name(self, name); + struct sym* s = sym_table_fetch(self, name, NULL); - if (s && s->parent == self->root) + if (s && s->parent == self->root + && type_equals(s->type, new_type)) { return 1; } @@ -150,9 +236,10 @@ int sym_table_declare_global(struct sym_table* self, assert(self); assert(strcmp(name, "") != 0); - struct sym* s = sym_table_try_by_name(self, name); + struct sym* s = sym_table_fetch(self, name, NULL); - if (s && s->parent == self->root && s->is_global) + if (s && s->parent == self->root && s->is_global + && type_equals(s->type, new_type)) { return 1; } diff --git a/lang/src/sym_table.h b/lang/src/sym_table.h index 0ddb9ea..7905f4b 100644 --- a/lang/src/sym_table.h +++ b/lang/src/sym_table.h @@ -31,7 +31,14 @@ void sym_table_free(struct sym_table* self); void sym_table_push_table(struct sym_table* self); void sym_table_pop_table(struct sym_table* self); -struct sym* sym_table_try_by_name(struct sym_table* self, char* const name); +struct sym* sym_table_fetch(struct sym_table* self, + char* const name, + struct type* type); + +struct sym* sym_table_fetch_fun(struct sym_table* self, + char* const name, + struct node* args); + int sym_table_declare_const(struct sym_table* self, char* const name, struct type* new_type); diff --git a/lang/src/type_checker.c b/lang/src/type_checker.c index bb05c1f..4e6b40b 100644 --- a/lang/src/type_checker.c +++ b/lang/src/type_checker.c @@ -81,8 +81,10 @@ int type_checker_check(struct type_checker* self, case NODE_CALL: { struct node* target = node->children.data[0]; struct node* args = node->children.data[1]; - struct sym* entry = sym_table_try_by_name(&self->sym_table, - target->value); + + struct sym* entry = sym_table_fetch_fun(&self->sym_table, + target->value, + args); if (!entry) { @@ -95,7 +97,6 @@ int type_checker_check(struct type_checker* self, struct type* ty = entry->type; assert(ty); - if (ty->subtypes.size - 1 != args->children.size) { self->error_line = node->line; @@ -278,8 +279,9 @@ int type_checker_check(struct type_checker* self, struct node* ident = node->children.data[0]; struct node* expr = node->children.data[1]; - struct sym* entry = sym_table_try_by_name(&self->sym_table, - ident->value); + struct sym* entry = sym_table_fetch(&self->sym_table, + ident->value, + NULL); if (!entry) { @@ -318,10 +320,19 @@ int type_checker_check(struct type_checker* self, case NODE_VARDECL: case NODE_CONSTDECL:{ - struct sym* entry = sym_table_try_by_name(&self->sym_table, - node->value); + struct type type; + type_init(&type, TYPE_VOID); - if (entry && entry->parent == self->sym_table.root) + type_resolver_resolve(&self->resolver, node->children.data[0], &type); + + struct sym* entry = sym_table_fetch(&self->sym_table, + node->value, + &type); + + type_free(&type); + + if (entry && entry->parent == self->sym_table.root + && type_equals(entry->type, &type)) { snprintf(self->error_msg, GUX_STR_SIZE, "%s is already defined", node->value); diff --git a/lang/src/type_resolver.c b/lang/src/type_resolver.c index 7e7a621..299b5fa 100644 --- a/lang/src/type_resolver.c +++ b/lang/src/type_resolver.c @@ -43,12 +43,14 @@ int type_resolver_resolve(struct type_resolver* self, struct type call_type; type_init(&call_type, TYPE_VOID); - if (type_resolver_resolve(self, node->children.data[0], &call_type) == 0) + if (type_resolver_resolve(self, node->children.data[0], &call_type) == 0 + && call_type.subtypes.size > 0) { type_copy(call_type.subtypes.data[0], type); } type_free(&call_type); + } return 0; case NODE_FUN: { @@ -83,14 +85,14 @@ int type_resolver_resolve(struct type_resolver* self, type_copy(ty, type); - sym_table_declare(self->sym_table, node->value, ty, - node->type == NODE_VARDECL); + //sym_table_declare(self->sym_table, node->value, ty, + // node->type == NODE_VARDECL); } return 0; case NODE_IDENT: { - struct sym* entry = sym_table_try_by_name(self->sym_table, - node->value); + struct sym* entry = sym_table_fetch(self->sym_table, + node->value, NULL); if (strcmp(node->value, "this") == 0) { diff --git a/lang/tests/sym_table.c b/lang/tests/sym_table.c index a76312a..a00d3bb 100644 --- a/lang/tests/sym_table.c +++ b/lang/tests/sym_table.c @@ -6,7 +6,7 @@ Test(sym_table, simple) { struct sym_table table; sym_table_init(&table, NULL); - struct sym* sym = sym_table_try_by_name(&table, "hello"); + struct sym* sym = sym_table_fetch(&table, "hello", NULL); cr_assert_eq(sym, 0); struct type* ty = malloc(sizeof(struct type)); @@ -15,7 +15,7 @@ Test(sym_table, simple) { int err = sym_table_declare_const(&table, "hello", ty); cr_assert_eq(err, 0); - sym = sym_table_try_by_name(&table, "hello"); + sym = sym_table_fetch(&table, "hello", NULL); cr_assert_neq(sym, 0); cr_assert_str_eq("hello", sym->name); @@ -58,15 +58,15 @@ Test(sym_table, scope) { struct sym* sym; - sym = sym_table_try_by_name(&table, "abc"); + sym = sym_table_fetch(&table, "abc", NULL); cr_assert_eq(sym->type->kind, TYPE_STRING); sym_table_pop_table(&table); - sym = sym_table_try_by_name(&table, "abc"); + sym = sym_table_fetch(&table, "abc", NULL); cr_assert_eq(sym->type->kind, TYPE_FLOAT); sym_table_pop_table(&table); - sym = sym_table_try_by_name(&table, "abc"); + sym = sym_table_fetch(&table, "abc", NULL); cr_assert_eq(sym->type->kind, TYPE_INT); sym_table_free(&table); @@ -84,7 +84,7 @@ Test(sym_table, outer_scope) { sym_table_push_table(&table); sym_table_push_table(&table); - struct sym* sym = sym_table_try_by_name(&table, "abc"); + struct sym* sym = sym_table_fetch(&table, "abc", NULL); cr_assert_eq(sym->type->kind, TYPE_INT); sym_table_free(&table); diff --git a/tests/fun.gux b/tests/fun.gux index 105f3b3..d820001 100644 --- a/tests/fun.gux +++ b/tests/fun.gux @@ -64,4 +64,15 @@ fun empty(n: string) { return; } -empty('useless'); \ No newline at end of file +empty('useless'); + +fun first(n: int) -> int { + return 27; +} + +fun first(n: float) -> int { + return 79; +} + +assert first(4) == 27; +assert first(7.3) == 79; \ No newline at end of file