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

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

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