content: module Language.C.Analysis.TypeConversions (
      arithmeticConversion,
      floatConversion,
      intConversion
  ) where
  
  import Language.C.Analysis.SemRep
  
  -- | For an arithmetic operator, if the arguments are of the given
  --   types, return the type of the full expression.
  arithmeticConversion :: TypeName -> TypeName -> Maybe TypeName
  -- XXX: I'm assuming that double `op` complex float = complex
  -- double. The standard seems somewhat unclear on whether this is
  -- really the case.
  arithmeticConversion (TyComplex t1) (TyComplex t2) =
    Just $ TyComplex $ floatConversion t1 t2
  arithmeticConversion (TyComplex t1) (TyFloating t2) =
    Just $ TyComplex $ floatConversion t1 t2
  arithmeticConversion (TyFloating t1) (TyComplex t2) =
    Just $ TyComplex $ floatConversion t1 t2
  arithmeticConversion t1@(TyComplex _) (TyIntegral _) = Just t1
  arithmeticConversion (TyIntegral _) t2@(TyComplex _) = Just t2
  arithmeticConversion (TyFloating t1) (TyFloating t2) =
    Just $ TyFloating $ floatConversion t1 t2
  arithmeticConversion t1@(TyFloating _) (TyIntegral _) = Just t1
  arithmeticConversion (TyIntegral _) t2@(TyFloating _) = Just t2
  arithmeticConversion (TyIntegral t1) (TyIntegral t2) =
    Just $ TyIntegral $ intConversion t1 t2
  arithmeticConversion (TyEnum _) (TyEnum _) = Just $ TyIntegral TyInt
  arithmeticConversion (TyEnum _) t2 = Just $ t2
  arithmeticConversion t1 (TyEnum _) = Just $ t1
  arithmeticConversion _ _ = Nothing
  
  floatConversion :: FloatType -> FloatType -> FloatType
  floatConversion = max
  
  intConversion :: IntType -> IntType -> IntType
  intConversion t1 t2 = max TyInt (max t1 t2)
  
  