module Agda.TypeChecking.Forcing
  ( computeForcingAnnotations,
    isForced,
    nextIsForced ) where
import Data.Bifunctor
import Data.DList (DList)
import qualified Data.DList as DL
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import Data.Monoid 
import Agda.Interaction.Options
import Agda.Syntax.Common
import Agda.Syntax.Internal
import Agda.TypeChecking.Monad
import Agda.TypeChecking.Reduce
import Agda.TypeChecking.Substitute
import Agda.TypeChecking.Telescope
import Agda.Utils.List
import Agda.Utils.Monad
import Agda.Utils.Pretty (prettyShow)
import Agda.Utils.Size
import Agda.Utils.Impossible
computeForcingAnnotations :: QName -> Type -> TCM [IsForced]
computeForcingAnnotations :: QName -> Type -> TCM [IsForced]
computeForcingAnnotations QName
c Type
t =
  TCMT IO Bool -> TCM [IsForced] -> TCM [IsForced] -> TCM [IsForced]
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifNotM (PragmaOptions -> Bool
optForcing (PragmaOptions -> Bool) -> TCMT IO PragmaOptions -> TCMT IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TCMT IO PragmaOptions
forall (m :: * -> *). HasOptions m => m PragmaOptions
pragmaOptions ) ([IsForced] -> TCM [IsForced]
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []) (TCM [IsForced] -> TCM [IsForced])
-> TCM [IsForced] -> TCM [IsForced]
forall a b. (a -> b) -> a -> b
$  do
    
    
    
    
    
    Type
t <- Type -> TCMT IO Type
forall a (m :: * -> *).
(InstantiateFull a, MonadReduce m) =>
a -> m a
instantiateFull Type
t
    
    
    
    TelV Tele (Dom Type)
tel (El Sort' Term
_ Term
a) <- Type -> TCMT IO (TelV Type)
forall (m :: * -> *). PureTCM m => Type -> m (TelV Type)
telViewPath Type
t
    let vs :: Elims
vs = case Term
a of
          Def QName
_ Elims
us -> Elims
us
          Term
_        -> Elims
forall a. HasCallStack => a
__IMPOSSIBLE__
        n :: Int
n = Tele (Dom Type) -> Int
forall a. Sized a => a -> Int
size Tele (Dom Type)
tel
        xs :: [(Modality, Nat)]
        xs :: [(Modality, Int)]
xs = DList (Modality, Int) -> [(Modality, Int)]
forall a. DList a -> [a]
DL.toList (DList (Modality, Int) -> [(Modality, Int)])
-> DList (Modality, Int) -> [(Modality, Int)]
forall a b. (a -> b) -> a -> b
$ Elims -> DList (Modality, Int)
forall a. ForcedVariables a => a -> DList (Modality, Int)
forcedVariables Elims
vs
        xs' :: IntMap [Modality]
        xs' :: IntMap [Modality]
xs' = (DList Modality -> [Modality])
-> IntMap (DList Modality) -> IntMap [Modality]
forall a b. (a -> b) -> IntMap a -> IntMap b
IntMap.map DList Modality -> [Modality]
forall a. DList a -> [a]
DL.toList (IntMap (DList Modality) -> IntMap [Modality])
-> IntMap (DList Modality) -> IntMap [Modality]
forall a b. (a -> b) -> a -> b
$ (DList Modality -> DList Modality -> DList Modality)
-> [(Int, DList Modality)] -> IntMap (DList Modality)
forall a. (a -> a -> a) -> [(Int, a)] -> IntMap a
IntMap.fromListWith DList Modality -> DList Modality -> DList Modality
forall a. Semigroup a => a -> a -> a
(<>) ([(Int, DList Modality)] -> IntMap (DList Modality))
-> [(Int, DList Modality)] -> IntMap (DList Modality)
forall a b. (a -> b) -> a -> b
$
              ((Modality, Int) -> (Int, DList Modality))
-> [(Modality, Int)] -> [(Int, DList Modality)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Modality
m, Int
i) -> (Int
i, Modality -> DList Modality
forall a. a -> DList a
DL.singleton Modality
m)) [(Modality, Int)]
xs
        
        
        
        
        
        isForced :: Modality -> Nat -> Bool
        isForced :: Modality -> Int -> Bool
isForced Modality
m Int
i =
               (Modality -> Bool
forall a. LensQuantity a => a -> Bool
hasQuantity0 Modality
m Bool -> Bool -> Bool
|| Modality -> Bool
forall a. LensQuantity a => a -> Bool
noUserQuantity Modality
m)
            Bool -> Bool -> Bool
&& (Modality -> Relevance
forall a. LensRelevance a => a -> Relevance
getRelevance Modality
m Relevance -> Relevance -> Bool
forall a. Eq a => a -> a -> Bool
/= Relevance
Irrelevant)
            Bool -> Bool -> Bool
&& case Int -> IntMap [Modality] -> Maybe [Modality]
forall a. Int -> IntMap a -> Maybe a
IntMap.lookup Int
i IntMap [Modality]
xs' of
                 Maybe [Modality]
Nothing -> Bool
False
                 Just [Modality]
ms -> (Modality -> Bool) -> [Modality] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Modality -> Modality -> Bool
`moreUsableModality` Modality
m) [Modality]
ms
        forcedArgs :: [IsForced]
forcedArgs =
          [ if Modality -> Int -> Bool
isForced Modality
m Int
i then IsForced
Forced else IsForced
NotForced
          | (Int
i, Modality
m) <- [Int] -> [Modality] -> [(Int, Modality)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Int -> [Int]
forall a. Integral a => a -> [a]
downFrom Int
n) ([Modality] -> [(Int, Modality)])
-> [Modality] -> [(Int, Modality)]
forall a b. (a -> b) -> a -> b
$ (Dom (ArgName, Type) -> Modality)
-> [Dom (ArgName, Type)] -> [Modality]
forall a b. (a -> b) -> [a] -> [b]
map Dom (ArgName, Type) -> Modality
forall a. LensModality a => a -> Modality
getModality (Tele (Dom Type) -> [Dom (ArgName, Type)]
forall t. Tele (Dom t) -> [Dom (ArgName, t)]
telToList Tele (Dom Type)
tel)
          ]
    ArgName -> Int -> [ArgName] -> TCMT IO ()
forall a (m :: * -> *).
(ReportS a, MonadDebug m) =>
ArgName -> Int -> a -> m ()
forall (m :: * -> *).
MonadDebug m =>
ArgName -> Int -> [ArgName] -> m ()
reportS ArgName
"tc.force" Int
60
      [ ArgName
"Forcing analysis for " ArgName -> ArgName -> ArgName
forall a. [a] -> [a] -> [a]
++ QName -> ArgName
forall a. Pretty a => a -> ArgName
prettyShow QName
c
      , ArgName
"  xs          = " ArgName -> ArgName -> ArgName
forall a. [a] -> [a] -> [a]
++ [Int] -> ArgName
forall a. Show a => a -> ArgName
show (((Modality, Int) -> Int) -> [(Modality, Int)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Modality, Int) -> Int
forall a b. (a, b) -> b
snd [(Modality, Int)]
xs)
      , ArgName
"  forcedArgs  = " ArgName -> ArgName -> ArgName
forall a. [a] -> [a] -> [a]
++ [IsForced] -> ArgName
forall a. Show a => a -> ArgName
show [IsForced]
forcedArgs
      ]
    [IsForced] -> TCM [IsForced]
forall a. a -> TCMT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [IsForced]
forcedArgs
class ForcedVariables a where
  forcedVariables :: a -> DList (Modality, Nat)
  default forcedVariables ::
    (ForcedVariables b, Foldable t, a ~ t b) =>
    a -> DList (Modality, Nat)
  forcedVariables = (b -> DList (Modality, Int)) -> t b -> DList (Modality, Int)
forall m a. Monoid m => (a -> m) -> t a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap b -> DList (Modality, Int)
forall a. ForcedVariables a => a -> DList (Modality, Int)
forcedVariables
instance ForcedVariables a => ForcedVariables [a] where
instance ForcedVariables a => ForcedVariables (Elim' a) where
  forcedVariables :: Elim' a -> DList (Modality, Int)
forcedVariables (Apply Arg a
x) = Arg a -> DList (Modality, Int)
forall a. ForcedVariables a => a -> DList (Modality, Int)
forcedVariables Arg a
x
  forcedVariables IApply{}  = DList (Modality, Int)
forall a. Monoid a => a
mempty  
  forcedVariables Proj{}    = DList (Modality, Int)
forall a. Monoid a => a
mempty
instance ForcedVariables a => ForcedVariables (Arg a) where
  forcedVariables :: Arg a -> DList (Modality, Int)
forcedVariables Arg a
x =
    ((Modality, Int) -> (Modality, Int))
-> DList (Modality, Int) -> DList (Modality, Int)
forall a b. (a -> b) -> DList a -> DList b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Modality -> Modality) -> (Modality, Int) -> (Modality, Int)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (Modality -> Modality -> Modality
composeModality Modality
m)) (a -> DList (Modality, Int)
forall a. ForcedVariables a => a -> DList (Modality, Int)
forcedVariables (Arg a -> a
forall e. Arg e -> e
unArg Arg a
x))
    where m :: Modality
m = Arg a -> Modality
forall a. LensModality a => a -> Modality
getModality Arg a
x
instance ForcedVariables Term where
  forcedVariables :: Term -> DList (Modality, Int)
forcedVariables = \case
    Var Int
i []   -> (Modality, Int) -> DList (Modality, Int)
forall a. a -> DList a
DL.singleton (Modality
unitModality, Int
i)
    Con ConHead
_ ConInfo
_ Elims
vs -> Elims -> DList (Modality, Int)
forall a. ForcedVariables a => a -> DList (Modality, Int)
forcedVariables Elims
vs
    Term
_          -> DList (Modality, Int)
forall a. Monoid a => a
mempty
isForced :: IsForced -> Bool
isForced :: IsForced -> Bool
isForced IsForced
Forced    = Bool
True
isForced IsForced
NotForced = Bool
False
nextIsForced :: [IsForced] -> (IsForced, [IsForced])
nextIsForced :: [IsForced] -> (IsForced, [IsForced])
nextIsForced []     = (IsForced
NotForced, [])
nextIsForced (IsForced
f:[IsForced]
fs) = (IsForced
f, [IsForced]
fs)