content: 
  module DDC.Core.Discus.Convert.Type.Region
          ( convertRegionT
          , saltPrimeRegionOfDataType)
  where
  import DDC.Core.Discus.Convert.Type.Base
  import DDC.Core.Discus.Convert.Error
  import DDC.Core.Exp.Annot
  import DDC.Type.Env
  import DDC.Control.Check                        (throw)
  import qualified DDC.Core.Discus.Prim            as E
  import qualified DDC.Core.Salt.Runtime          as A
  import qualified DDC.Core.Salt.Name             as A
  import qualified DDC.Type.Env                   as Env
  import DDC.Data.Pretty
  
  
  -- Region Types -----------------------------------------------------------------------------------
  -- | Convert a region type to Salt.
  convertRegionT :: Context -> Type E.Name -> ConvertM a (Type A.Name)
  convertRegionT ctx tt
          | TVar u        <- tt
          , Just k        <- Env.lookup u (contextKindEnv ctx)
          , isRegionKind k
          = return $ A.rTop
  
          | otherwise
          = throw  $ ErrorMalformed
                   $ "Invalid region type " ++ (renderIndent $ ppr tt)
  
  
  -- Prime Region -----------------------------------------------------------------------------------
  -- | Given the type of some data value, determine what prime region to use
  --   for the object in the Salt language. The supplied type must have kind
  --   Data, else you'll get a bogus result.
  --
  --   NOTE: This used to do something more useful, but was changed so that
  --   all values go into rTop. The problem is that given a type like (m Nat)
  --   we can't know what region the value will be allocated into as the
  --   type is too polymorphic. We need to implement a region subtyping system
  --   so that the Top region can be treated as an Any/DontKnow specifier
  --   rather than a specific region that is distinct from all others.
  --
  saltPrimeRegionOfDataType
          :: KindEnv E.Name
          -> Type E.Name
          -> ConvertM a (Type A.Name)
  
  saltPrimeRegionOfDataType kenv tt
          -- Boxed data types with an attached primary region variable.
          | TCon _ : TVar u : _   <- takeTApps tt
          , Just k                <- Env.lookup u kenv
          , isRegionKind k
          = do    return  A.rTop
  
          -- Completely parametric data types.
          | TVar u        <- tt
          , Just k        <- Env.lookup u kenv
          , isDataKind k
          = do    return  A.rTop
  
          -- Boxed data types without an attached primary region variable.
          --   For applications of abstract type constructors like in
          --   (m Nat), we can't know what constructor 'm' will be instantiated
          --   with, nor what region the resulting value will be allocated into.
          | TCon{}  <- tt
          = do    return  A.rTop
  
          | TApp{}   <- tt
          = do    return  A.rTop
  
          -- Quantified types.
          | TForall{}     <- tt
          = do    return  A.rTop
  
          -- Type variable which is not in the environment.
          | otherwise
          = throw $ ErrorMalformed
                  $ "Cannot take prime region from " ++ (renderIndent $ ppr tt)
  
  