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.Syntax.Common.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)