{-# OPTIONS_GHC -Wunused-imports #-}
module Mikan.TypeChecking.DeadCode (eliminateDeadCode) where
import Control.Monad
import Control.Monad.Trans
import Data.Maybe
import Data.Map.Strict qualified as MapS
import Data.HashMap.Strict qualified as HMap
import Data.IORef
import Mikan.Syntax.Common
import Mikan.Syntax.Internal
import Mikan.Syntax.Internal.Names
import Mikan.Syntax.Scope.Base
import Mikan.Benchmarking qualified as Bench
import Mikan.TypeChecking.Monad.Benchmark qualified as Bench
import Mikan.TypeChecking.Monad
import Mikan.Utils.Impossible
import Mikan.Utils.List
import Mikan.Utils.List1 qualified as List1
import Mikan.Utils.HashTable (HashTableLU, HashTableLL)
import Mikan.Utils.HashTable qualified as HT
eliminateDeadCode :: ScopeInfo -> TCM (RemoteMetaStore, Definitions, DisplayForms)
eliminateDeadCode :: ScopeInfo
-> TCM
(RemoteMetaStore, Definitions,
HashMap QName (NonEmpty (Open DisplayForm)))
eliminateDeadCode !ScopeInfo
scope = Account (BenchPhase (TCMT IO))
-> TCM
(RemoteMetaStore, Definitions,
HashMap QName (NonEmpty (Open DisplayForm)))
-> TCM
(RemoteMetaStore, Definitions,
HashMap QName (NonEmpty (Open DisplayForm)))
forall (m :: * -> *) c.
MonadBench m =>
Account (BenchPhase m) -> m c -> m c
Bench.billTo [BenchPhase (TCMT IO)
Phase
Bench.DeadCode] (TCM
(RemoteMetaStore, Definitions,
HashMap QName (NonEmpty (Open DisplayForm)))
-> TCM
(RemoteMetaStore, Definitions,
HashMap QName (NonEmpty (Open DisplayForm))))
-> TCM
(RemoteMetaStore, Definitions,
HashMap QName (NonEmpty (Open DisplayForm)))
-> TCM
(RemoteMetaStore, Definitions,
HashMap QName (NonEmpty (Open DisplayForm)))
forall a b. (a -> b) -> a -> b
$ do
!sig <- TCMT IO Signature
forall (m :: * -> *). ReadTCState m => m Signature
getSignature
let !defs = Signature
sig Signature
-> Getting Definitions Signature Definitions -> Definitions
forall s a. s -> Getting a s a -> a
^. Getting Definitions Signature Definitions
Lens' Signature Definitions
sigDefinitions
!metas <- useR stSolvedMetaStore
let hasCompilePragma = Bool -> Bool
not (Bool -> Bool) -> (Definition -> Bool) -> Definition -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map BackendName [CompilerPragma] -> Bool
forall k a. Map k a -> Bool
MapS.null (Map BackendName [CompilerPragma] -> Bool)
-> (Definition -> Map BackendName [CompilerPragma])
-> Definition
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Definition -> Map BackendName [CompilerPragma]
defCompiledRep
isPrimitive = \case
Primitive{} -> Bool
True
PrimitiveSort{} -> Bool
True
Defn
_ -> Bool
False
extraRootsFilter (a
name, Definition
def)
| Definition -> Bool
hasCompilePragma Definition
def Bool -> Bool -> Bool
|| Defn -> Bool
isPrimitive (Definition -> Defn
theDef Definition
def) = a -> Maybe a
forall a. a -> Maybe a
Just a
name
| Bool
otherwise = Maybe a
forall a. Maybe a
Nothing
let !pubModules = ScopeInfo -> Map ModuleName Scope
publicModules ScopeInfo
scope
let eliminateNonClosed = [Open a] -> Maybe (NonEmpty (Open a))
forall a. [a] -> Maybe (NonEmpty a)
List1.nonEmpty ([Open a] -> Maybe (NonEmpty (Open a)))
-> (NonEmpty (Open a) -> [Open a])
-> NonEmpty (Open a)
-> Maybe (NonEmpty (Open a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Open a -> Bool) -> NonEmpty (Open a) -> [Open a]
forall a. (a -> Bool) -> NonEmpty a -> [a]
List1.filter Open a -> Bool
forall a. Open a -> Bool
isClosed
!rootDisplayForms <-
HMap.mapMaybe eliminateNonClosed <$> useTC stImportsDisplayForms
let !rootPubNames = (AbstractName -> QName) -> [AbstractName] -> [QName]
forall a b. (a -> b) -> [a] -> [b]
map' AbstractName -> QName
anameName ([AbstractName] -> [QName]) -> [AbstractName] -> [QName]
forall a b. (a -> b) -> a -> b
$ Map ModuleName Scope -> [AbstractName]
publicNamesOfModules Map ModuleName Scope
pubModules
let !rootExtraDefs = ((QName, Definition) -> Maybe QName)
-> [(QName, Definition)] -> [QName]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (QName, Definition) -> Maybe QName
forall {a}. (a, Definition) -> Maybe a
extraRootsFilter ([(QName, Definition)] -> [QName])
-> [(QName, Definition)] -> [QName]
forall a b. (a -> b) -> a -> b
$ Definitions -> [(QName, Definition)]
forall k v. HashMap k v -> [(k, v)]
HMap.toList Definitions
defs
let !rootModSections = Signature
sig Signature -> Getting Sections Signature Sections -> Sections
forall s a. s -> Getting a s a -> a
^. Getting Sections Signature Sections
Lens' Signature Sections
sigSections
!rootBuiltins <- useTC stLocalBuiltins
!rootPatSyns <- getPatternSyns
!insideDef <- lift $ newIORef Nothing :: TCM (IORef (Maybe (IORef Bool)))
!seenNames <- lift $ HT.empty :: TCM (HashTableLL QName (IORef Bool))
!seenMetas <- lift $ HT.empty :: TCM (HashTableLU MetaId ())
let goName :: QName -> IO ()
goName !QName
x = HashTableLL QName (IORef Bool)
-> QName
-> (IORef Bool -> IO ())
-> IO (IORef Bool)
-> (IORef Bool -> IO ())
-> IO ()
forall (ks :: * -> * -> *) k (vs :: * -> * -> *) v a.
(Hashable k, MVector ks k, MVector vs v) =>
HashTable ks k vs v
-> k -> (v -> IO a) -> IO v -> (v -> IO a) -> IO a
HT.insertingIfAbsent HashTableLL QName (IORef Bool)
seenNames QName
x
(\IORef Bool
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
(Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False)
(\IORef Bool
ref -> do
prevRef <- IORef (Maybe (IORef Bool)) -> IO (Maybe (IORef Bool))
forall a. IORef a -> IO a
readIORef IORef (Maybe (IORef Bool))
insideDef
writeIORef insideDef (Just ref)
go (HMap.lookup x defs)
writeIORef insideDef prevRef
)
goMeta :: MetaId -> IO ()
goMeta !MetaId
m = do
prevRef <- IORef (Maybe (IORef Bool)) -> IO (Maybe (IORef Bool))
forall a. IORef a -> IO a
readIORef IORef (Maybe (IORef Bool))
insideDef
case prevRef of
Maybe (IORef Bool)
Nothing -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just IORef Bool
ref -> IORef Bool -> Bool -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Bool
ref Bool
True
HT.insertingIfAbsent seenMetas m
(\()
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
(pure ())
(\()
_ -> case MetaId -> Map MetaId MetaVariable -> Maybe MetaVariable
forall k a. Ord k => k -> Map k a -> Maybe a
MapS.lookup MetaId
m Map MetaId MetaVariable
metas of
Maybe MetaVariable
Nothing -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just MetaVariable
mv -> do
IORef (Maybe (IORef Bool)) -> Maybe (IORef Bool) -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe (IORef Bool))
insideDef Maybe (IORef Bool)
forall a. Maybe a
Nothing
Term -> IO ()
forall a. NamesIn a => a -> IO ()
go (Instantiation -> Term
instBody (MetaVariable -> Instantiation
theInstantiation MetaVariable
mv))
Teletype -> IO ()
forall a. NamesIn a => a -> IO ()
go (Judgement MetaId -> Teletype
forall a. Judgement a -> Teletype
jMetaType (MetaVariable -> Judgement MetaId
mvJudgement MetaVariable
mv))
IORef (Maybe (IORef Bool)) -> Maybe (IORef Bool) -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe (IORef Bool))
insideDef Maybe (IORef Bool)
prevRef
)
go :: NamesIn a => a -> IO ()
go !a
x = (Either QName MetaId -> IO ()) -> a -> IO ()
forall m. Monoid m => (Either QName MetaId -> m) -> a -> m
forall a m.
(NamesIn a, Monoid m) =>
(Either QName MetaId -> m) -> a -> m
namesAndMetasIn' ((QName -> IO ())
-> (MetaId -> IO ()) -> Either QName MetaId -> IO ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either QName -> IO ()
goName MetaId -> IO ()
goMeta) a
x
{-# INLINE go #-}
Bench.billTo [Bench.DeadCode, Bench.DeadCodeReachable] $ lift $ do
go rootDisplayForms
foldMap goName rootPubNames
foldMap goName rootExtraDefs
go rootModSections
go rootBuiltins
foldMap go rootPatSyns
let goMetas :: [(MetaId, MetaVariable)] -> IO [(MetaId, RemoteMetaVariable)]
goMetas [] = [(MetaId, RemoteMetaVariable)] -> IO [(MetaId, RemoteMetaVariable)]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
goMetas ((!MetaId
i, !MetaVariable
m):[(MetaId, MetaVariable)]
metas) = HashTableLU MetaId () -> MetaId -> IO (Maybe ())
forall k (ks :: * -> * -> *) (vs :: * -> * -> *) v.
(Hashable k, MVector ks k, MVector vs v) =>
HashTable ks k vs v -> k -> IO (Maybe v)
HT.lookup HashTableLU MetaId ()
seenMetas MetaId
i IO (Maybe ())
-> (Maybe () -> IO [(MetaId, RemoteMetaVariable)])
-> IO [(MetaId, RemoteMetaVariable)]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe ()
Nothing -> [(MetaId, MetaVariable)] -> IO [(MetaId, RemoteMetaVariable)]
goMetas [(MetaId, MetaVariable)]
metas
Just ()
_ -> do
let !m' :: RemoteMetaVariable
m' = MetaVariable -> RemoteMetaVariable
remoteMetaVariable MetaVariable
m
((MetaId
i, RemoteMetaVariable
m')(MetaId, RemoteMetaVariable)
-> [(MetaId, RemoteMetaVariable)] -> [(MetaId, RemoteMetaVariable)]
forall a. a -> [a] -> [a]
:) ([(MetaId, RemoteMetaVariable)] -> [(MetaId, RemoteMetaVariable)])
-> IO [(MetaId, RemoteMetaVariable)]
-> IO [(MetaId, RemoteMetaVariable)]
forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
<$!> [(MetaId, MetaVariable)] -> IO [(MetaId, RemoteMetaVariable)]
goMetas [(MetaId, MetaVariable)]
metas
goDefs :: [(QName, Definition)] -> IO [(QName, Definition)]
goDefs [] = [(QName, Definition)] -> IO [(QName, Definition)]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
goDefs ((!QName
x, !Definition
d):[(QName, Definition)]
defs) = HashTableLL QName (IORef Bool) -> QName -> IO (Maybe (IORef Bool))
forall k (ks :: * -> * -> *) (vs :: * -> * -> *) v.
(Hashable k, MVector ks k, MVector vs v) =>
HashTable ks k vs v -> k -> IO (Maybe v)
HT.lookup HashTableLL QName (IORef Bool)
seenNames QName
x IO (Maybe (IORef Bool))
-> (Maybe (IORef Bool) -> IO [(QName, Definition)])
-> IO [(QName, Definition)]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe (IORef Bool)
Nothing -> [(QName, Definition)] -> IO [(QName, Definition)]
goDefs [(QName, Definition)]
defs
Just IORef Bool
r -> do
hasM <- IORef Bool -> IO Bool
forall a. IORef a -> IO a
readIORef IORef Bool
r
!d <- case hasM of
Bool
True -> Definition -> IO Definition
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Definition
d
Bool
False -> Definition -> IO Definition
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Definition -> IO Definition) -> Definition -> IO Definition
forall a b. (a -> b) -> a -> b
$! Definition
d {defMightContainMetas = False}
((x, d):) <$!> goDefs defs
!metas <- lift $ HMap.fromList <$> goMetas (MapS.toList metas)
!defs <- lift $ HMap.fromList <$> goDefs (HMap.toList defs)
pure (metas, defs, rootDisplayForms)
theInstantiation :: MetaVariable -> Instantiation
theInstantiation :: MetaVariable -> Instantiation
theInstantiation MetaVariable
mv = case MetaVariable -> MetaInstantiation
mvInstantiation MetaVariable
mv of
InstV Instantiation
inst -> Instantiation
inst
OpenMeta{} -> Instantiation
forall a. HasCallStack => a
__IMPOSSIBLE__
BlockedConst{} -> Instantiation
forall a. HasCallStack => a
__IMPOSSIBLE__
PostponedTypeCheckingProblem{} -> Instantiation
forall a. HasCallStack => a
__IMPOSSIBLE__
remoteMetaVariable :: MetaVariable -> RemoteMetaVariable
remoteMetaVariable :: MetaVariable -> RemoteMetaVariable
remoteMetaVariable !MetaVariable
mv = RemoteMetaVariable
{ rmvInstantiation :: Instantiation
rmvInstantiation = MetaVariable -> Instantiation
theInstantiation MetaVariable
mv
, rmvJudgement :: Judgement MetaId
rmvJudgement = MetaVariable -> Judgement MetaId
mvJudgement MetaVariable
mv
}