// @todo for jesse these should be PascalCase but I didn't want to give you an annoying merge conflict

TypeTagIs :: ($$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;
}

TypeIsInteger :: ($$T: Type) -> (bool, *Type_Info_Integer) {
   ok, info := TypeTagIs(T, .INTEGER);
   return ok, info.(*Type_Info_Integer);
}

TypeIsFloat :: ($$T: Type) -> (bool, *Type_Info_Float) {
   ok, info := TypeTagIs(T, .FLOAT);
   return ok, info.(*Type_Info_Float);
}

TypeIsScalar :: ($$T: Type) -> bool {
   return TypeIsInteger(T) || TypeIsFloat(T);
}

TypeIsArray :: ($$T: Type) -> (bool, *Type_Info_Array) {
   ok, info := TypeTagIs(T, .ARRAY);
   return ok, info.(*Type_Info_Array);
}

TypeIsStruct :: ($$T: Type) -> (bool, *Type_Info_Struct) {
   ok, info := TypeTagIs(T, .STRUCT);
   return ok, info.(*Type_Info_Struct);
}

TypeIsEnum :: ($$T: Type) -> (bool, *Type_Info_Enum) {
   ok, info := TypeTagIs(T, .ENUM);
   return ok, info.(*Type_Info_Enum);
}

TypeIsPointer :: ($$T: Type) -> (bool, *Type_Info_Pointer) {
   ok, info := TypeTagIs(T, .POINTER);
   return ok, info.(*Type_Info_Pointer);
}
