content: {-# OPTIONS_GHC -fno-warn-orphans #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE KindSignatures #-}
  
  {-# LANGUAGE UndecidableInstances #-}
  {-# LANGUAGE FunctionalDependencies #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  
  module Ivory.Language.CArray where
  
  import Ivory.Language.Area
  import Ivory.Language.Proxy
  import Ivory.Language.Ref
  import Ivory.Language.Struct
  import Ivory.Language.Type
  import qualified Ivory.Language.Syntax as I
  
  --------------------------------------------------------------------------------
  
  instance IvoryArea a => IvoryArea ('CArray a) where
    ivoryArea _ = I.TyCArray (ivoryArea (Proxy :: Proxy a))
  
  
  -- | Guard invocations of toCArray.
  class (IvoryArea area, IvoryArea rep)
    => ToCArray (area :: Area *) (rep :: Area *) | area -> rep
  
  instance (ANat len, ToCArray area rep)
      => ToCArray ('Array len area) ('CArray rep)
  instance IvoryType a => ToCArray ('Stored a) ('Stored a)
  instance IvoryStruct sym => ToCArray ('Struct sym) ('Struct sym)
  
  -- | Convert from a checked array to one that can be given to a c function.
  toCArray :: forall s len area rep ref.
              ( ANat len, ToCArray area rep, IvoryRef ref
              , IvoryExpr (ref s ('Array len area))
              , IvoryExpr (ref s ('CArray rep)))
           => ref s ('Array len area) -> ref s ('CArray rep)
  toCArray ref = wrapExpr $ I.ExpSafeCast ty (unwrapExpr ref)
    where ty = ivoryType (Proxy :: Proxy (ref s ('CArray rep)))
  