Explicit procedure group; Remove implicit procedure overloading

This commit is contained in:
gingerBill
2017-12-09 18:11:36 +00:00
parent 41b8281c73
commit 3703ca4df4
12 changed files with 359 additions and 532 deletions

View File

@@ -127,14 +127,6 @@ void check_scope_decls(Checker *c, Array<AstNode *> nodes, isize reserve_size) {
check_entity_decl(c, e, d, nullptr);
}
}
for_array(i, s->elements.entries) {
Entity *e = s->elements.entries[i].value;
if (e->kind != Entity_Procedure) {
continue;
}
check_procedure_overloading(c, e);
}
}
@@ -659,18 +651,16 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
return;
}
if (operand->mode == Addressing_Overload) {
if (operand->mode == Addressing_ProcGroup) {
// GB_PANIC("HERE!\n");
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
defer (gb_temp_arena_memory_end(tmp));
Entity **procs = operand->overload_entities;
isize overload_count = operand->overload_count;
Array<Entity *> procs = proc_group_entities(c, *operand);
bool good = false;
// NOTE(bill): These should be done
for (isize i = 0; i < overload_count; i++) {
for_array(i, procs) {
Type *t = base_type(procs[i]->type);
if (t == t_invalid) {
continue;
@@ -783,7 +773,10 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
return false;
case Type_Array:
if (source->kind == Type_Array) {
if (poly->Array.generic_type && modify_type) {
// IMPORTANT TODO(bill): Which is correct?
// if (poly->Array.generic_type != nullptr && modify_type) {
if (poly->Array.generic_type != nullptr) {
Type *gt = poly->Array.generic_type;
GB_ASSERT(gt->kind == Type_Generic);
Entity *e = scope_lookup_entity(gt->Generic.scope, gt->Generic.name);
@@ -808,8 +801,6 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
} else {
return false;
}
return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type);
}
if (poly->Array.count == source->Array.count) {
return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type);
@@ -936,10 +927,6 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
return nullptr;
}
}
bool is_overloaded = false;
isize overload_count = 0;
bool is_alias = false;
while (e->kind == Entity_Alias) {
GB_ASSERT(e->Alias.base != nullptr);
@@ -949,63 +936,14 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
HashKey key = hash_string(e->token.string);
if (e->kind == Entity_Procedure) {
// NOTE(bill): Overloads are only allowed with the same scope
Scope *s = e->scope;
overload_count = multi_map_count(&s->elements, key);
if (overload_count > 1) {
is_overloaded = true;
}
}
if (is_overloaded) {
Scope *s = e->scope;
bool skip = false;
Entity **procs = gb_alloc_array(heap_allocator(), Entity *, overload_count);
multi_map_get_all(&s->elements, key, procs);
if (type_hint != nullptr) {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
defer (gb_temp_arena_memory_end(tmp));
// 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 = {};
x.mode = Addressing_Value;
x.type = t;
if (check_is_assignable_to(c, &x, type_hint)) {
e = procs[i];
add_entity_use(c, n, e);
skip = true;
break;
}
}
}
if (!skip) {
o->mode = Addressing_Overload;
o->type = t_invalid;
o->overload_count = overload_count;
o->overload_entities = procs;
return nullptr;
}
gb_free(heap_allocator(), procs);
}
if (e->kind == Entity_ProcedureGrouping) {
auto *pge = &e->ProcedureGrouping;
if (e->kind == Entity_ProcGroup) {
auto *pge = &e->ProcGroup;
DeclInfo *d = decl_info_of_entity(&c->info, e);
check_entity_decl(c, e, d, nullptr);
Entity **procs = pge->entities.data;
isize overload_count = pge->entities.count;
Array<Entity *> procs = pge->entities;
bool skip = false;
if (type_hint != nullptr) {
@@ -1013,7 +951,7 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
defer (gb_temp_arena_memory_end(tmp));
// NOTE(bill): These should be done
for (isize i = 0; i < overload_count; i++) {
for_array(i, procs) {
Type *t = base_type(procs[i]->type);
if (t == t_invalid) {
continue;
@@ -1031,10 +969,9 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
}
if (!skip) {
o->mode = Addressing_Overload;
o->type = t_invalid;
o->overload_count = overload_count;
o->overload_entities = procs;
o->mode = Addressing_ProcGroup;
o->type = t_invalid;
o->proc_group = e;
return nullptr;
}
}
@@ -1550,13 +1487,13 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
}
} else {
gbString xt, yt;
if (x->mode == Addressing_Overload) {
xt = gb_string_make(heap_allocator(), "overloaded procedure");
if (x->mode == Addressing_ProcGroup) {
xt = gb_string_make(heap_allocator(), "procedure group");
} else {
xt = type_to_string(x->type);
}
if (y->mode == Addressing_Overload) {
yt = gb_string_make(heap_allocator(), "overloaded procedure");
if (y->mode == Addressing_ProcGroup) {
yt = gb_string_make(heap_allocator(), "procedure group");
} else {
yt = type_to_string(y->type);
}
@@ -2483,18 +2420,6 @@ bool check_index_value(Checker *c, bool open_range, AstNode *index_value, i64 ma
return true;
}
isize entity_overload_count(Scope *s, String name) {
Entity *e = scope_lookup_entity(s, name);
if (e == nullptr) {
return 0;
}
if (e->kind == Entity_Procedure) {
// NOTE(bill): Overloads are only allowed with the same scope
return multi_map_count(&s->elements, hash_string(e->token.string));
}
return 1;
}
Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_hint) {
ast_node(se, SelectorExpr, node);
@@ -2572,7 +2497,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
}
check_entity_decl(c, entity, nullptr, nullptr);
GB_ASSERT(entity->type != nullptr || entity->kind == Entity_ProcedureGrouping);
GB_ASSERT(entity->type != nullptr || entity->kind == Entity_ProcGroup);
if (is_alias) {
// TODO(bill): Which scope do you search for for an alias?
@@ -2580,46 +2505,26 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
entity_name = entity->token.string;
}
isize overload_count = entity_overload_count(import_scope, entity_name);
bool is_overloaded = overload_count > 1;
bool implicit_is_found = is_entity_implicitly_imported(e, entity);
bool is_not_exported = !is_entity_exported(entity);
if (entity->kind == Entity_ImportName) {
is_not_exported = true;
} else if (implicit_is_found) {
is_not_exported = !is_overloaded;
is_not_exported = true;
}
Entity **procs = nullptr;
if (is_overloaded) {
HashKey key = hash_string(entity_name);
procs = gb_alloc_array(heap_allocator(), Entity *, overload_count);
multi_map_get_all(&import_scope->elements, key, procs);
} else if (entity->kind == Entity_ProcedureGrouping) {
is_overloaded = true;
procs = entity->ProcedureGrouping.entities.data;
overload_count = entity->ProcedureGrouping.entities.count;
}
if (is_overloaded) {
if (is_not_exported && entity->kind == Entity_ProcGroup) {
check_entity_decl(c, entity, nullptr, nullptr);
auto *pge = &entity->ProcGroup;
Array<Entity *> procs = pge->entities;
bool skip = false;
for (isize i = 0; i < overload_count; i++) {
for_array(i, procs) {
Type *t = base_type(procs[i]->type);
if (t == t_invalid) {
continue;
}
// NOTE(bill): Check to see if it's imported
if (is_entity_implicitly_imported(e, procs[i])) {
gb_swap(Entity *, procs[i], procs[overload_count-1]);
overload_count--;
i--; // NOTE(bill): Counteract the post event
continue;
}
Operand x = {};
x.mode = Addressing_Value;
x.type = t;
@@ -2633,16 +2538,12 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
}
if (!skip) {
if (overload_count > 0) {
operand->mode = Addressing_Overload;
operand->type = t_invalid;
operand->expr = node;
operand->overload_count = overload_count;
operand->overload_entities = procs;
return procs[0];
} else {
is_not_exported = true;
}
GB_ASSERT(e != nullptr);
operand->mode = Addressing_ProcGroup;
operand->type = t_invalid;
operand->expr = node;
operand->proc_group = e;
return e;
}
}
@@ -2791,7 +2692,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
operand->builtin_id = cast(BuiltinProcId)entity->Builtin.id;
break;
case Entity_ProcedureGrouping:
case Entity_ProcGroup:
entity->type = t_invalid;
break;
@@ -4439,7 +4340,6 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
return err;
}
CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
ast_node(ce, CallExpr, call);
@@ -4469,31 +4369,19 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
check_unpack_arguments(c, nullptr, -1, &operands, ce->args, false);
}
if (operand->mode == Addressing_Overload) {
// GB_ASSERT_MSG(operand->overload_entities != nullptr &&
// operand->overload_count > 0,
// "%p %td", operand->overload_entities, operand->overload_count);
isize overload_count = operand->overload_count;
Entity ** procs = operand->overload_entities;
ValidIndexAndScore *valids = gb_alloc_array(heap_allocator(), ValidIndexAndScore, overload_count);
isize valid_count = 0;
if (operand->mode == Addressing_ProcGroup) {
Array<Entity *> procs = proc_group_entities(c, *operand);
defer (gb_free(heap_allocator(), procs));
ValidIndexAndScore *valids = gb_alloc_array(heap_allocator(), ValidIndexAndScore, procs.count);
isize valid_count = 0;
defer (gb_free(heap_allocator(), valids));
gbString expr_name = expr_to_string(operand->expr);
defer (gb_string_free(expr_name));
for (isize i = 0; i < overload_count; i++) {
Entity *e = procs[i];
// GB_ASSERT(e->token.string == name);
DeclInfo *d = decl_info_of_entity(&c->info, e);
GB_ASSERT(d != nullptr);
check_entity_decl(c, e, d, nullptr);
}
for (isize i = 0; i < overload_count; i++) {
for_array(i, procs) {
Entity *p = procs[i];
check_entity_decl(c, p, nullptr, nullptr);
Type *pt = base_type(p->type);
if (pt != nullptr && is_type_proc(pt)) {
CallArgumentError err = CallArgumentError_None;
@@ -4502,6 +4390,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
defer (c->context = prev_context);
c->context.no_polymorphic_errors = true;
c->context.allow_polymorphic_types = is_type_polymorphic(pt);
err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
if (err == CallArgumentError_None) {
@@ -4531,7 +4420,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
if (valid_count == 0) {
error(operand->expr, "No overloads or ambiguous call for '%s' that match with the given arguments", expr_name);
error(operand->expr, "No procedures or ambiguous call for procedure group '%s' that match with the given arguments", expr_name);
gb_printf_err("\tGiven argument types -> (");
for_array(i, operands) {
Operand o = operands[i];
@@ -4542,10 +4431,10 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
}
gb_printf_err(")\n");
if (overload_count > 0) {
if (procs.count > 0) {
gb_printf_err("Did you mean to use one of the following:\n");
}
for (isize i = 0; i < overload_count; i++) {
for_array(i, procs) {
Entity *proc = procs[i];
TokenPos pos = proc->token.pos;
Type *t = base_type(proc->type);
@@ -4562,12 +4451,12 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
// gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column);
gb_string_free(pt);
}
if (overload_count > 0) {
if (procs.count > 0) {
gb_printf_err("\n");
}
result_type = t_invalid;
} else if (valid_count > 1) {
error(operand->expr, "Ambiguous procedure call '%s' tha match with the given arguments", expr_name);
error(operand->expr, "Ambiguous procedure group call '%s' that match with the given arguments", expr_name);
gb_printf_err("\tGiven argument types -> (");
for_array(i, operands) {
Operand o = operands[i];
@@ -4606,11 +4495,8 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
proc_type = e->type;
CallArgumentData data = {};
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
if (data.gen_entity != nullptr) {
add_entity_use(c, ident, data.gen_entity);
} else {
add_entity_use(c, ident, e);
}
Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
add_entity_use(c, ident, entity_to_use);
return data;
}
} else {
@@ -4623,11 +4509,8 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
Entity *e = entity_of_ident(&c->info, ident);
CallArgumentData data = {};
CallArgumentError err = call_checker(c, call, proc_type, e, operands, CallArgumentMode_ShowErrors, &data);
if (data.gen_entity != nullptr) {
add_entity_use(c, ident, data.gen_entity);
} else {
add_entity_use(c, ident, e);
}
Entity *entity_to_use = data.gen_entity != nullptr ? data.gen_entity : e;
add_entity_use(c, ident, entity_to_use);
return data;
}
@@ -4953,7 +4836,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
}
Type *proc_type = base_type(operand->type);
if (operand->mode != Addressing_Overload) {
if (operand->mode != Addressing_ProcGroup) {
bool valid_type = (proc_type != nullptr) && is_type_proc(proc_type);
bool valid_mode = is_operand_value(*operand);
if (!valid_type || !valid_mode) {
@@ -5206,8 +5089,8 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
o->mode = Addressing_Constant;
case_end;
case_ast_node(pg, ProcGrouping, node);
error(node, "Illegal use of a procedure grouping");
case_ast_node(pg, ProcGroup, node);
error(node, "Illegal use of a procedure group");
o->mode = Addressing_Invalid;
case_end;
@@ -6205,7 +6088,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = gb_string_appendc(str, "---");
case_end;
case_ast_node(pg, ProcGrouping, node);
case_ast_node(pg, ProcGroup, node);
str = gb_string_appendc(str, "proc[");
for_array(i, pg->args) {
if (i > 0) str = gb_string_appendc(str, ", ");