diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-01-15 19:55:04 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-01-15 19:55:04 +0000 |
| commit | ac736aa4ecf5dce7b1dbd4c5ef3758f8f2008ebc (patch) | |
| tree | b7d30f39fb13723d33de2b0a5f4029873f25a205 /src/check_stmt.c | |
| parent | 6fe25badf067d63c79999814f46be0ac79a39ef8 (diff) | |
Procedure overloading
Diffstat (limited to 'src/check_stmt.c')
| -rw-r--r-- | src/check_stmt.c | 68 |
1 files changed, 54 insertions, 14 deletions
diff --git a/src/check_stmt.c b/src/check_stmt.c index 5ca553600..e877bc190 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -184,7 +184,7 @@ bool check_is_terminating(AstNode *node) { Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) { if (op_a->mode == Addressing_Invalid || - op_a->type == t_invalid) { + (op_a->type == t_invalid && op_a->mode != Addressing_Overload)) { return NULL; } @@ -195,33 +195,73 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) { str_eq(node->Ident.string, str_lit("_"))) { add_entity_definition(&c->info, node, NULL); check_assignment(c, op_a, NULL, str_lit("assignment to `_` identifier")); - if (op_a->mode == Addressing_Invalid) + if (op_a->mode == Addressing_Invalid) { return NULL; + } return op_a->type; } Entity *e = NULL; bool used = false; - if (node->kind == AstNode_Ident) { - ast_node(i, Ident, node); - e = scope_lookup_entity(c->context.scope, i->string); - if (e != NULL && e->kind == Entity_Variable) { - used = (e->flags & EntityFlag_Used) != 0; // TODO(bill): Make backup just in case - } - } + Operand op_b = {Addressing_Invalid}; - Operand op_b = {Addressing_Invalid}; check_expr(c, &op_b, lhs); - if (e) { - e->flags |= EntityFlag_Used*used; - } - if (op_b.mode == Addressing_Invalid || op_b.type == t_invalid) { return NULL; } + + if (op_a->mode == Addressing_Overload) { + isize overload_count = op_a->overload_count; + Entity *entity = op_a->initial_overload_entity; + String name = entity->token.string; + Scope *s = entity->scope; + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + Entity **procs = gb_alloc_array(c->tmp_allocator, Entity *, overload_count); + + HashKey key = hash_string(name); + map_entity_multi_get_all(&s->elements, key, procs); + // NOTE(bill): These should be done + for (isize i = 0; i < overload_count; i++) { + Type *t = base_type(procs[i]->type); + if (t == t_invalid) { + continue; + } + Operand x = {0}; + x.mode = Addressing_Value; + x.type = t; + if (check_is_assignable_to(c, &x, op_b.type)) { + e = procs[i]; + add_entity_use(c, op_a->expr, e); + break; + } + } + gb_temp_arena_memory_end(tmp); + + if (e != NULL) { + op_a->mode = Addressing_Value; + op_a->type = e->type; + op_a->overload_count = 0; + op_a->initial_overload_entity = NULL; + } + + } else { + if (node->kind == AstNode_Ident) { + ast_node(i, Ident, node); + e = scope_lookup_entity(c->context.scope, i->string); + if (e != NULL && e->kind == Entity_Variable) { + used = (e->flags & EntityFlag_Used) != 0; // TODO(bill): Make backup just in case + } + } + + } + + if (e != NULL && used) { + e->flags |= EntityFlag_Used; + } + switch (op_b.mode) { case Addressing_Invalid: return NULL; |