summaryrefslogtreecommitdiff
path: root/source/Checking/Facts.hs
diff options
context:
space:
mode:
Diffstat (limited to 'source/Checking/Facts.hs')
-rw-r--r--source/Checking/Facts.hs340
1 files changed, 0 insertions, 340 deletions
diff --git a/source/Checking/Facts.hs b/source/Checking/Facts.hs
deleted file mode 100644
index b365e1e..0000000
--- a/source/Checking/Facts.hs
+++ /dev/null
@@ -1,340 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Checking.Facts
- ( PreparedSemanticFact
- , prepareSemanticFact
- , preparedSemanticStatement
- , preparedSemanticDependencies
- , FactOrigin
- , factOrigin
- , factOriginLocation
- , factOriginBlock
- , StagedFact
- , stageFact
- , stagedFactAliases
- , stagedFactOrigin
- , stagedFactSemantic
- , FactRegistry
- , emptyFactRegistry
- , registerStagedFacts
- , lookupPreparedFact
- , lookupFactOrigin
- , registeredFacts
- , registeredFactsWithOrigins
- , factRegistryExtension
- , restrictFactRegistry
- , partitionFactRegistry
- , factRegistryInvariant
- ) where
-
-import Base
-import Report.Location
-import Syntax.Internal
-
-import Data.List qualified as List
-import Data.List.NonEmpty qualified as NonEmpty
-import Data.Map.Strict qualified as Map
-import Data.Set qualified as Set
-
-
--- | A checked fact before aliases and diagnostic provenance are attached.
--- This is the complete long-lived semantic row.
-data PreparedSemanticFact = PreparedSemanticFact
- { preparedSemanticStatement :: !Formula
- , preparedSemanticDependencies :: !(Set Symbol)
- }
- deriving (Show, Eq)
-
-prepareSemanticFact :: Formula -> PreparedSemanticFact
-prepareSemanticFact statement =
- PreparedSemanticFact
- { preparedSemanticStatement = statement
- , preparedSemanticDependencies = mentionedSymbols statement
- }
-
-data FactOrigin = FactOrigin
- { factOriginLocation :: !Location
- , factOriginBlock :: !Marker
- }
- deriving (Show, Eq)
-
-factOrigin :: Location -> Marker -> FactOrigin
-factOrigin = FactOrigin
-
--- | Registration data for one semantic fact.
-data StagedFact = StagedFact
- { stagedFactAliases :: !(NonEmpty Marker)
- , stagedFactOrigin :: !FactOrigin
- , stagedFactSemantic :: !PreparedSemanticFact
- }
- deriving (Show, Eq)
-
-stageFact
- :: NonEmpty Marker
- -> FactOrigin
- -> PreparedSemanticFact
- -> StagedFact
-stageFact = StagedFact
-
-newtype FactHandle = FactHandle
- { unFactHandle :: Int
- }
- deriving (Show, Eq, Ord)
-
-data FactRegistration = FactRegistration
- { factRegistrationAliases :: !(NonEmpty Marker)
- , factRegistrationOrigin :: !FactOrigin
- }
- deriving (Show, Eq)
-
--- | Semantic rows and their registration sidecars share only a private handle.
-data FactRegistry = FactRegistry
- { factOrder :: ![FactHandle]
- , factRows :: !(Map FactHandle PreparedSemanticFact)
- , factRegistrations :: !(Map FactHandle FactRegistration)
- , factAliases :: !(Map Marker FactHandle)
- , nextFactHandle :: !Int
- }
- deriving (Show, Eq)
-
-emptyFactRegistry :: FactRegistry
-emptyFactRegistry =
- FactRegistry
- { factOrder = []
- , factRows = mempty
- , factRegistrations = mempty
- , factAliases = mempty
- , nextFactHandle = 0
- }
-
-registerStagedFacts
- :: NonEmpty StagedFact
- -> FactRegistry
- -> Either Marker FactRegistry
-registerStagedFacts staged registry =
- case firstDuplicateAlias (Map.keysSet (factAliases registry)) aliases of
- Just duplicate ->
- Left duplicate
- Nothing ->
- Right
- registry
- { factOrder = handles <> factOrder registry
- , factRows =
- Map.union
- (Map.fromList
- [ (handle, stagedFactSemantic fact)
- | (handle, fact) <- registrations
- ])
- (factRows registry)
- , factRegistrations =
- Map.union
- (Map.fromList
- [ ( handle
- , FactRegistration
- { factRegistrationAliases =
- stagedFactAliases fact
- , factRegistrationOrigin =
- stagedFactOrigin fact
- }
- )
- | (handle, fact) <- registrations
- ])
- (factRegistrations registry)
- , factAliases =
- Map.union
- (Map.fromList
- [ (alias, handle)
- | (handle, fact) <- registrations
- , alias <-
- NonEmpty.toList (stagedFactAliases fact)
- ])
- (factAliases registry)
- , nextFactHandle =
- nextFactHandle registry + length stagedList
- }
- where
- stagedList = NonEmpty.toList staged
- handles =
- FactHandle <$>
- [ nextFactHandle registry
- .. nextFactHandle registry + length stagedList - 1
- ]
- registrations = zip handles stagedList
- aliases =
- concatMap
- (NonEmpty.toList . stagedFactAliases)
- stagedList
-
-lookupPreparedFact :: Marker -> FactRegistry -> Maybe PreparedSemanticFact
-lookupPreparedFact marker registry = do
- handle <- Map.lookup marker (factAliases registry)
- Map.lookup handle (factRows registry)
-
-lookupFactOrigin :: Marker -> FactRegistry -> Maybe FactOrigin
-lookupFactOrigin marker registry = do
- handle <- Map.lookup marker (factAliases registry)
- factRegistrationOrigin
- <$> Map.lookup handle (factRegistrations registry)
-
--- | Facts in checker premise order, paired with their primary aliases.
-registeredFacts :: FactRegistry -> [(Marker, PreparedSemanticFact)]
-registeredFacts registry =
- [ (marker, semantic)
- | (marker, semantic, _origin) <-
- registeredFactsWithOrigins registry
- ]
-
--- | Facts in checker premise order with their registration provenance.
-registeredFactsWithOrigins
- :: FactRegistry
- -> [(Marker, PreparedSemanticFact, FactOrigin)]
-registeredFactsWithOrigins registry =
- [ (primaryAlias registration, semantic, factRegistrationOrigin registration)
- | handle <- factOrder registry
- , Just registration <- [Map.lookup handle (factRegistrations registry)]
- , Just semantic <- [Map.lookup handle (factRows registry)]
- ]
- where
- primaryAlias =
- NonEmpty.head . factRegistrationAliases
-
--- | Recover the source-ordered facts appended to one registry.
---
--- The first registry must be an unchanged prefix of the second.
-factRegistryExtension
- :: FactRegistry
- -> FactRegistry
- -> Either Text [StagedFact]
-factRegistryExtension previous current
- | nextFactHandle current < nextFactHandle previous =
- Left "fact registry handle counter moved backwards"
- | Map.restrictKeys
- (factRows current)
- previousHandles
- /= factRows previous =
- Left "fact registry changed an existing semantic row"
- | Map.restrictKeys
- (factRegistrations current)
- previousHandles
- /= factRegistrations previous =
- Left "fact registry changed an existing registration"
- | Map.restrictKeys
- (factAliases current)
- previousAliases
- /= factAliases previous =
- Left "fact registry changed an existing alias"
- | factOrder current
- /= extensionHandles <> factOrder previous =
- Left "fact registry extension changed premise order"
- | otherwise =
- traverse staged extensionHandles
- where
- previousHandles =
- Map.keysSet (factRows previous)
- previousAliases =
- Map.keysSet (factAliases previous)
- extensionHandles =
- FactHandle <$>
- [ nextFactHandle previous
- .. nextFactHandle current - 1
- ]
-
- staged handle = do
- semantic <-
- maybe
- (Left "fact registry extension is missing a semantic row")
- Right
- (Map.lookup handle (factRows current))
- registration <-
- maybe
- (Left "fact registry extension is missing a registration")
- Right
- (Map.lookup handle (factRegistrations current))
- pure
- (StagedFact
- (factRegistrationAliases registration)
- (factRegistrationOrigin registration)
- semantic)
-
-restrictFactRegistry
- :: NonEmpty Marker
- -> FactRegistry
- -> Either Marker FactRegistry
-restrictFactRegistry markers registry = do
- handles <- traverse resolveHandle markers
- pure (registryForHandles (orderedUnique (NonEmpty.toList handles)) registry)
- where
- resolveHandle marker =
- maybe (Left marker) Right (Map.lookup marker (factAliases registry))
-
-partitionFactRegistry
- :: NonEmpty Marker
- -> FactRegistry
- -> Either Marker (FactRegistry, FactRegistry)
-partitionFactRegistry markers registry = do
- selected <- restrictFactRegistry markers registry
- let selectedHandles = Set.fromList (factOrder selected)
- selectedInRegistryOrder =
- List.filter (`Set.member` selectedHandles) (factOrder registry)
- unselectedHandles =
- List.filter (`Set.notMember` selectedHandles) (factOrder registry)
- pure
- ( registryForHandles selectedInRegistryOrder registry
- , registryForHandles unselectedHandles registry
- )
-
-factRegistryInvariant :: FactRegistry -> Bool
-factRegistryInvariant registry =
- length order == Set.size orderSet
- && orderSet == Map.keysSet (factRows registry)
- && orderSet == Map.keysSet (factRegistrations registry)
- && aliasCount == Map.size expectedAliases
- && expectedAliases == factAliases registry
- && all ((< nextFactHandle registry) . unFactHandle) order
- where
- order = factOrder registry
- orderSet = Set.fromList order
- aliasPairs =
- [ (alias, handle)
- | (handle, registration) <-
- Map.toList (factRegistrations registry)
- , alias <-
- NonEmpty.toList (factRegistrationAliases registration)
- ]
- aliasCount = length aliasPairs
- expectedAliases = Map.fromList aliasPairs
-
-registryForHandles :: [FactHandle] -> FactRegistry -> FactRegistry
-registryForHandles handles registry =
- registry
- { factOrder = handles
- , factRows = Map.restrictKeys (factRows registry) handleSet
- , factRegistrations =
- Map.restrictKeys (factRegistrations registry) handleSet
- , factAliases =
- Map.filter (`Set.member` handleSet) (factAliases registry)
- }
- where
- handleSet = Set.fromList handles
-
-firstDuplicateAlias :: Set Marker -> [Marker] -> Maybe Marker
-firstDuplicateAlias existing =
- go mempty
- where
- go _seen [] =
- Nothing
- go seen (marker:rest)
- | marker `Set.member` existing || marker `Set.member` seen =
- Just marker
- | otherwise =
- go (Set.insert marker seen) rest
-
-orderedUnique :: Ord a => [a] -> [a]
-orderedUnique =
- reverse . snd . foldl' step (mempty, [])
- where
- step (seen, acc) value
- | value `Set.member` seen =
- (seen, acc)
- | otherwise =
- (Set.insert value seen, value : acc)