content: {-# LANGUAGE GADTs #-}
  
  -- | Translate Copilot Core expressions and operators to C99.
  module Copilot.Compile.C99.Type
      ( transType
      , transLocalVarDeclType
      , transTypeName
      )
    where
  
  -- External imports
  import qualified Language.C99.Simple as C
  
  -- Internal imports: Copilot
  import Copilot.Core ( Type (..), typeLength, typeName )
  
  -- | Translate a Copilot type to a C99 type.
  transType :: Type a -> C.Type
  transType ty = case ty of
    Bool      -> C.TypeSpec $ C.TypedefName "bool"
    Int8      -> C.TypeSpec $ C.TypedefName "int8_t"
    Int16     -> C.TypeSpec $ C.TypedefName "int16_t"
    Int32     -> C.TypeSpec $ C.TypedefName "int32_t"
    Int64     -> C.TypeSpec $ C.TypedefName "int64_t"
    Word8     -> C.TypeSpec $ C.TypedefName "uint8_t"
    Word16    -> C.TypeSpec $ C.TypedefName "uint16_t"
    Word32    -> C.TypeSpec $ C.TypedefName "uint32_t"
    Word64    -> C.TypeSpec $ C.TypedefName "uint64_t"
    Float     -> C.TypeSpec C.Float
    Double    -> C.TypeSpec C.Double
    Array ty' -> C.Array (transType ty') len
      where
        len = Just $ C.LitInt $ fromIntegral $ typeLength ty
    Struct s  -> C.TypeSpec $ C.Struct (typeName s)
  
  -- | Translate a Copilot type to a valid (local) variable declaration C99 type.
  --
  -- If the type denotes an array, translate it to a pointer to whatever the
  -- array holds. This special case is needed when the type is used for a local
  -- variable declaration. We treat global variables differently (we generate
  -- list initializers).
  transLocalVarDeclType :: Type a -> C.Type
  transLocalVarDeclType (Array ty') = C.Ptr $ transType ty'
  transLocalVarDeclType ty          = transType ty
  
  -- | Translate a Copilot type intro a C typename
  transTypeName :: Type a -> C.TypeName
  transTypeName ty = C.TypeName $ transType ty
  