From 3703ca4df47134e0c274cf5096d14c9323331ff0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 9 Dec 2017 18:11:36 +0000 Subject: [PATCH] Explicit procedure group; Remove implicit procedure overloading --- core/math.odin | 6 +- examples/game.odin | 4 +- src/build_settings.cpp | 2 +- src/check_decl.cpp | 98 ++++++++++-- src/check_expr.cpp | 221 +++++++-------------------- src/check_stmt.cpp | 329 ++++++++++++++++++++--------------------- src/checker.cpp | 166 +++------------------ src/entity.cpp | 8 +- src/ir.cpp | 21 +-- src/main.cpp | 1 - src/map.cpp | 7 +- src/parser.cpp | 28 ++-- 12 files changed, 359 insertions(+), 532 deletions(-) diff --git a/core/math.odin b/core/math.odin index 54f44c1d0..3c66575fc 100644 --- a/core/math.odin +++ b/core/math.odin @@ -148,9 +148,10 @@ div :: proc[ ]; inverse :: proc[mat4_inverse, quat_inverse]; +dot :: proc[vec_dot, quat_dot]; +cross :: proc[cross2, cross3]; - -dot :: proc(a, b: $T/[$N]$E) -> E { +vec_dot :: proc(a, b: $T/[$N]$E) -> E { res: E; for i in 0..N { res += a[i] * b[i]; @@ -167,7 +168,6 @@ cross3 :: proc(a, b: $T/[3]$E) -> T { j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0); return T(i - j); } -cross :: proc[cross2, cross3]; length :: proc(v: $T/[$N]$E) -> E { return sqrt(dot(v, v)); } diff --git a/examples/game.odin b/examples/game.odin index 464c9d7d2..b0f4c990c 100644 --- a/examples/game.odin +++ b/examples/game.odin @@ -1,5 +1,5 @@ -import win32 "core:sys/windows.odin" when ODIN_OS == "windows"; -import wgl "core:sys/wgl.odin" when ODIN_OS == "windows"; +when ODIN_OS == "windows" do import win32 "core:sys/windows.odin"; +when ODIN_OS == "windows" import wgl "core:sys/wgl.odin"; import "core:fmt.odin"; import "core:math.odin"; import "core:os.odin"; diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 95c418839..7d7634806 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -308,7 +308,7 @@ String get_fullpath_core(gbAllocator a, String path) { } -String const ODIN_VERSION = str_lit("0.7.1"); +String const ODIN_VERSION = str_lit("0.8.0-dev"); String cross_compile_target = str_lit(""); String cross_compile_lib_dir = str_lit(""); diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 7b01c259e..817377baf 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -23,9 +23,9 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex } - if (operand->mode == Addressing_Overload) { + if (operand->mode == Addressing_ProcGroup) { if (e->type == nullptr) { - error(operand->expr, "Cannot determine type from overloaded procedure '%.*s'", LIT(operand->overload_entities[0]->token.string)); + error(operand->expr, "Cannot determine type from overloaded procedure '%.*s'", LIT(operand->proc_group->token.string)); } else { check_assignment(c, operand, e->type, str_lit("variable assignment")); if (operand->mode != Addressing_Type) { @@ -275,11 +275,15 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, e->type = t_invalid; return; - case Addressing_Overload: - e->kind = Entity_Alias; - e->Alias.base = operand.overload_entities[0]; + case Addressing_ProcGroup: { + GB_ASSERT(operand.proc_group != nullptr); + GB_ASSERT(operand.proc_group->kind == Entity_ProcGroup); + + e->kind = Entity_ProcGroup; e->type = t_invalid; + gb_memcopy(&e->ProcGroup, &operand.proc_group->ProcGroup, gb_size_of(e->ProcGroup)); return; + } #endif } #if 1 @@ -708,11 +712,11 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count check_init_variables(c, entities, entity_count, init_expr_list, context_name); } -void check_proc_grouping_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { - GB_ASSERT(pg_entity->kind == Entity_ProcedureGrouping); - auto *pge = &pg_entity->ProcedureGrouping; +void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { + GB_ASSERT(pg_entity->kind == Entity_ProcGroup); + auto *pge = &pg_entity->ProcGroup; - ast_node(pg, ProcGrouping, d->init_expr); + ast_node(pg, ProcGroup, d->init_expr); array_init(&pge->entities, c->allocator, pg->args.count); @@ -731,22 +735,87 @@ void check_proc_grouping_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { e = check_selector(c, &o, arg, nullptr); } if (e == nullptr) { - error(arg, "Expected a valid entity name in procedure grouping"); + error(arg, "Expected a valid entity name in procedure group"); continue; } - if (e->kind != Entity_Procedure) { + if (e->kind == Entity_Variable) { + if (!is_type_proc(e->type)) { + error(arg, "Expected a procedure variable"); + continue; + } + } else if (e->kind != Entity_Procedure) { error(arg, "Expected a procedure entity"); continue; } if (ptr_set_exists(&entity_map, e)) { - error(arg, "Previous use of `%.*s` in procedure grouping", LIT(e->token.string)); + error(arg, "Previous use of `%.*s` in procedure group", LIT(e->token.string)); continue; } ptr_set_add(&entity_map, e); array_add(&pge->entities, e); } + + for_array(j, pge->entities) { + Entity *p = pge->entities[j]; + if (p->type == t_invalid) { + // NOTE(bill): This invalid overload has already been handled + continue; + } + + String name = p->token.string; + + for (isize k = j+1; k < pge->entities.count; k++) { + Entity *q = pge->entities[k]; + GB_ASSERT(p != q); + + bool is_invalid = false; + + TokenPos pos = q->token.pos; + + if (q->type == nullptr || q->type == t_invalid) { + continue; + } + + ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type); + switch (kind) { + case ProcOverload_Identical: + error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name)); + is_invalid = true; + break; + // case ProcOverload_CallingConvention: + // error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name)); + // is_invalid = true; + // break; + case ProcOverload_ParamVariadic: + error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name)); + is_invalid = true; + break; + case ProcOverload_ResultCount: + case ProcOverload_ResultTypes: + error(p->token, "Overloaded procedure '%.*s' as the same parameters but different results in this scope", LIT(name)); + is_invalid = true; + break; + case ProcOverload_Polymorphic: + #if 0 + error(p->token, "Overloaded procedure '%.*s' has a polymorphic counterpart in this scope which is not allowed", LIT(name)); + is_invalid = true; + #endif + break; + case ProcOverload_ParamCount: + case ProcOverload_ParamTypes: + // This is okay :) + break; + + } + + if (is_invalid) { + gb_printf_err("\tprevious procedure at %.*s(%td:%td)\n", LIT(pos.file), pos.line, pos.column); + q->type = t_invalid; + } + } + } } void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { @@ -787,9 +856,8 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { check_proc_decl(c, e, d); break; - case Entity_ProcedureGrouping: - // error(e->token, "Procedure groupings are not yet supported"); - check_proc_grouping_decl(c, e, d); + case Entity_ProcGroup: + check_proc_group_decl(c, e, d); break; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index a81022d87..0c3292fb8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -127,14 +127,6 @@ void check_scope_decls(Checker *c, Array 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 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 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 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 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, ", "); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 6dd2bcdaa..17d50fb6d 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -30,7 +30,7 @@ void check_stmt_list(Checker *c, Array stmts, u32 flags) { if (i+1 < max) { switch (n->kind) { case AstNode_ReturnStmt: - error(n, "Statements after this 'return' are never executed"); + error(n, "Statements after this 'return' are never execu"); break; case AstNode_BranchStmt: @@ -182,7 +182,7 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) { return nullptr; } if (rhs->type == t_invalid && - rhs->mode != Addressing_Overload && + rhs->mode != Addressing_ProcGroup && rhs->mode != Addressing_Builtin) { return nullptr; } @@ -203,17 +203,16 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) { bool used = false; if (lhs->mode == Addressing_Invalid || - (lhs->type == t_invalid && lhs->mode != Addressing_Overload)) { + (lhs->type == t_invalid && lhs->mode != Addressing_ProcGroup)) { return nullptr; } - if (rhs->mode == Addressing_Overload) { - isize overload_count = rhs->overload_count; - Entity **procs = rhs->overload_entities; - GB_ASSERT(procs != nullptr && overload_count > 0); + if (rhs->mode == Addressing_ProcGroup) { + Array procs = proc_group_entities(c, *rhs); + GB_ASSERT(procs.count > 0); // 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; @@ -232,8 +231,7 @@ Type *check_assignment_variable(Checker *c, Operand *lhs, Operand *rhs) { // HACK TODO(bill): Should the entities be freed as it's technically a leak rhs->mode = Addressing_Value; rhs->type = e->type; - rhs->overload_count = 0; - rhs->overload_entities = nullptr; + rhs->proc_group = nullptr; } } else { if (node->kind == AstNode_Ident) { @@ -1680,176 +1678,177 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case_end; case_ast_node(vd, ValueDecl, node); - if (!vd->is_mutable) { - break; - } - Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); - isize entity_count = 0; + if (vd->is_mutable) { + Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); + isize entity_count = 0; - for_array(i, vd->names) { - AstNode *name = vd->names[i]; - Entity *entity = nullptr; - if (name->kind != AstNode_Ident) { - error(name, "A variable declaration must be an identifier"); - } else { - Token token = name->Ident.token; - String str = token.string; - Entity *found = nullptr; - // NOTE(bill): Ignore assignments to '_' - if (!is_blank_ident(str)) { - found = current_scope_lookup_entity(c->context.scope, str); - } - if (found == nullptr) { - entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false); - entity->identifier = name; - - AstNode *fl = c->context.foreign_context.curr_library; - if (fl != nullptr) { - GB_ASSERT(fl->kind == AstNode_Ident); - entity->Variable.is_foreign = true; - entity->Variable.foreign_library_ident = fl; - } + for_array(i, vd->names) { + AstNode *name = vd->names[i]; + Entity *entity = nullptr; + if (name->kind != AstNode_Ident) { + error(name, "A variable declaration must be an identifier"); } else { - TokenPos pos = found->token.pos; - error(token, - "Redeclaration of '%.*s' in this scope\n" - "\tat %.*s(%td:%td)", - LIT(str), LIT(pos.file), pos.line, pos.column); - entity = found; - } - } - if (entity == nullptr) { - entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name)); - } - entity->parent_proc_decl = c->context.curr_proc_decl; - entities[entity_count++] = entity; - } + Token token = name->Ident.token; + String str = token.string; + Entity *found = nullptr; + // NOTE(bill): Ignore assignments to '_' + if (!is_blank_ident(str)) { + found = current_scope_lookup_entity(c->context.scope, str); + } + if (found == nullptr) { + entity = make_entity_variable(c->allocator, c->context.scope, token, nullptr, false); + entity->identifier = name; - Type *init_type = nullptr; - if (vd->type != nullptr) { - init_type = check_type(c, vd->type, nullptr); - if (init_type == nullptr) { - init_type = t_invalid; - } else if (is_type_polymorphic(base_type(init_type))) { - gbString str = type_to_string(init_type); - error(vd->type, "Invalid use of a polymorphic type '%s' in variable declaration", str); - gb_string_free(str); - init_type = t_invalid; - } else if (is_type_empty_union(init_type)) { - gbString str = type_to_string(init_type); - error(vd->type, "An empty union '%s' cannot be instantiated in variable declaration", str); - gb_string_free(str); - init_type = t_invalid; - } - } - - - // TODO NOTE(bill): This technically checks things multple times - AttributeContext ac = make_attribute_context(c->context.foreign_context.link_prefix); - check_decl_attributes(c, vd->attributes, var_decl_attribute, &ac); - - for (isize i = 0; i < entity_count; i++) { - Entity *e = entities[i]; - GB_ASSERT(e != nullptr); - if (e->flags & EntityFlag_Visited) { - e->type = t_invalid; - continue; - } - e->flags |= EntityFlag_Visited; - - if (e->type == nullptr) { - e->type = init_type; - } - ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix); - e->Variable.thread_local_model = ac.thread_local_model; - - if (ac.link_name.len > 0) { - e->Variable.link_name = ac.link_name; - } - } - - check_arity_match(c, vd); - check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration")); - - for (isize i = 0; i < entity_count; i++) { - Entity *e = entities[i]; - if (e->Variable.is_foreign) { - if (vd->values.count > 0) { - error(e->token, "A foreign variable declaration cannot have a default value"); - } - - String name = e->token.string; - if (e->Variable.link_name.len > 0) { - name = e->Variable.link_name; - } - - if (vd->values.count > 0) { - error(e->token, "A foreign variable declaration cannot have a default value"); - } - init_entity_foreign_library(c, e); - - auto *fp = &c->info.foreigns; - HashKey key = hash_string(name); - Entity **found = map_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - Type *this_type = base_type(e->type); - Type *other_type = base_type(f->type); - if (!are_types_identical(this_type, other_type)) { - error(e->token, - "Foreign entity '%.*s' previously declared elsewhere with a different type\n" + AstNode *fl = c->context.foreign_context.curr_library; + if (fl != nullptr) { + GB_ASSERT(fl->kind == AstNode_Ident); + entity->Variable.is_foreign = true; + entity->Variable.foreign_library_ident = fl; + } + } else { + TokenPos pos = found->token.pos; + error(token, + "Redeclaration of '%.*s' in this scope\n" "\tat %.*s(%td:%td)", - LIT(name), LIT(pos.file), pos.line, pos.column); + LIT(str), LIT(pos.file), pos.line, pos.column); + entity = found; } - } else { - map_set(fp, key, e); } - } - add_entity(c, c->context.scope, e->identifier, e); - } - - if (vd->is_using != 0) { - Token token = ast_node_token(node); - if (vd->type != nullptr && entity_count > 1) { - error(token, "'using' can only be applied to one variable of the same type"); - // TODO(bill): Should a 'continue' happen here? + if (entity == nullptr) { + entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name)); + } + entity->parent_proc_decl = c->context.curr_proc_decl; + entities[entity_count++] = entity; } - for (isize entity_index = 0; entity_index < entity_count; entity_index++) { - Entity *e = entities[entity_index]; - if (e == nullptr) { - continue; + Type *init_type = nullptr; + if (vd->type != nullptr) { + init_type = check_type(c, vd->type, nullptr); + if (init_type == nullptr) { + init_type = t_invalid; + } else if (is_type_polymorphic(base_type(init_type))) { + gbString str = type_to_string(init_type); + error(vd->type, "Invalid use of a polymorphic type '%s' in variable declaration", str); + gb_string_free(str); + init_type = t_invalid; + } else if (is_type_empty_union(init_type)) { + gbString str = type_to_string(init_type); + error(vd->type, "An empty union '%s' cannot be instantiated in variable declaration", str); + gb_string_free(str); + init_type = t_invalid; } - if (e->kind != Entity_Variable) { - continue; - } - bool is_immutable = e->Variable.is_immutable; - String name = e->token.string; - Type *t = base_type(type_deref(e->type)); + } - if (is_blank_ident(name)) { - error(token, "'using' cannot be applied variable declared as '_'"); - } else if (is_type_struct(t) || is_type_raw_union(t)) { - Scope *scope = scope_of_node(&c->info, t->Struct.node); - for_array(i, scope->elements.entries) { - Entity *f = scope->elements.entries[i].value; - if (f->kind == Entity_Variable) { - Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type); - uvar->Variable.is_immutable = is_immutable; - Entity *prev = scope_insert_entity(c->context.scope, uvar); - if (prev != nullptr) { - error(token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(name), LIT(prev->token.string)); - return; + + // TODO NOTE(bill): This technically checks things multple times + AttributeContext ac = make_attribute_context(c->context.foreign_context.link_prefix); + check_decl_attributes(c, vd->attributes, var_decl_attribute, &ac); + + for (isize i = 0; i < entity_count; i++) { + Entity *e = entities[i]; + GB_ASSERT(e != nullptr); + if (e->flags & EntityFlag_Visited) { + e->type = t_invalid; + continue; + } + e->flags |= EntityFlag_Visited; + + if (e->type == nullptr) { + e->type = init_type; + } + ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix); + e->Variable.thread_local_model = ac.thread_local_model; + + if (ac.link_name.len > 0) { + e->Variable.link_name = ac.link_name; + } + } + + check_arity_match(c, vd); + check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration")); + + for (isize i = 0; i < entity_count; i++) { + Entity *e = entities[i]; + if (e->Variable.is_foreign) { + if (vd->values.count > 0) { + error(e->token, "A foreign variable declaration cannot have a default value"); + } + + String name = e->token.string; + if (e->Variable.link_name.len > 0) { + name = e->Variable.link_name; + } + + if (vd->values.count > 0) { + error(e->token, "A foreign variable declaration cannot have a default value"); + } + init_entity_foreign_library(c, e); + + auto *fp = &c->info.foreigns; + HashKey key = hash_string(name); + Entity **found = map_get(fp, key); + if (found) { + Entity *f = *found; + TokenPos pos = f->token.pos; + Type *this_type = base_type(e->type); + Type *other_type = base_type(f->type); + if (!are_types_identical(this_type, other_type)) { + error(e->token, + "Foreign entity '%.*s' previously declared elsewhere with a different type\n" + "\tat %.*s(%td:%td)", + LIT(name), LIT(pos.file), pos.line, pos.column); + } + } else { + map_set(fp, key, e); + } + } + add_entity(c, c->context.scope, e->identifier, e); + } + + if (vd->is_using != 0) { + Token token = ast_node_token(node); + if (vd->type != nullptr && entity_count > 1) { + error(token, "'using' can only be applied to one variable of the same type"); + // TODO(bill): Should a 'continue' happen here? + } + + for (isize entity_index = 0; entity_index < entity_count; entity_index++) { + Entity *e = entities[entity_index]; + if (e == nullptr) { + continue; + } + if (e->kind != Entity_Variable) { + continue; + } + bool is_immutable = e->Variable.is_immutable; + String name = e->token.string; + Type *t = base_type(type_deref(e->type)); + + if (is_blank_ident(name)) { + error(token, "'using' cannot be applied variable declared as '_'"); + } else if (is_type_struct(t) || is_type_raw_union(t)) { + Scope *scope = scope_of_node(&c->info, t->Struct.node); + for_array(i, scope->elements.entries) { + Entity *f = scope->elements.entries[i].value; + if (f->kind == Entity_Variable) { + Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type); + uvar->Variable.is_immutable = is_immutable; + Entity *prev = scope_insert_entity(c->context.scope, uvar); + if (prev != nullptr) { + error(token, "Namespace collision while 'using' '%.*s' of: %.*s", LIT(name), LIT(prev->token.string)); + return; + } } } + } else { + // NOTE(bill): skip the rest to remove extra errors + error(token, "'using' can only be applied to variables of type struct or raw_union"); + return; } - } else { - // NOTE(bill): skip the rest to remove extra errors - error(token, "'using' can only be applied to variables of type struct or raw_union"); - return; } } + } else { + // constant value declarations } case_end; } diff --git a/src/checker.cpp b/src/checker.cpp index 7c9f20135..16bc32ca1 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -120,7 +120,7 @@ enum AddressingMode { Addressing_Constant, // constant Addressing_Type, // type Addressing_Builtin, // built-in procedure - Addressing_Overload, // overloaded procedure + Addressing_ProcGroup, // procedure group (overloaded procedure) Addressing_MapIndex, // map index expression - // lhs: acts like a Variable // rhs: acts like OptionalOk @@ -138,8 +138,7 @@ struct Operand { ExactValue value; AstNode * expr; BuiltinProcId builtin_id; - isize overload_count; - Entity ** overload_entities; + Entity * proc_group; }; struct TypeAndValue { @@ -166,6 +165,8 @@ bool is_operand_undef(Operand o) { return o.mode == Addressing_Value && o.type == t_untyped_undef; } + + struct BlockLabel { String name; AstNode *label; // AstNode_Label; @@ -780,28 +781,10 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) { HashKey key = hash_string(name); Entity **found = map_get(&s->elements, key); -#ifndef DISABLE_PROCEDURE_OVERLOADING - // IMPORTANT NOTE(bill): Procedure overloading code - Entity *prev = nullptr; - if (found) { - prev = *found; - if (prev->kind != Entity_Procedure || - entity->kind != Entity_Procedure) { - return prev; - } - } - - if (prev != nullptr && entity->kind == Entity_Procedure) { - multi_map_insert(&s->elements, key, entity); - } else { - map_set(&s->elements, key, entity); - } -#else if (found) { return *found; } map_set(&s->elements, key, entity); -#endif if (entity->scope == nullptr) { entity->scope = s; } @@ -1620,6 +1603,18 @@ Type *find_core_type(Checker *c, String name) { void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type); +Array proc_group_entities(Checker *c, Operand o) { + Array procs = {}; + if (o.mode == Addressing_ProcGroup) { + GB_ASSERT(o.proc_group != nullptr); + if (o.proc_group->kind == Entity_ProcGroup) { + check_entity_decl(c, o.proc_group, nullptr, nullptr); + return o.proc_group->ProcGroup.entities; + } + } + return procs; +} + void init_preload(Checker *c) { if (t_type_info == nullptr) { Entity *type_info_entity = find_core_entity(c, str_lit("Type_Info")); @@ -1736,118 +1731,6 @@ void check_collect_entities(Checker *c, Array nodes); void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws); void check_delayed_file_import_entity(Checker *c, AstNode *decl); -bool check_is_entity_overloaded(Entity *e) { - if (e->kind != Entity_Procedure) { - return false; - } - Scope *s = e->scope; - HashKey key = hash_string(e->token.string); - isize overload_count = multi_map_count(&s->elements, key); - return overload_count > 1; -} - -void check_procedure_overloading(Checker *c, Entity *e) { - GB_ASSERT(e->kind == Entity_Procedure); - if (e->type == t_invalid) { - return; - } - if (e->Procedure.overload_kind != Overload_Unknown) { - // NOTE(bill): The overloading has already been handled - return; - } - - - // NOTE(bill): Procedures call only overload other procedures in the same scope - - String name = e->token.string; - HashKey key = hash_string(name); - Scope *s = e->scope; - isize overload_count = multi_map_count(&s->elements, key); - GB_ASSERT(overload_count >= 1); - if (overload_count == 1) { - e->Procedure.overload_kind = Overload_No; - return; - } - GB_ASSERT(overload_count > 1); - - - gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); - Entity **procs = gb_alloc_array(c->tmp_allocator, Entity *, overload_count); - multi_map_get_all(&s->elements, key, procs); - - for (isize j = 0; j < overload_count; j++) { - Entity *p = procs[j]; - if (p->type == t_invalid) { - // NOTE(bill): This invalid overload has already been handled - continue; - } - - String name = p->token.string; - - GB_ASSERT(p->kind == Entity_Procedure); - for (isize k = j+1; k < overload_count; k++) { - Entity *q = procs[k]; - GB_ASSERT(p != q); - - bool is_invalid = false; - GB_ASSERT(q->kind == Entity_Procedure); - - TokenPos pos = q->token.pos; - - if (q->type == nullptr || q->type == t_invalid) { - continue; - } - - ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type); - switch (kind) { - case ProcOverload_Identical: - error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name)); - is_invalid = true; - break; - // case ProcOverload_CallingConvention: - // error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name)); - // is_invalid = true; - // break; - case ProcOverload_ParamVariadic: - error(p->token, "Overloaded procedure '%.*s' as the same type as another procedure in this scope", LIT(name)); - is_invalid = true; - break; - case ProcOverload_ResultCount: - case ProcOverload_ResultTypes: - error(p->token, "Overloaded procedure '%.*s' as the same parameters but different results in this scope", LIT(name)); - is_invalid = true; - break; - case ProcOverload_Polymorphic: - #if 0 - error(p->token, "Overloaded procedure '%.*s' has a polymorphic counterpart in this scope which is not allowed", LIT(name)); - is_invalid = true; - #endif - break; - case ProcOverload_ParamCount: - case ProcOverload_ParamTypes: - // This is okay :) - break; - - } - - if (is_invalid) { - gb_printf_err("\tprevious procedure at %.*s(%td:%td)\n", LIT(pos.file), pos.line, pos.column); - q->type = t_invalid; - } - } - } - - for (isize j = 0; j < overload_count; j++) { - Entity *p = procs[j]; - if (p->type != t_invalid) { - p->Procedure.overload_kind = Overload_Yes; - } - } - - gb_temp_arena_memory_end(tmp); -} - - struct AttributeContext { String link_name; String link_prefix; @@ -2259,11 +2142,11 @@ void check_collect_value_decl(Checker *c, AstNode *decl) { } d->proc_lit = init; d->type_expr = pl->type; - } else if (init->kind == AstNode_ProcGrouping) { - ast_node(pg, ProcGrouping, init); - e = make_entity_procedure_grouping(c->allocator, d->scope, token, nullptr); + } else if (init->kind == AstNode_ProcGroup) { + ast_node(pg, ProcGroup, init); + e = make_entity_proc_group(c->allocator, d->scope, token, nullptr); if (fl != nullptr) { - error(name, "Procedure groupings are not allowed within a foreign block"); + error(name, "Procedure groups are not allowed within a foreign block"); } d->init_expr = init; } else { @@ -2447,15 +2330,6 @@ void check_all_global_entities(Checker *c) { init_preload(c); } } - - for_array(i, c->info.entities.entries) { - auto *entry = &c->info.entities.entries[i]; - Entity *e = cast(Entity *)entry->key.ptr; - if (e->kind != Entity_Procedure) { - continue; - } - check_procedure_overloading(c, e); - } } diff --git a/src/entity.cpp b/src/entity.cpp index ef49c4d0e..ff3fd5c20 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -10,7 +10,7 @@ struct DeclInfo; ENTITY_KIND(Variable) \ ENTITY_KIND(TypeName) \ ENTITY_KIND(Procedure) \ - ENTITY_KIND(ProcedureGrouping) \ + ENTITY_KIND(ProcGroup) \ ENTITY_KIND(Builtin) \ ENTITY_KIND(Alias) \ ENTITY_KIND(ImportName) \ @@ -110,7 +110,7 @@ struct Entity { } Procedure; struct { Array entities; - } ProcedureGrouping; + } ProcGroup; struct { i32 id; } Builtin; @@ -248,8 +248,8 @@ Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *si return entity; } -Entity *make_entity_procedure_grouping(gbAllocator a, Scope *scope, Token token, Type *type) { - Entity *entity = alloc_entity(a, Entity_ProcedureGrouping, scope, token, type); +Entity *make_entity_proc_group(gbAllocator a, Scope *scope, Token token, Type *type) { + Entity *entity = alloc_entity(a, Entity_ProcGroup, scope, token, type); return entity; } diff --git a/src/ir.cpp b/src/ir.cpp index f1b6a5ee0..c869e550b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3620,7 +3620,7 @@ String ir_mangle_name(irGen *s, String path, Entity *e) { isize base_len = ext-1-base; isize max_len = base_len + 1 + 1 + 10 + 1 + name.len; - bool require_suffix_id = check_is_entity_overloaded(e) || is_type_polymorphic(e->type); + bool require_suffix_id = is_type_polymorphic(e->type); if (require_suffix_id) { max_len += 21; } @@ -8304,19 +8304,22 @@ void ir_gen_tree(irGen *s) { } for_array(i, info->entities.entries) { - auto *entry = &info->entities.entries[i]; - Entity *e = cast(Entity *)entry->key.ptr; - String name = e->token.string; - DeclInfo *decl = entry->value; - Scope *scope = e->scope; + auto * entry = &info->entities.entries[i]; + Entity * e = cast(Entity *)entry->key.ptr; + String name = e->token.string; + DeclInfo *decl = entry->value; + Scope * scope = e->scope; if (!scope->is_file) { continue; } - if (e->kind == Entity_Variable || e->kind == Entity_ProcedureGrouping) { + switch (e->kind) { + case Entity_Variable: // NOTE(bill): Handled above as it requires a specific load order continue; + case Entity_ProcGroup: + continue; } bool polymorphic_struct = false; @@ -8341,8 +8344,6 @@ void ir_gen_tree(irGen *s) { } else { name = ir_mangle_name(s, e->token.pos.file, e); } - } else if (check_is_entity_overloaded(e)) { - name = ir_mangle_name(s, e->token.pos.file, e); } ir_add_entity_name(m, e, name); @@ -8373,7 +8374,7 @@ void ir_gen_tree(irGen *s) { ir_module_add_value(m, e, p); HashKey hash_name = hash_string(name); if (map_get(&m->members, hash_name) == nullptr) { - multi_map_insert(&m->members, hash_name, p); + map_set(&m->members, hash_name, p); } break; } diff --git a/src/main.cpp b/src/main.cpp index 7f24a7d4d..5df246e7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,4 @@ #define ALLOW_ARRAY_PROGRAMMING -// #define DISABLE_PROCEDURE_OVERLOADING // #define NO_ARRAY_BOUNDS_CHECK diff --git a/src/map.cpp b/src/map.cpp index 92840a480..152b8cb39 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2,6 +2,8 @@ // with the use of the `multi_*` procedures. // TODO(bill): I should probably allow the `multi_map_*` stuff to be #ifdefed out +#define MAP_ENABLE_MULTI_MAP 1 + #ifndef MAP_UTIL_STUFF #define MAP_UTIL_STUFF // NOTE(bill): This util stuff is the same for every `Map` @@ -110,6 +112,7 @@ template void map_clear (Map *h); template void map_grow (Map *h); template void map_rehash (Map *h, isize new_count); +#if MAP_ENABLE_MULTI_MAP // Mutlivalued map procedure template MapEntry * multi_map_find_first(Map *h, HashKey key); template MapEntry * multi_map_find_next (Map *h, MapEntry *e); @@ -119,7 +122,7 @@ template void multi_map_get_all (Map *h, HashKey key, T *item template void multi_map_insert (Map *h, HashKey key, T const &value); template void multi_map_remove (Map *h, HashKey key, MapEntry *e); template void multi_map_remove_all(Map *h, HashKey key); - +#endif template gb_inline void map_init(Map *h, gbAllocator a, isize capacity) { @@ -291,7 +294,7 @@ gb_inline void map_clear(Map *h) { } -#if 1 +#if MAP_ENABLE_MULTI_MAP template MapEntry *multi_map_find_first(Map *h, HashKey key) { isize i = map__find(h, key).entry_index; diff --git a/src/parser.cpp b/src/parser.cpp index 189e13f32..704833170 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -164,7 +164,7 @@ Array make_ast_node_array(AstFile *f, isize init_capacity = 8) { Token token; \ AstNode *expr; \ }) \ - AST_NODE_KIND(ProcGrouping, "procedure grouping", struct { \ + AST_NODE_KIND(ProcGroup, "procedure group", struct { \ Token token; \ Token open; \ Token close; \ @@ -540,7 +540,7 @@ Token ast_node_token(AstNode *node) { case AstNode_Undef: return node->Undef; case AstNode_BasicLit: return node->BasicLit; case AstNode_BasicDirective: return node->BasicDirective.token; - case AstNode_ProcGrouping: return node->ProcGrouping.token; + case AstNode_ProcGroup: return node->ProcGroup.token; case AstNode_ProcLit: return ast_node_token(node->ProcLit.type); case AstNode_CompoundLit: if (node->CompoundLit.type != nullptr) { @@ -669,8 +669,8 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) { case AstNode_Ellipsis: n->Ellipsis.expr = clone_ast_node(a, n->Ellipsis.expr); break; - case AstNode_ProcGrouping: - n->ProcGrouping.args = clone_ast_node_array(a, n->ProcGrouping.args); + case AstNode_ProcGroup: + n->ProcGroup.args = clone_ast_node_array(a, n->ProcGroup.args); break; case AstNode_ProcLit: n->ProcLit.type = clone_ast_node(a, n->ProcLit.type); @@ -1121,12 +1121,12 @@ AstNode *ast_ellipsis(AstFile *f, Token token, AstNode *expr) { } -AstNode *ast_proc_grouping(AstFile *f, Token token, Token open, Token close, Array args) { - AstNode *result = make_ast_node(f, AstNode_ProcGrouping); - result->ProcGrouping.token = token; - result->ProcGrouping.open = open; - result->ProcGrouping.close = close; - result->ProcGrouping.args = args; +AstNode *ast_proc_group(AstFile *f, Token token, Token open, Token close, Array args) { + AstNode *result = make_ast_node(f, AstNode_ProcGroup); + result->ProcGroup.token = token; + result->ProcGroup.open = open; + result->ProcGroup.close = close; + result->ProcGroup.args = args; return result; } @@ -2266,11 +2266,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) { return expr; } break; - // Parse Procedure Type or Literal or Grouping + // Parse Procedure Type or Literal or Group case Token_proc: { Token token = expect_token(f, Token_proc); - if (f->curr_token.kind == Token_OpenBracket) { // ProcGrouping + if (f->curr_token.kind == Token_OpenBracket) { // ProcGroup Token open = expect_token(f, Token_OpenBracket); Array args = {}; @@ -2289,10 +2289,10 @@ AstNode *parse_operand(AstFile *f, bool lhs) { Token close = expect_token(f, Token_CloseBracket); if (args.count == 0) { - syntax_error(token, "Expected a least 1 argument in a procedure grouping"); + syntax_error(token, "Expected a least 1 argument in a procedure group"); } - return ast_proc_grouping(f, token, open, close, args); + return ast_proc_group(f, token, open, close, args); } AstNode *type = parse_proc_type(f, token);