mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
Add #partial tag for enumerated arrays to prevent common errors using non-contiguous enumerations
This commit is contained in:
@@ -1845,11 +1845,9 @@ constant_literal_expressions :: proc() {
|
||||
FOO_ARRAY_DEFAULTS :: [3]Foo{{}, {}, {}};
|
||||
fmt.println(FOO_ARRAY_DEFAULTS[2].x);
|
||||
|
||||
|
||||
|
||||
fmt.println("-------");
|
||||
|
||||
Baz :: enum{A=5, B, C, D=9};
|
||||
Baz :: enum{A=5, B, C, D};
|
||||
ENUM_ARRAY_CONST :: [Baz]int{.A .. .C = 1, .D = 16};
|
||||
|
||||
fmt.println(ENUM_ARRAY_CONST[.A]);
|
||||
@@ -1859,6 +1857,18 @@ constant_literal_expressions :: proc() {
|
||||
|
||||
fmt.println("-------");
|
||||
|
||||
Partial_Baz :: enum{A=5, B, C, D=16};
|
||||
#assert(len(Partial_Baz) < len(#partial [Partial_Baz]int));
|
||||
PARTIAL_ENUM_ARRAY_CONST :: #partial [Partial_Baz]int{.A .. .C = 1, .D = 16};
|
||||
|
||||
fmt.println(PARTIAL_ENUM_ARRAY_CONST[.A]);
|
||||
fmt.println(PARTIAL_ENUM_ARRAY_CONST[.B]);
|
||||
fmt.println(PARTIAL_ENUM_ARRAY_CONST[.C]);
|
||||
fmt.println(PARTIAL_ENUM_ARRAY_CONST[.D]);
|
||||
|
||||
fmt.println("-------");
|
||||
|
||||
|
||||
STRING_CONST :: "Hellope!";
|
||||
|
||||
fmt.println(STRING_CONST[0]);
|
||||
|
||||
@@ -3241,11 +3241,32 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
|
||||
|
||||
Type *t = alloc_type_enumerated_array(elem, index, bt->Enum.min_value, bt->Enum.max_value, Token_Invalid);
|
||||
|
||||
bool is_partial = false;
|
||||
if (at->tag != nullptr) {
|
||||
GB_ASSERT(at->tag->kind == Ast_BasicDirective);
|
||||
String name = at->tag->BasicDirective.name;
|
||||
error(at->tag, "Invalid tag applied to an enumerated array, got #%.*s", LIT(name));
|
||||
if (name == "partial") {
|
||||
is_partial = true;
|
||||
} else {
|
||||
error(at->tag, "Invalid tag applied to an enumerated array, got #%.*s", LIT(name));
|
||||
}
|
||||
}
|
||||
|
||||
if (t->EnumeratedArray.count != bt->Enum.fields.count) {
|
||||
if (!is_partial) {
|
||||
error(e, "Non-contiguous enumeration used as an index in an enumerated array");
|
||||
long long ea_count = cast(long long)t->EnumeratedArray.count;
|
||||
long long enum_count = cast(long long)t->Enum.fields.count;
|
||||
error_line("\tenumerated array length: %lld\n", ea_count);
|
||||
error_line("\tenum field count: %lld\n", enum_count);
|
||||
error_line("\tSuggestion: prepend #partial to the enumerated array to allow for non-named elements\n");
|
||||
if (2*enum_count < ea_count) {
|
||||
error_line("\tWarning: the number of named elements is much smaller than the length of the array, are you sure this is what you want?\n");
|
||||
error_line("\t this warning will be removed if #partial is applied\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*type = t;
|
||||
|
||||
goto array_end;
|
||||
|
||||
@@ -1759,6 +1759,17 @@ Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
break;
|
||||
}
|
||||
return original_type;
|
||||
} else if (name.string == "partial") {
|
||||
Ast *tag = ast_basic_directive(f, token, name.string);
|
||||
Ast *original_type = parse_type(f);
|
||||
Ast *type = unparen_expr(original_type);
|
||||
switch (type->kind) {
|
||||
case Ast_ArrayType: type->ArrayType.tag = tag; break;
|
||||
default:
|
||||
syntax_error(type, "Expected an enumerated array type after #%.*s, got %.*s", LIT(name.string), LIT(ast_strings[type->kind]));
|
||||
break;
|
||||
}
|
||||
return original_type;
|
||||
} else if (name.string == "bounds_check") {
|
||||
Ast *operand = parse_expr(f, lhs);
|
||||
operand->state_flags |= StateFlag_bounds_check;
|
||||
|
||||
Reference in New Issue
Block a user