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 :: TypeName -> TypeName -> Maybe TypeName
arithmeticConversion (TyComplex FloatType
t1) (TyComplex FloatType
t2) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatType -> TypeName
TyComplex forall a b. (a -> b) -> a -> b
$ FloatType -> FloatType -> FloatType
floatConversion FloatType
t1 FloatType
t2
arithmeticConversion (TyComplex FloatType
t1) (TyFloating FloatType
t2) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatType -> TypeName
TyComplex forall a b. (a -> b) -> a -> b
$ FloatType -> FloatType -> FloatType
floatConversion FloatType
t1 FloatType
t2
arithmeticConversion (TyFloating FloatType
t1) (TyComplex FloatType
t2) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatType -> TypeName
TyComplex forall a b. (a -> b) -> a -> b
$ FloatType -> FloatType -> FloatType
floatConversion FloatType
t1 FloatType
t2
arithmeticConversion t1 :: TypeName
t1@(TyComplex FloatType
_) (TyIntegral IntType
_) = forall a. a -> Maybe a
Just TypeName
t1
arithmeticConversion (TyIntegral IntType
_) t2 :: TypeName
t2@(TyComplex FloatType
_) = forall a. a -> Maybe a
Just TypeName
t2
arithmeticConversion (TyFloating FloatType
t1) (TyFloating FloatType
t2) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ FloatType -> TypeName
TyFloating forall a b. (a -> b) -> a -> b
$ FloatType -> FloatType -> FloatType
floatConversion FloatType
t1 FloatType
t2
arithmeticConversion t1 :: TypeName
t1@(TyFloating FloatType
_) (TyIntegral IntType
_) = forall a. a -> Maybe a
Just TypeName
t1
arithmeticConversion (TyIntegral IntType
_) t2 :: TypeName
t2@(TyFloating FloatType
_) = forall a. a -> Maybe a
Just TypeName
t2
arithmeticConversion (TyIntegral IntType
t1) (TyIntegral IntType
t2) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntType -> TypeName
TyIntegral forall a b. (a -> b) -> a -> b
$ IntType -> IntType -> IntType
intConversion IntType
t1 IntType
t2
arithmeticConversion (TyEnum EnumTypeRef
_) (TyEnum EnumTypeRef
_) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ IntType -> TypeName
TyIntegral IntType
TyInt
arithmeticConversion (TyEnum EnumTypeRef
_) TypeName
t2 = forall a. a -> Maybe a
Just TypeName
t2
arithmeticConversion TypeName
t1 (TyEnum EnumTypeRef
_) = forall a. a -> Maybe a
Just TypeName
t1
arithmeticConversion TypeName
_ TypeName
_ = forall a. Maybe a
Nothing

floatConversion :: FloatType -> FloatType -> FloatType
floatConversion :: FloatType -> FloatType -> FloatType
floatConversion = forall a. Ord a => a -> a -> a
max

intConversion :: IntType -> IntType -> IntType
intConversion :: IntType -> IntType -> IntType
intConversion IntType
t1 IntType
t2 = forall a. Ord a => a -> a -> a
max IntType
TyInt (forall a. Ord a => a -> a -> a
max IntType
t1 IntType
t2)