packages feed

ddc-core-0.4.3.1: DDC/Core/Check/Context/Effect.hs

module DDC.Core.Check.Context.Effect
        (effectSupported)
where
import DDC.Core.Check.Context.Base
import DDC.Core.Check.Context.Elem
import DDC.Type.Exp.Simple
import Data.Maybe
import qualified DDC.Core.Env.EnvT      as EnvT
import qualified DDC.Type.Sum           as Sum
import qualified Data.Map.Strict        as Map


-- | Check whether this effect is supported by the given context.
--   This is used when effects are treated as capabilities.
--
--   The overall function can be passed a compound effect, 
--    it returns `Nothing` if the effect is supported, 
--    or `Just e`, where `e` is some unsuported atomic effect.
--
effectSupported 
        :: (Ord n, Show n)
        => Context n 
        -> Effect n 
        -> Maybe (Effect n)

effectSupported ctx eff 
        -- Check that all the components of a sum are supported.
        | TSum ts       <- eff
        = listToMaybe $ concat [ maybeToList $ effectSupported ctx e
                               | e <- Sum.toList ts ]

        -- Abstract effects are fine.
        --  We'll find out if it is really supported once it's instantiated.
        | TVar {} <- eff
        = Nothing

        -- Abstract global effects are always supported.
        | TCon (TyConBound _ k) <- eff
        , k == kEffect
        = Nothing

        -- For an effects on concrete region,
        -- the capability is supported if it's in the lexical environment.
        | TApp (TCon (TyConSpec tc)) _t2 <- eff
        , elem tc [TcConRead, TcConWrite, TcConAlloc]

        ,   -- Capability in local environment. 
            (any  (\b -> equivT (contextEnvT ctx) (typeOfBind b) eff) 
                  [ b | ElemType b <- contextElems ctx ] )
   
            -- Capability imported at top level.
         || (any  (\t -> equivT (contextEnvT ctx) t eff)
                  (Map.elems $ EnvT.envtCapabilities $ contextEnvT ctx))
        = Nothing

        -- For an effect on an abstract region, we allow any capability.
        --  We'll find out if it really has this capability when we try
        --  to run the computation.
        | TApp (TCon (TyConSpec tc)) (TVar u) <- eff
        , elem tc [TcConRead, TcConWrite, TcConAlloc]
        = case lookupKind u ctx of
                Just (_, RoleConcrete)  -> Just eff
                Just (_, RoleAbstract)  -> Nothing
                Nothing                 -> Nothing

        | otherwise
        = Just eff