summaryrefslogtreecommitdiff
path: root/source/Felix/Store.hs
diff options
context:
space:
mode:
Diffstat (limited to 'source/Felix/Store.hs')
-rw-r--r--source/Felix/Store.hs189
1 files changed, 104 insertions, 85 deletions
diff --git a/source/Felix/Store.hs b/source/Felix/Store.hs
index 973a172..bf84f6e 100644
--- a/source/Felix/Store.hs
+++ b/source/Felix/Store.hs
@@ -47,6 +47,9 @@ module Felix.Store
, newStoreMemo
, StoreMemoVisits(..)
, storeMemoVisits
+ , StoreCoordinator
+ , newStoreCoordinator
+ , withStoreCoordinator
) where
import Base
@@ -61,6 +64,11 @@ import Felix.Parsed.Identity qualified as Parsed
import Felix.Parsed.Payload qualified as ParsedPayload
import Syntax.Interface qualified as Syntax
+import Control.Concurrent.MVar
+ ( MVar
+ , newMVar
+ , withMVar
+ )
import Control.Exception qualified as Exception
import Control.Monad (foldM, unless)
import Control.Monad.Except qualified as Except
@@ -84,6 +92,18 @@ data Store = Store
!TheoryId
!SQLite.Connection
+-- | The single invocation-local gateway for a store connection and its
+-- ordinary 'IORef'-backed validation memo. Module checkers may run in
+-- parallel, but every SQLite and memo operation remains coordinator-owned.
+newtype StoreCoordinator = StoreCoordinator (MVar ())
+
+newStoreCoordinator :: IO StoreCoordinator
+newStoreCoordinator = StoreCoordinator <$> newMVar ()
+
+withStoreCoordinator :: StoreCoordinator -> IO value -> IO value
+withStoreCoordinator (StoreCoordinator ownership) action =
+ withMVar ownership (const action)
+
-- | A completely validated, inert cached module. Runtime authority is
-- minted only after this value is adopted by 'Checking.Module'.
data CachedModuleInstallation = CachedModuleInstallation
@@ -157,8 +177,6 @@ data StoreMemo = StoreMemo
, memoCheckedObjects :: !(IORef.IORef CheckedObjectClosure)
, memoValidatedPropositions :: !(IORef.IORef
(Map PropositionId CheckedPropositionContent))
- , memoSemanticInventories :: !(IORef.IORef
- (Map SemanticInterfaceId SemanticInventory))
, memoValidatedArtifacts :: !(IORef.IORef (Set ModuleArtifactId))
, memoSyntaxValidationVisits :: !(IORef.IORef Int)
, memoSemanticValidationVisits :: !(IORef.IORef Int)
@@ -167,8 +185,9 @@ data StoreMemo = StoreMemo
, memoArtifactValidationVisits :: !(IORef.IORef Int)
}
--- Complete aggregate inventories keep validation direct for the current
--- walking subset. Measure long chains before adding Phase 6 sharing.
+-- Root-scoped validation carries one flat inventory through a deterministic
+-- visited fold. Immutable rows and their validation results are memoized
+-- above, but complete transitive inventories are not retained per interface.
data SemanticInventory = SemanticInventory
!(Set SemanticFactOccurrenceFingerprint)
!(Map SemanticName SemanticFactOccurrenceFingerprint)
@@ -203,7 +222,6 @@ newStoreMemo (Store _path theory _connection) = do
validatedSemantic <- IORef.newIORef Set.empty
checkedObjects <- IORef.newIORef emptyClosure
validatedPropositions <- IORef.newIORef Map.empty
- semanticInventories <- IORef.newIORef Map.empty
validatedArtifacts <- IORef.newIORef Set.empty
syntaxVisits <- IORef.newIORef 0
semanticVisits <- IORef.newIORef 0
@@ -221,7 +239,6 @@ newStoreMemo (Store _path theory _connection) = do
, memoValidatedSemantic = validatedSemantic
, memoCheckedObjects = checkedObjects
, memoValidatedPropositions = validatedPropositions
- , memoSemanticInventories = semanticInventories
, memoValidatedArtifacts = validatedArtifacts
, memoSyntaxValidationVisits = syntaxVisits
, memoSemanticValidationVisits = semanticVisits
@@ -1654,7 +1671,6 @@ validateModuleArtifactClosure memo store root = do
(moduleArtifactResultSemantic artifact)
void
(validateSemanticInventory
- Set.empty
(moduleArtifactResultSemantic artifact))
case checked of
Left failure ->
@@ -1734,6 +1750,8 @@ validateModuleArtifactClosure memo store root = do
traverse_
(validateSemantic (Set.insert identity path))
(semanticInterfaceDirectInputs interface)
+ operationBindings <-
+ semanticOperationBindings Set.empty identity
validateObjectRoots objects
closure <- Except.liftIO
(IORef.readIORef (memoCheckedObjects memo))
@@ -1745,7 +1763,7 @@ validateModuleArtifactClosure memo store root = do
(semanticGlobalBindingKey binding)
(semanticGlobalBindingTarget binding))
(validateSemanticGlobalBindingTarget
- closure binding)))
+ operationBindings closure binding)))
bindings
traverse_ validateProposition propositions
traverse_ validateOccurrence
@@ -1758,6 +1776,33 @@ validateModuleArtifactClosure memo store root = do
(memoValidatedSemantic memo)
(Set.insert identity))
+ semanticOperationBindings path identity
+ | identity `Set.member` path = pure Set.empty
+ | otherwise = do
+ interface <- requireMemo
+ SemanticInterfaces
+ (cacheDigestBytes
+ (semanticInterfaceIdDigest identity))
+ (memoSemantic memo store identity)
+ inherited <-
+ traverse
+ (semanticOperationBindings
+ (Set.insert identity path))
+ (semanticInterfaceDirectInputs interface)
+ let local =
+ Set.fromList
+ [ ( semanticStructureOperationSymbol operation
+ , semanticStructureOperationObject operation
+ )
+ | declaration <-
+ semanticInterfaceDeclarations interface
+ , descriptor <- semanticEnvironmentStructures
+ (declarationDeltaEnvironment declaration)
+ , operation <-
+ semanticStructureDescriptorOperations descriptor
+ ]
+ pure (Set.unions (local : inherited))
+
validateObjectRoots identities = do
closure <- Except.liftIO
(IORef.readIORef (memoCheckedObjects memo))
@@ -1843,83 +1888,57 @@ validateModuleArtifactClosure memo store root = do
proposition
(semanticFactAuthority occurrence))))
- validateSemanticInventory path identity = do
- inventories <- Except.liftIO
- (IORef.readIORef (memoSemanticInventories memo))
- case Map.lookup identity inventories of
- Just inventory ->
- pure inventory
- Nothing
- | identity `Set.member` path ->
- pure
- (SemanticInventory
- Set.empty Map.empty Map.empty)
- | otherwise -> do
- interface <- requireMemo
- SemanticInterfaces
- (cacheDigestBytes
- (semanticInterfaceIdDigest identity))
- (memoSemantic memo store identity)
- parents <- traverse
- (validateSemanticInventory
- (Set.insert identity path))
- (semanticInterfaceDirectInputs interface)
- SemanticInventory
- parentFacts parentAliases parentGlobals <-
- foldM mergeInventory
- (SemanticInventory
- Set.empty Map.empty Map.empty)
- parents
- let declarations =
- semanticInterfaceDeclarations interface
- localFacts = Set.fromList
- [ semanticFactFingerprint occurrence
- | declaration <- declarations
- , occurrence <- declarationDeltaFacts declaration
- ]
- visibleFacts = parentFacts <> localFacts
- aliases <- foldM
- (insertAlias visibleFacts)
- parentAliases
- [ alias
- | declaration <- declarations
- , alias <- declarationDeltaAliases declaration
- ]
- globals <- foldM
- insertGlobal
- parentGlobals
- [ binding
- | declaration <- declarations
- , binding <- semanticEnvironmentBindings
- (declarationDeltaEnvironment declaration)
- ]
- let inventory =
- SemanticInventory
- visibleFacts aliases globals
- Except.liftIO
- (IORef.modifyIORef'
- (memoSemanticInventories memo)
- (Map.insert identity inventory))
- pure inventory
-
- mergeInventory
- (SemanticInventory facts aliases globals)
- (SemanticInventory moreFacts moreAliases moreGlobals) = do
- merged <- foldM
- (\current (name, target) ->
- insertNamedAlias name target current)
- aliases
- (Map.toAscList moreAliases)
- mergedGlobals <- foldM
- (\current (key, target) ->
- insertGlobalBinding key target current)
- globals
- (Map.toAscList moreGlobals)
- pure
- (SemanticInventory
- (facts <> moreFacts)
- merged
- mergedGlobals)
+ validateSemanticInventory identity =
+ snd
+ <$> foldSemanticInventory
+ Set.empty
+ (SemanticInventory Set.empty Map.empty Map.empty)
+ identity
+
+ foldSemanticInventory visited inventory identity
+ | identity `Set.member` visited =
+ pure (visited, inventory)
+ | otherwise = do
+ interface <- requireMemo
+ SemanticInterfaces
+ (cacheDigestBytes
+ (semanticInterfaceIdDigest identity))
+ (memoSemantic memo store identity)
+ (parentVisited, parentInventory) <-
+ foldM
+ (\(seen, current) parent ->
+ foldSemanticInventory seen current parent)
+ (Set.insert identity visited, inventory)
+ (semanticInterfaceDirectInputs interface)
+ let declarations = semanticInterfaceDeclarations interface
+ SemanticInventory
+ parentFacts parentAliases parentGlobals =
+ parentInventory
+ localFacts = Set.fromList
+ [ semanticFactFingerprint occurrence
+ | declaration <- declarations
+ , occurrence <- declarationDeltaFacts declaration
+ ]
+ visibleFacts = parentFacts <> localFacts
+ aliases <- foldM
+ (insertAlias visibleFacts)
+ parentAliases
+ [ alias
+ | declaration <- declarations
+ , alias <- declarationDeltaAliases declaration
+ ]
+ globals <- foldM
+ insertGlobal
+ parentGlobals
+ [ binding
+ | declaration <- declarations
+ , binding <- semanticEnvironmentBindings
+ (declarationDeltaEnvironment declaration)
+ ]
+ pure
+ ( parentVisited
+ , SemanticInventory visibleFacts aliases globals
+ )
insertGlobal globals binding =
insertGlobalBinding