content: 
  module DDC.Core.Salt.Name.PrimCast
          ( PrimCast (..)
          , readPrimCast
          , primCastPromoteIsValid
          , primCastTruncateIsValid)
  where
  import DDC.Core.Salt.Name.PrimTyCon
  import DDC.Core.Salt.Platform
  import DDC.Data.Pretty
  import Control.DeepSeq
  
  
  -- | Primitive cast between two types.
  --
  --   The exact set of available casts is determined by the target platform.
  --   For example, you can only promote a @Nat\#@ to a @Word32\#@ on a 32-bit
  --   system. On a 64-bit system the @Nat\#@ type is 64-bits wide, so casting it
  --   to a @Word32\#@ would be a truncation.
  data PrimCast
          -- | Convert a value to a new representation with the same precision.
          = PrimCastConvert
  
          -- | Promote a value to one of similar or larger width,
          --   without loss of precision.
          | PrimCastPromote
  
          -- | Truncate a value to a new width,
          --   possibly losing precision.
          | PrimCastTruncate
          deriving (Eq, Ord, Show)
  
  
  instance NFData PrimCast where
   rnf !_ = ()
  
  
  instance Pretty PrimCast where
   ppr c
    = case c of
          PrimCastConvert         -> text "convert#"
          PrimCastPromote         -> text "promote#"
          PrimCastTruncate        -> text "truncate#"
  
  
  readPrimCast :: String -> Maybe PrimCast
  readPrimCast str
   = case str of
          "convert#"              -> Just PrimCastConvert
          "promote#"              -> Just PrimCastPromote
          "truncate#"             -> Just PrimCastTruncate
          _                       -> Nothing
  
  
  -- | Check for a valid promotion primop.
  primCastPromoteIsValid
          :: Platform     -- ^ Target platform.
          -> PrimTyCon    -- ^ Source type.
          -> PrimTyCon    -- ^ Destination type.
          -> Bool
  
  primCastPromoteIsValid pp src dst
          -- Promote unsigned to a larger or similar width.
          | primTyConIsIntegral src, primTyConIsIntegral dst
          , primTyConIsUnsigned src, primTyConIsUnsigned dst
          , primTyConWidth pp dst >= primTyConWidth pp src
          = True
  
          -- Promote signed to a larger or similar width.
          | primTyConIsIntegral src, primTyConIsIntegral dst
          , primTyConIsSigned   src, primTyConIsSigned   dst
          , primTyConWidth pp dst >= primTyConWidth pp src
          = True
  
          -- Promote unsigned to a strictly larger signed width.
          | primTyConIsIntegral src, primTyConIsIntegral dst
          , primTyConIsUnsigned src, primTyConIsSigned   dst
          , primTyConWidth pp dst >  primTyConWidth pp src
          = True
  
          | otherwise
          = False
  
  
  -- | Check for valid truncation primop.
  primCastTruncateIsValid
          :: Platform     -- ^ Target platform.
          -> PrimTyCon    -- ^ Source type.
          -> PrimTyCon    -- ^ Destination type.
          -> Bool
  
  primCastTruncateIsValid _pp src dst
          | primTyConIsIntegral src
          , primTyConIsIntegral dst
          = True
  
          | otherwise
          = False
  
  