// These return the bool first so you can check in a conditional, // rather than having to do '_, ok := ...' check_type_tag :: ($$T: Type, tag: Type_Info_Tag) -> bool, *Type_Info { #if is_constant(T) { info :: type_info(T); if info.type == tag return true, info; } else { info := T.(*Type_Info); if info.type == tag return true, info; } return false, null; } type_is_integer :: ($$T: Type) -> bool, *Type_Info_Integer { ok, info := check_type_tag(T, .INTEGER); return ok, info.(*Type_Info_Integer); } type_is_float :: ($$T: Type) -> bool, *Type_Info_Float { ok, info := check_type_tag(T, .FLOAT); return ok, info.(*Type_Info_Float); } type_is_scalar :: (t: Type) -> bool { return type_is_integer(t) || type_is_float(t); } type_is_array :: ($$T: Type) -> bool, *Type_Info_Array { ok, info := check_type_tag(T, .ARRAY); return ok, info.(*Type_Info_Array); } type_is_struct :: ($$T: Type) -> bool, *Type_Info_Struct { ok, info := check_type_tag(T, .STRUCT); return ok, info.(*Type_Info_Struct); } type_is_enum :: ($$T: Type) -> bool, *Type_Info_Enum { ok, info := check_type_tag(T, .ENUM); return ok, info.(*Type_Info_Enum); } enum_min :: (T: Type) -> int #expand { return #run -> int { ok, info := type_is_enum(T); assert(ok, "type given to enum_min must be an enum"); if info.values.count == 0 { return 0; } min := 0xFFFFFF_FFFFFF; for info.values if it < min { min = it; } return min; }; } enum_max :: (T: Type) -> int #expand { return #run -> int { ok, info := type_is_enum(T); assert(ok, "type given to enum_max must be an enum"); if info.values.count == 0 { return 0; } max := 0; for info.values if it > max { max = it; } return max; }; }