Browse Source

Add `intrinsics.type_has_shared_fields`

gingerBill 11 months ago
parent
commit
d0eaf7642d
3 changed files with 58 additions and 0 deletions
  1. 2 0
      base/intrinsics/intrinsics.odin
  2. 53 0
      src/check_builtin.cpp
  3. 3 0
      src/checker_builtin_procs.hpp

+ 2 - 0
base/intrinsics/intrinsics.odin

@@ -219,6 +219,8 @@ type_map_cell_info :: proc($T: typeid)           -> ^runtime.Map_Cell_Info ---
 type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
 type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
 
+type_has_shared_fields :: proc($U, $V: typeid) -> bool typeid where type_is_struct(U), type_is_struct(V) ---
+
 constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
 
 constant_log2 :: proc($v: $T) -> T where type_is_integer(T) ---

+ 53 - 0
src/check_builtin.cpp

@@ -5665,6 +5665,59 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
 			break;
 		}
 		break;
+
+	case BuiltinProc_type_has_shared_fields:
+		{
+			Type *u = check_type(c, ce->args[0]);
+			Type *ut = base_type(u);
+			if (ut == nullptr || ut == t_invalid) {
+				error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name));
+				return false;
+			}
+			if (ut->kind != Type_Struct || ut->Struct.soa_kind != StructSoa_None) {
+				gbString t = type_to_string(ut);
+				error(ce->args[0], "Expected a struct type for '%.*s', got %s", LIT(builtin_name), t);
+				gb_string_free(t);
+				return false;
+			}
+
+			Type *v = check_type(c, ce->args[1]);
+			Type *vt = base_type(v);
+			if (vt == nullptr || vt == t_invalid) {
+				error(ce->args[1], "Expected a type for '%.*s'", LIT(builtin_name));
+				return false;
+			}
+			if (vt->kind != Type_Struct || vt->Struct.soa_kind != StructSoa_None) {
+				gbString t = type_to_string(vt);
+				error(ce->args[1], "Expected a struct type for '%.*s', got %s", LIT(builtin_name), t);
+				gb_string_free(t);
+				return false;
+			}
+
+			bool is_shared = true;
+
+			for (Entity *v_field : vt->Struct.fields) {
+				bool found = false;
+				for (Entity *u_field : ut->Struct.fields) {
+					if (v_field->token.string == u_field->token.string &&
+					    are_types_identical(v_field->type, u_field->type)) {
+						found = true;
+						break;
+					}
+				}
+
+				if (!found) {
+					is_shared = false;
+					break;
+				}
+			}
+
+			operand->mode = Addressing_Constant;
+			operand->value = exact_value_bool(is_shared);
+			operand->type = t_untyped_bool;
+			break;
+		}
+
 	case BuiltinProc_type_field_type:
 		{
 			Operand op = {};

+ 3 - 0
src/checker_builtin_procs.hpp

@@ -313,6 +313,8 @@ BuiltinProc__type_simple_boolean_end,
 	BuiltinProc_type_map_info,
 	BuiltinProc_type_map_cell_info,
 
+	BuiltinProc_type_has_shared_fields,
+
 BuiltinProc__type_end,
 
 	BuiltinProc_procedure_of,
@@ -647,6 +649,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("type_map_info"),      1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 	{STR_LIT("type_map_cell_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 
+	{STR_LIT("type_has_shared_fields"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 
 	{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},