mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-26 23:44:58 -07:00
Fix array lengths with enum value counts.
This commit is contained in:
@@ -107,23 +107,24 @@ type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using
|
||||
type_is_dereferenceable :: proc($T: typeid) -> bool ---
|
||||
type_is_valid_map_key :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_is_named :: proc($T: typeid) -> bool ---
|
||||
type_is_pointer :: proc($T: typeid) -> bool ---
|
||||
type_is_opaque :: proc($T: typeid) -> bool ---
|
||||
type_is_array :: proc($T: typeid) -> bool ---
|
||||
type_is_slice :: proc($T: typeid) -> bool ---
|
||||
type_is_dynamic_array :: proc($T: typeid) -> bool ---
|
||||
type_is_map :: proc($T: typeid) -> bool ---
|
||||
type_is_struct :: proc($T: typeid) -> bool ---
|
||||
type_is_union :: proc($T: typeid) -> bool ---
|
||||
type_is_enum :: proc($T: typeid) -> bool ---
|
||||
type_is_proc :: proc($T: typeid) -> bool ---
|
||||
type_is_bit_field :: proc($T: typeid) -> bool ---
|
||||
type_is_bit_field_value :: proc($T: typeid) -> bool ---
|
||||
type_is_bit_set :: proc($T: typeid) -> bool ---
|
||||
type_is_simd_vector :: proc($T: typeid) -> bool ---
|
||||
type_is_named :: proc($T: typeid) -> bool ---
|
||||
type_is_pointer :: proc($T: typeid) -> bool ---
|
||||
type_is_opaque :: proc($T: typeid) -> bool ---
|
||||
type_is_array :: proc($T: typeid) -> bool ---
|
||||
type_is_enumerated_array :: proc($T: typeid) -> bool ---
|
||||
type_is_slice :: proc($T: typeid) -> bool ---
|
||||
type_is_dynamic_array :: proc($T: typeid) -> bool ---
|
||||
type_is_map :: proc($T: typeid) -> bool ---
|
||||
type_is_struct :: proc($T: typeid) -> bool ---
|
||||
type_is_union :: proc($T: typeid) -> bool ---
|
||||
type_is_enum :: proc($T: typeid) -> bool ---
|
||||
type_is_proc :: proc($T: typeid) -> bool ---
|
||||
type_is_bit_field :: proc($T: typeid) -> bool ---
|
||||
type_is_bit_field_value :: proc($T: typeid) -> bool ---
|
||||
type_is_bit_set :: proc($T: typeid) -> bool ---
|
||||
type_is_simd_vector :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_has_nil :: proc($T: typeid) -> bool ---
|
||||
type_has_nil :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) ---
|
||||
type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) ---
|
||||
|
||||
@@ -161,6 +161,8 @@ void check_init_constant(CheckerContext *ctx, Entity *e, Operand *operand) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (!is_type_constant_type(operand->type)) {
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
error(operand->expr, "Invalid constant type: '%s'", type_str);
|
||||
@@ -170,6 +172,7 @@ void check_init_constant(CheckerContext *ctx, Entity *e, Operand *operand) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e->type == nullptr) { // NOTE(bill): type inference
|
||||
e->type = operand->type;
|
||||
|
||||
@@ -3144,6 +3144,74 @@ bool check_index_value(CheckerContext *c, bool open_range, Ast *index_value, i64
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ExactValue get_constant_field(CheckerContext *c, Operand const *operand, Selection sel, bool *success_) {
|
||||
if (operand->mode != Addressing_Constant) {
|
||||
if (success_) *success_ = false;
|
||||
return empty_exact_value;
|
||||
}
|
||||
|
||||
if (sel.indirect) {
|
||||
if (success_) *success_ = false;
|
||||
return empty_exact_value;
|
||||
}
|
||||
|
||||
if (sel.index.count == 0) {
|
||||
if (success_) *success_ = false;
|
||||
return empty_exact_value;
|
||||
}
|
||||
|
||||
|
||||
ExactValue value = operand->value;
|
||||
if (value.kind == ExactValue_Compound) {
|
||||
i32 depth = 0;
|
||||
while (sel.index.count > 0) {
|
||||
i32 index = sel.index[0];
|
||||
sel = sub_selection(sel, 1);
|
||||
|
||||
Ast *node = value.value_compound;
|
||||
switch (node->kind) {
|
||||
case_ast_node(cl, CompoundLit, node);
|
||||
if (cl->elems.count == 0) {
|
||||
if (success_) *success_ = true;
|
||||
return empty_exact_value;
|
||||
}
|
||||
|
||||
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||
GB_PANIC("TODO");
|
||||
} else {
|
||||
i32 count = (i32)cl->elems.count;
|
||||
if (count < index) {
|
||||
if (success_) *success_ = false;
|
||||
return empty_exact_value;
|
||||
}
|
||||
TypeAndValue tav = cl->elems[index]->tav;
|
||||
if (tav.mode == Addressing_Constant) {
|
||||
value = tav.value;
|
||||
} else {
|
||||
GB_ASSERT(is_type_untyped_nil(tav.type));
|
||||
value = tav.value;
|
||||
}
|
||||
}
|
||||
|
||||
case_end;
|
||||
|
||||
default:
|
||||
if (success_) *success_ = true;
|
||||
return empty_exact_value;
|
||||
}
|
||||
|
||||
depth += 1;
|
||||
}
|
||||
|
||||
if (success_) *success_ = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
if (success_) *success_ = true;
|
||||
return empty_exact_value;
|
||||
}
|
||||
|
||||
Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *type_hint) {
|
||||
ast_node(se, SelectorExpr, node);
|
||||
|
||||
@@ -3291,6 +3359,39 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
|
||||
}
|
||||
|
||||
if (expr_entity != nullptr && expr_entity->kind == Entity_Constant && entity->kind != Entity_Constant) {
|
||||
bool success = false;
|
||||
ExactValue field_value = get_constant_field(c, operand, sel, &success);
|
||||
if (success) {
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->expr = node;
|
||||
operand->value = field_value;
|
||||
operand->type = entity->type;
|
||||
return entity;
|
||||
}
|
||||
|
||||
gbString op_str = expr_to_string(op_expr);
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
gbString sel_str = expr_to_string(selector);
|
||||
error(op_expr, "Cannot access non-constant field '%s' from '%s'", sel_str, op_str);
|
||||
gb_string_free(sel_str);
|
||||
gb_string_free(type_str);
|
||||
gb_string_free(op_str);
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->expr = node;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (operand->mode == Addressing_Constant && entity->kind != Entity_Constant) {
|
||||
bool success = false;
|
||||
ExactValue field_value = get_constant_field(c, operand, sel, &success);
|
||||
if (success) {
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->expr = node;
|
||||
operand->value = field_value;
|
||||
operand->type = entity->type;
|
||||
return entity;
|
||||
}
|
||||
|
||||
gbString op_str = expr_to_string(op_expr);
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
gbString sel_str = expr_to_string(selector);
|
||||
@@ -3441,6 +3542,7 @@ BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_end - BuiltinProc__ty
|
||||
is_type_pointer,
|
||||
is_type_opaque,
|
||||
is_type_array,
|
||||
is_type_enumerated_array,
|
||||
is_type_slice,
|
||||
is_type_dynamic_array,
|
||||
|
||||
|
||||
+1
-1
@@ -3234,7 +3234,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
|
||||
|
||||
if (o.mode == Addressing_Type && o.type->kind == Type_Generic) {
|
||||
generic_type = o.type;
|
||||
} else if (is_type_enum(o.type)) {
|
||||
} else if (o.mode == Addressing_Type && is_type_enum(o.type)) {
|
||||
Type *index = o.type;
|
||||
Type *bt = base_type(index);
|
||||
GB_ASSERT(bt->kind == Type_Enum);
|
||||
|
||||
@@ -142,6 +142,7 @@ BuiltinProc__type_begin,
|
||||
BuiltinProc_type_is_pointer,
|
||||
BuiltinProc_type_is_opaque,
|
||||
BuiltinProc_type_is_array,
|
||||
BuiltinProc_type_is_enumerated_array,
|
||||
BuiltinProc_type_is_slice,
|
||||
BuiltinProc_type_is_dynamic_array,
|
||||
BuiltinProc_type_is_map,
|
||||
@@ -305,6 +306,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("type_is_pointer"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_opaque"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_array"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_enumerated_array"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_slice"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_dynamic_array"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_map"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
@@ -336,6 +336,14 @@ Selection selection_combine(Selection const &lhs, Selection const &rhs) {
|
||||
return new_sel;
|
||||
}
|
||||
|
||||
Selection sub_selection(Selection const &sel, isize offset) {
|
||||
Selection res = {};
|
||||
res.index.data = sel.index.data + offset;
|
||||
res.index.count = sel.index.count - offset;
|
||||
res.index.capacity = res.index.count;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_global Type basic_types[] = {
|
||||
|
||||
Reference in New Issue
Block a user