✨ function overloading.
parent
6420e283a1
commit
85875d2d94
|
@ -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);
|
||||
|
||||
|
|
|
@ -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; i<table->syms.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; j<args_ty.size; j++)
|
||||
{
|
||||
struct type* arg = args_ty.data[j];
|
||||
struct type* sub = sym->type->subtypes.data[1 + j];
|
||||
|
||||
if (!type_equals(arg, sub))
|
||||
{
|
||||
same = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (same)
|
||||
{
|
||||
for (size_t k=0; k<args_ty.size; k++)
|
||||
{
|
||||
type_free(args_ty.data[k]);
|
||||
}
|
||||
|
||||
vec_free_elements(&args_ty);
|
||||
vec_free(&args_ty);
|
||||
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table = table->prev;
|
||||
}
|
||||
|
||||
for (size_t i=0; i<args_ty.size; i++)
|
||||
{
|
||||
type_free(args_ty.data[i]);
|
||||
}
|
||||
|
||||
vec_free_elements(&args_ty);
|
||||
vec_free(&args_ty);
|
||||
|
||||
if (self->prev)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -65,3 +65,14 @@ fun empty(n: string) {
|
|||
}
|
||||
|
||||
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;
|
Loading…
Reference in New Issue