From 0a85d1af6b290d30bc4c171df5fddfef3d09bed6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 24 Aug 2018 22:28:00 +0100 Subject: [PATCH] Improve error messages for using on fields --- src/check_type.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index b6d99772e..28f3d539d 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1,5 +1,32 @@ -void populate_using_entity_scope(CheckerContext *ctx, Ast *node, Type *t) { +void populate_using_array_index(CheckerContext *ctx, Ast *node, AstField *field, Type *t, String name, i32 idx) { + t = base_type(t); + GB_ASSERT(t->kind == Type_Array); + Entity *e = scope_lookup_current(ctx->scope, name); + if (e != nullptr) { + gbString str = nullptr; + defer (gb_string_free(str)); + if (node != nullptr) { + str = expr_to_string(node); + } + if (str != nullptr) { + error(e->token, "'%.*s' is already declared in '%s'", LIT(name), str); + } else { + error(e->token, "'%.*s' is already declared", LIT(name)); + } + } else { + Token tok = make_token_ident(name); + if (field->names.count > 0) { + tok.pos = ast_token(field->names[0]).pos; + } else { + tok.pos = ast_token(field->type).pos; + } + Entity *f = alloc_entity_array_elem(nullptr, tok, t->Array.elem, idx); + add_entity(ctx->checker, ctx->scope, nullptr, f); + } +} + +void populate_using_entity_scope(CheckerContext *ctx, Ast *node, AstField *field, Type *t) { t = base_type(type_deref(t)); gbString str = nullptr; defer (gb_string_free(str)); @@ -11,7 +38,7 @@ void populate_using_entity_scope(CheckerContext *ctx, Ast *node, Type *t) { for_array(i, t->Struct.fields) { Entity *f = t->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable); - String name = f->token.string;; + String name = f->token.string; Entity *e = scope_lookup_current(ctx->scope, name); if (e != nullptr && name != "_") { // TODO(bill): Better type error @@ -23,10 +50,46 @@ void populate_using_entity_scope(CheckerContext *ctx, Ast *node, Type *t) { } else { add_entity(ctx->checker, ctx->scope, nullptr, f); if (f->flags & EntityFlag_Using) { - populate_using_entity_scope(ctx, node, f->type); + populate_using_entity_scope(ctx, node, field, f->type); } } } + } else if (t->kind == Type_BitField) { + for_array(i, t->BitField.fields) { + Entity *f = t->BitField.fields[i]; + String name = f->token.string; + Entity *e = scope_lookup_current(ctx->scope, name); + if (e != nullptr && name != "_") { + // TODO(bill): Better type error + if (str != nullptr) { + error(e->token, "'%.*s' is already declared in '%s'", LIT(name), str); + } else { + error(e->token, "'%.*s' is already declared", LIT(name)); + } + } else { + add_entity(ctx->checker, ctx->scope, nullptr, f); + } + } + } else if (t->kind == Type_Array && t->Array.count <= 4) { + Entity *e = nullptr; + String name = {}; + i32 idx = 0; + switch (t->Array.count) { + case 4: + populate_using_array_index(ctx, node, field, t, str_lit("w"), 3); + /*fallthrough*/ + case 3: + populate_using_array_index(ctx, node, field, t, str_lit("z"), 2); + /*fallthrough*/ + case 2: + populate_using_array_index(ctx, node, field, t, str_lit("y"), 1); + /*fallthrough*/ + case 1: + populate_using_array_index(ctx, node, field, t, str_lit("x"), 0); + /*fallthrough*/ + default: + break; + } } } @@ -122,7 +185,7 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array *fields continue; } - populate_using_entity_scope(ctx, node, type); + populate_using_entity_scope(ctx, node, p, type); } } }