diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 974224ed2..880de73f5 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -32,6 +32,7 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool is_type_sliceable, is_type_comparable, is_type_simple_compare, + is_type_nearly_simple_compare, is_type_dereferenceable, is_type_valid_for_keys, is_type_valid_for_matrix_elems, @@ -6145,6 +6146,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_type_is_sliceable: case BuiltinProc_type_is_comparable: case BuiltinProc_type_is_simple_compare: + case BuiltinProc_type_is_nearly_simple_compare: case BuiltinProc_type_is_dereferenceable: case BuiltinProc_type_is_valid_map_key: case BuiltinProc_type_is_valid_matrix_elements: diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6723a7580..51fb5511b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6533,7 +6533,7 @@ gb_internal bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Sco Entity *e = entry.value; switch (e->kind) { case Entity_TypeName: { - if (print_count == 0) error_line("\n\tWith the following definitions:\n"); + // if (print_count == 0) error_line("\n\tWith the following definitions:\n"); gbString str = type_to_string(e->type); error_line("\t\t%.*s :: %s;\n", LIT(e->token.string), str); diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 8e135ab10..e9655e88a 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -264,6 +264,7 @@ BuiltinProc__type_simple_boolean_begin, BuiltinProc_type_is_sliceable, BuiltinProc_type_is_comparable, BuiltinProc_type_is_simple_compare, // easily compared using memcmp + BuiltinProc_type_is_nearly_simple_compare, // easily compared using memcmp (including floats) BuiltinProc_type_is_dereferenceable, BuiltinProc_type_is_valid_map_key, BuiltinProc_type_is_valid_matrix_elements, @@ -621,6 +622,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_is_sliceable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_comparable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_simple_compare"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_nearly_simple_compare"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_dereferenceable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_valid_map_key"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_valid_matrix_elements"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/types.cpp b/src/types.cpp index 2e696810d..9ffd10ca8 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2559,6 +2559,62 @@ gb_internal bool is_type_simple_compare(Type *t) { return false; } +// NOTE(bill): type can be easily compared using memcmp or contains a float +gb_internal bool is_type_nearly_simple_compare(Type *t) { + t = core_type(t); + switch (t->kind) { + case Type_Array: + return is_type_nearly_simple_compare(t->Array.elem); + + case Type_EnumeratedArray: + return is_type_nearly_simple_compare(t->EnumeratedArray.elem); + + case Type_Basic: + if (t->Basic.flags & (BasicFlag_SimpleCompare|BasicFlag_Numeric)) { + return true; + } + if (t->Basic.kind == Basic_typeid) { + return true; + } + return false; + + case Type_Pointer: + case Type_MultiPointer: + case Type_SoaPointer: + case Type_Proc: + case Type_BitSet: + return true; + + case Type_Matrix: + return is_type_nearly_simple_compare(t->Matrix.elem); + + case Type_Struct: + for_array(i, t->Struct.fields) { + Entity *f = t->Struct.fields[i]; + if (!is_type_nearly_simple_compare(f->type)) { + return false; + } + } + return true; + + case Type_Union: + for_array(i, t->Union.variants) { + Type *v = t->Union.variants[i]; + if (!is_type_nearly_simple_compare(v)) { + return false; + } + } + // make it dumb on purpose + return t->Union.variants.count == 1; + + case Type_SimdVector: + return is_type_nearly_simple_compare(t->SimdVector.elem); + + } + + return false; +} + gb_internal bool is_type_load_safe(Type *type) { GB_ASSERT(type != nullptr); type = core_type(core_array_type(type));