summaryrefslogtreecommitdiff
path: root/source/Felix/Test/Unit/Declaration.hs
diff options
context:
space:
mode:
Diffstat (limited to 'source/Felix/Test/Unit/Declaration.hs')
-rw-r--r--source/Felix/Test/Unit/Declaration.hs3596
1 files changed, 3596 insertions, 0 deletions
diff --git a/source/Felix/Test/Unit/Declaration.hs b/source/Felix/Test/Unit/Declaration.hs
new file mode 100644
index 0000000..f3d9be7
--- /dev/null
+++ b/source/Felix/Test/Unit/Declaration.hs
@@ -0,0 +1,3596 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Felix.Test.Unit.Declaration (unitTests) where
+
+import Base
+import Felix.Checking.Authority qualified as Authority
+import Felix.Checking.Backend.Problem qualified as Backend
+import Felix.Checking.Core qualified as Core
+import Felix.Checking.Declaration qualified as Declaration
+import Felix.Checking.Foundation qualified as Foundation
+import Felix.Checking.Exact qualified as Exact
+import Felix.Checking.Exact.Vocabulary qualified as Vocabulary
+import Felix.Checking.Identity qualified as Identity
+import Felix.Checking.Kernel.Derivation qualified as Kernel
+import Felix.Checking.SetConstruction qualified as SetConstruction
+import Felix.Checking.Semantic qualified as Semantic
+import Felix.Checking.Typed.Inductive qualified as Typed
+import Felix.Math.Codec
+import Felix.Module
+import Felix.Source
+import Felix.Store qualified as Store
+import Felix.Meaning qualified as Meaning
+import Felix.Provers qualified as Provers
+import Felix.Report.Location
+import Felix.Syntax.Abstract qualified as Raw
+import Felix.Syntax.Interface qualified as Syntax
+import Felix.Syntax.Internal qualified as Internal
+import Felix.Syntax.Lexicon qualified as Lexicon
+
+import Data.List.NonEmpty qualified as NonEmpty
+import Data.IORef qualified as IORef
+import Data.Set qualified as Set
+import Data.Text qualified as Text
+import Data.Text.Encoding qualified as TextEncoding
+import Data.Vector qualified as Vector
+import Numeric.Natural (Natural)
+import Control.Exception (bracket)
+import Control.Exception qualified as Exception
+import Control.Monad.Except (runExceptT)
+import Control.Monad.State (evalState)
+import System.Directory qualified as Directory
+import System.FilePath.Posix qualified as Posix
+import Test.Tasty
+import Test.Tasty.HUnit
+
+
+unitTests :: TestTree
+unitTests =
+ testGroup "Typed declaration seam"
+ [ testCase "enforces staged candidate order"
+ enforcesStagedCandidateOrder
+ , testCase "retains only appended declaration prefixes"
+ retainsOnlyAppendedPrefixes
+ , testCase "makes declaration failures terminal"
+ makesDeclarationFailuresTerminal
+ , testCase "propagates unsafe authority through local claims"
+ propagatesUnsafeAuthorityThroughLocalClaims
+ , testCase "aggregates exact Vampire obligations"
+ aggregatesExactVampireObligations
+ , testCase "validates complete resolver batches before rejection"
+ validatesCompleteResolverBatchesBeforeRejection
+ , testCase "rejects retained-plan admission drift fatally"
+ rejectsRetainedPlanAdmissionDrift
+ , testCase "preserves source-axiom safety through Vampire validation"
+ preservesSourceAxiomSafetyThroughVampireValidation
+ , testCase "materializes a sealed import with fresh authority"
+ materializesSealedImport
+ , testCase "reconstructs exact imported global bindings"
+ reconstructsImportedGlobalBindings
+ , testCase "elaborates scoped exact propositions"
+ elaboratesScopedExactPropositions
+ , testCase "lowers fixed equality aliases without global support"
+ lowersFixedEqualityAliases
+ , testCase "scopes quantified proposition terms"
+ scopesQuantifiedPropositionTerms
+ , testCase "prepares exact claim envelopes"
+ preparesExactClaimEnvelopes
+ , testCase "lowers exact separation comprehensions"
+ lowersExactSeparationComprehensions
+ , testCase "lowers exact replacement telescopes"
+ lowersExactReplacementTelescopes
+ , testCase "lowers exact finite sets"
+ lowersExactFiniteSets
+ , testCase "lowers exact ordinary declarations"
+ lowersExactOrdinaryDeclarations
+ , testCase "folds transitive and diamond import evidence"
+ foldsTransitiveAndDiamondEvidence
+ , testCase "validates exact kernel construction descriptors"
+ validatesExactKernelConstructionDescriptors
+ , testCase "authorizes exact datatype compilation families"
+ authorizesExactDatatypeCompilationFamilies
+ , testCase "reuses exact compiled declaration validation"
+ reusesExactCompiledDeclarationValidation
+ , testCase "keeps fatal validation lookup failures out of declarations"
+ keepsFatalValidationLookupFailuresOutOfDeclarations
+ ]
+
+data FatalValidationLookup = FatalValidationLookup
+ deriving (Show)
+
+instance Exception.Exception FatalValidationLookup
+
+keepsFatalValidationLookupFailuresOutOfDeclarations :: Assertion
+keepsFatalValidationLookupFailuresOutOfDeclarations = do
+ fixture <- makeFixture
+ prepared <- makePreparedObligation
+ fixture
+ Foundation.EmptyCharacteristic
+ let lookup = proofOnlyValidationLookup
+ (const (Exception.throwIO FatalValidationLookup))
+ action = Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "fatal-validation-lookup") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "fatal-validation-lookup")
+ Declaration.authorizeVampireCandidate candidate
+ (Declaration.acceptVampireObligation prepared)
+ result <- Exception.try
+ (runDriverWithValidation fixture lookup action)
+ :: IO
+ (Either
+ FatalValidationLookup
+ (Declaration.DriverResult
+ Void
+ ((), Declaration.CommittedDeclarationBatch)))
+ case result of
+ Left FatalValidationLookup -> pure ()
+ Right _ ->
+ assertFailure "fatal validation lookup became a driver result"
+
+enforcesStagedCandidateOrder :: Assertion
+enforcesStagedCandidateOrder = do
+ fixture <- makeFixture
+ accepted <- runSuccessful fixture do
+ result <- Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "staged-success") do
+ first <- Declaration.reserveCandidate
+ (factSpec fixture "first")
+ later <- Declaration.reserveCandidateBatch
+ ( factSpec fixture "later-a"
+ :| [factSpec fixture "later-b"]
+ )
+ Declaration.authorizeCompiledDeclaration do
+ Declaration.authorizeSourceAxiomCandidate first
+ traverse_
+ (\candidate ->
+ Declaration.authorizeKernelProofCandidate
+ candidate do
+ premise <-
+ Declaration.useStagedCandidate first
+ pure
+ (Kernel.importedFactDerivation premise))
+ later
+ pure result
+ let (_value, batch) = accepted
+ assertEqual
+ "all source-ordered candidates appended"
+ 3
+ (length
+ (Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta batch)))
+
+ provenance <- runDriver fixture (priorDeclarationUse fixture)
+ case provenance of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.CandidateOutsideDeclaration slot))
+ prefix -> do
+ assertEqual
+ "cross-declaration staged premise"
+ (localFact fixture 0)
+ slot
+ assertSingleCompletedPrefix prefix
+ _other ->
+ assertFailure
+ "cross-declaration staged provenance was not rejected"
+
+ traverse_
+ (\(label, action, expectedPremise, expectedCandidate) -> do
+ result <- runDriver fixture action
+ case result of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.StagedPremiseNotEarlier
+ premiseSlot premiseStage
+ candidateSlot candidateStage))
+ _prefix -> do
+ assertEqual (label <> " premise slot")
+ expectedPremise premiseSlot
+ assertEqual (label <> " candidate slot")
+ expectedCandidate candidateSlot
+ assertBool (label <> " rejected non-earlier stage")
+ (premiseStage >= candidateStage)
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed other)
+ _prefix ->
+ assertFailure
+ (label <> ": unexpected error " <> show other)
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed _failure)
+ _prefix ->
+ assertFailure
+ (label <> ": unexpected ordinary driver failure")
+ Declaration.DriverSucceeded{} ->
+ assertFailure (label <> ": invalid staged use succeeded")
+ Declaration.DriverSealFailed{} ->
+ assertFailure (label <> ": invalid staged use reached sealing"))
+ [ ( "self"
+ , selfUse fixture
+ , localFact fixture 0
+ , localFact fixture 0
+ )
+ , ( "same stage"
+ , sameStageUse fixture
+ , localFact fixture 1
+ , localFact fixture 0
+ )
+ , ( "forward"
+ , forwardUse fixture
+ , localFact fixture 1
+ , localFact fixture 0
+ )
+ ]
+ where
+ localFact fixture ordinal =
+ Semantic.factSlot
+ (fixtureOwner fixture)
+ (localFactOrdinal ordinal)
+
+ selfUse fixture =
+ Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "self") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "self")
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeKernelProofCandidate candidate do
+ premise <- Declaration.useStagedCandidate candidate
+ pure (Kernel.importedFactDerivation premise))
+
+ sameStageUse fixture =
+ Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "same-stage") do
+ candidates <- Declaration.reserveCandidateBatch
+ ( factSpec fixture "same-a"
+ :| [factSpec fixture "same-b"]
+ )
+ let first = NonEmpty.head candidates
+ second = NonEmpty.last candidates
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeKernelProofCandidate first do
+ premise <- Declaration.useStagedCandidate second
+ pure (Kernel.importedFactDerivation premise))
+
+ forwardUse fixture =
+ Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "forward") do
+ first <- Declaration.reserveCandidate
+ (factSpec fixture "forward-a")
+ second <- Declaration.reserveCandidate
+ (factSpec fixture "forward-b")
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeKernelProofCandidate first do
+ premise <- Declaration.useStagedCandidate second
+ pure (Kernel.importedFactDerivation premise))
+
+ priorDeclarationUse fixture = do
+ (premise, _batch) <- Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "prior-stage") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "prior-stage")
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeSourceAxiomCandidate candidate)
+ pure candidate
+ void
+ (Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "later-stage") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "later-stage")
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeKernelProofCandidate candidate do
+ imported <-
+ Declaration.useStagedCandidate premise
+ pure (Kernel.importedFactDerivation imported)))
+
+retainsOnlyAppendedPrefixes :: Assertion
+retainsOnlyAppendedPrefixes = do
+ fixture <- makeFixture
+ outcome <- runDriver fixture do
+ (_value, _firstBatch) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "accepted") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "accepted")
+ Declaration.authorizeSourceAxiomCandidate candidate
+ Declaration.failModuleDriver
+ ("later checker failure" :: Text)
+ case outcome of
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed reason) prefix -> do
+ assertEqual
+ "driver reports the later ordinary failure"
+ "later checker failure"
+ reason
+ assertSingleCompletedPrefix prefix
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed err) _prefix ->
+ assertFailure
+ ("unexpected declaration failure: " <> show err)
+ Declaration.DriverSucceeded{} ->
+ assertFailure "ordinary driver failure was lost"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "ordinary driver failure became a seal failure"
+
+makesDeclarationFailuresTerminal :: Assertion
+makesDeclarationFailuresTerminal = do
+ fixture <- makeFixture
+ outcome <- runDriver fixture do
+ void
+ (Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "accepted-before-failure") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "accepted-before-failure")
+ Declaration.authorizeSourceAxiomCandidate candidate)
+ void
+ (Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "rolled-back") do
+ void
+ (Declaration.reserveCandidate
+ (factSpec fixture "uncommitted")))
+ -- This declaration must be unreachable after the terminal failure.
+ void
+ (Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "must-not-publish") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "must-not-publish")
+ Declaration.authorizeSourceAxiomCandidate candidate)
+ case outcome of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ Declaration.DeclarationHasUnauthorizedCandidates)
+ prefix ->
+ assertSingleCompletedPrefix prefix
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed other) _prefix ->
+ assertFailure
+ ("unexpected declaration failure: " <> show other)
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed _failure) _prefix ->
+ assertFailure "unexpected ordinary driver failure"
+ Declaration.DriverSucceeded{} ->
+ assertFailure "failed declaration was skipped"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "failed declaration reached sealing"
+
+assertSingleCompletedPrefix
+ :: Declaration.PendingModulePrefix
+ -> Assertion
+assertSingleCompletedPrefix prefix = do
+ let batches =
+ Declaration.pendingModulePrefixBatches prefix
+ assertEqual "one completed envelope survives" 1 (length batches)
+ case batches of
+ [batch] -> do
+ let expected =
+ Declaration.committedBatchNextPrefix batch
+ assertEqual
+ "failed declaration did not advance the prefix"
+ expected
+ (Declaration.pendingModulePrefixCurrent prefix)
+ assertEqual
+ "retained envelope ends at the exposed prefix"
+ expected
+ (Declaration.committedBatchNextPrefix batch)
+ _ -> pure ()
+
+propagatesUnsafeAuthorityThroughLocalClaims :: Assertion
+propagatesUnsafeAuthorityThroughLocalClaims = do
+ fixture <- makeFixture
+ result <- runSuccessful fixture do
+ (_sourceValue, sourceBatch) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "source-axiom") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "source")
+ Declaration.authorizeSourceAxiomCandidate candidate
+ sourceOccurrence <- requireSingleOccurrence sourceBatch
+ let
+ sourceFingerprint =
+ Semantic.semanticFactFingerprint sourceOccurrence
+ (_derivedValue, derivedBatch) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "local-claim") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "derived")
+ Declaration.authorizeKernelProofCandidate candidate do
+ sourcePremise <-
+ Declaration.useAuthorizedFact sourceFingerprint
+ claim <- Declaration.proveLocalKernelClaim
+ (fixtureProposition fixture)
+ (Kernel.importedFactDerivation sourcePremise)
+ claimPremise <- Declaration.useLocalClaim claim
+ pure (Kernel.importedFactDerivation claimPremise)
+ pure derivedBatch
+ occurrence <-
+ case Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta result) of
+ [single] -> pure single
+ facts ->
+ assertFailure
+ ("unexpected fact count: " <> show (length facts))
+ >> fail "unreachable"
+ let authority = Semantic.semanticFactAuthority occurrence
+ assertEqual
+ "local claim cannot erase source-axiom safety"
+ (Authority.authoritySafety
+ (Authority.singletonEscapeKind Authority.SourceAxiom))
+ (Authority.factAuthoritySafety authority)
+ case Declaration.committedBatchProofValidations result of
+ [record] ->
+ assertEqual
+ "local support is absent from the compact direct authorization"
+ (Authority.CheckedSourceProof [])
+ (Authority.validationDirectAuthorization
+ (Semantic.proofValidationRecordCertificate record))
+ records ->
+ assertFailure
+ ("unexpected proof validation count: "
+ <> show (length records))
+
+aggregatesExactVampireObligations :: Assertion
+aggregatesExactVampireObligations =
+ withTemporaryDirectory "felix-declaration-vampire" \root -> do
+ fixture <- makeFixture
+ let executable = root Posix.</> "vampire"
+ writeAcceptedVampire executable
+ first <- makePreparedObligation
+ fixture
+ Foundation.EmptyCharacteristic
+ second <- makePreparedObligation
+ fixture
+ Foundation.PairSetCharacteristic
+ let exactResolver = acceptedResolver executable
+ freshOutcome <-
+ (runDriverWithResolver fixture exactResolver do
+ (_value, committed) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "two-vampire-obligations") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "two-vampire-obligations")
+ Declaration.authorizeVampireCandidate candidate do
+ Declaration.acceptVampireObligation first
+ Declaration.acceptVampireObligation second
+ pure committed
+ :: IO
+ (Declaration.DriverResult Text
+ Declaration.CommittedDeclarationBatch))
+ (batch, freshPrefix) <-
+ case freshOutcome of
+ Declaration.DriverSucceeded value _ prefix _closure ->
+ pure (value, prefix)
+ Declaration.DriverFailed failure _ ->
+ assertFailure
+ ("fresh Vampire fixture failed: " <> show failure)
+ >> fail "unreachable"
+ Declaration.DriverSealFailed failure _ ->
+ assertFailure
+ ("fresh Vampire fixture did not seal: "
+ <> show failure)
+ >> fail "unreachable"
+ let expectedRequests =
+ Provers.preparedVerificationRequestId
+ (Provers.preparedTypedProverRequest first)
+ : [Provers.preparedVerificationRequestId
+ (Provers.preparedTypedProverRequest second)]
+ case Declaration.committedBatchProofValidations batch of
+ [record] ->
+ assertEqual
+ "accepted requests retain source order"
+ (Authority.CheckedSourceProof expectedRequests)
+ (Authority.validationDirectAuthorization
+ (Semantic.proofValidationRecordCertificate record))
+ records ->
+ assertFailure
+ ("unexpected proof validation count: "
+ <> show (length records))
+
+ cachedRecord <-
+ case Declaration.committedBatchProofValidations batch of
+ [record] -> pure record
+ records ->
+ assertFailure
+ ("unexpected cached proof records: "
+ <> show (length records))
+ >> fail "unreachable"
+ cachedLookupKey <- IORef.newIORef Nothing
+ cached <- runSuccessfulWithValidation fixture
+ (proofOnlyValidationLookup
+ (\key -> do
+ IORef.writeIORef cachedLookupKey (Just key)
+ pure (Just cachedRecord))) do
+ (_value, committed) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "two-vampire-obligations") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "two-vampire-obligations")
+ Declaration.authorizeVampireCandidate candidate do
+ Declaration.acceptVampireObligation first
+ Declaration.acceptVampireObligation second
+ pure committed
+ publishedRecord <-
+ case Declaration.committedBatchProofValidations cached of
+ [record] -> pure record
+ records ->
+ assertFailure
+ ("unexpected cached validation records: "
+ <> show (length records))
+ >> fail "unreachable"
+ assertEqual
+ "cached authorization preserves the exact direct proof"
+ (Authority.CheckedSourceProof expectedRequests)
+ (Authority.validationDirectAuthorization
+ (Semantic.proofValidationRecordCertificate publishedRecord))
+ assertEqual
+ "lookup and publication retain the same validation key"
+ (Semantic.proofValidationRecordKey cachedRecord)
+ (Semantic.proofValidationRecordKey publishedRecord)
+ assertEqual
+ "one proof syntax key governs lookup and publication"
+ (Just
+ (Semantic.proofValidationRecordKey cachedRecord))
+ =<< IORef.readIORef cachedLookupKey
+
+ missLookups <- IORef.newIORef (0 :: Int)
+ missRuns <- IORef.newIORef (0 :: Int)
+ let missLookup = proofOnlyValidationLookup \_key -> do
+ IORef.modifyIORef' missLookups (+ 1)
+ pure Nothing
+ missResolver = Declaration.vampireResolver \prepared -> do
+ IORef.modifyIORef' missRuns (+ 1)
+ resolveAccepted executable prepared
+ miss <- runDriverWithValidationAndResolver
+ fixture
+ missLookup
+ missResolver
+ do
+ (_value, committed) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "two-vampire-obligations") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "two-vampire-obligations")
+ Declaration.authorizeVampireCandidate candidate do
+ Declaration.acceptVampireObligation first
+ Declaration.acceptVampireObligation second
+ pure committed
+ case miss of
+ Declaration.DriverSucceeded{} -> pure ()
+ _ ->
+ assertFailure "warm miss failed"
+ assertEqual "warm miss performs one exact lookup"
+ 1
+ =<< IORef.readIORef missLookups
+ assertEqual "warm miss runs every reached Vampire request"
+ 2
+ =<< IORef.readIORef missRuns
+
+ mismatchRuns <- IORef.newIORef (0 :: Int)
+ let editedSyntax =
+ Semantic.proofSyntaxId "edited-proof-syntax"
+ cachedCertificate =
+ Semantic.proofValidationRecordCertificate cachedRecord
+ corruptedKey =
+ Semantic.proofValidationKey
+ (Identity.theoremId
+ (Authority.factAuthorityTheorem
+ (Authority.validationTarget
+ cachedCertificate)))
+ editedSyntax
+ (Declaration.committedBatchPreviousPrefix batch)
+ corruptedRecord =
+ Semantic.proofValidationRecord
+ corruptedKey
+ cachedCertificate
+ mismatchResolver = Declaration.vampireResolver \prepared -> do
+ IORef.modifyIORef' mismatchRuns (+ 1)
+ resolveAccepted executable prepared
+ mismatchingLookup = proofOnlyValidationLookup
+ (const (pure (Just corruptedRecord)))
+ mismatching <- Exception.try
+ (runDriverWithValidationAndResolver
+ fixture
+ mismatchingLookup
+ mismatchResolver
+ do
+ Declaration.commitProofDeclaration editedSyntax do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "two-vampire-obligations")
+ Declaration.authorizeVampireCandidate candidate
+ (Declaration.acceptVampireObligation first))
+ :: IO
+ (Either
+ Declaration.ValidationIntegrityError
+ (Declaration.DriverResult
+ Text
+ ((), Declaration.CommittedDeclarationBatch)))
+ case mismatching of
+ Left Declaration.CachedValidationIntegrityError{} ->
+ pure ()
+ Right _ ->
+ assertFailure "mismatching hit did not abort as corruption"
+ assertEqual "mismatching hit does not fall back to Vampire"
+ 0
+ =<< IORef.readIORef mismatchRuns
+
+ withOpenedStore fixture root \store -> do
+ expectRightIO
+ (Store.writePendingModulePrefix store freshPrefix)
+ warmCalls <- IORef.newIORef (0 :: Int)
+ let storeLookup = proofOnlyValidationLookup \key -> do
+ IORef.modifyIORef' warmCalls (+ 1)
+ Store.loadProofValidation store key >>= expectRight
+ warm <- runSuccessfulWithValidation fixture
+ storeLookup
+ do
+ (_value, committed) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "two-vampire-obligations") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "two-vampire-obligations")
+ Declaration.authorizeVampireCandidate candidate do
+ Declaration.acceptVampireObligation first
+ Declaration.acceptVampireObligation second
+ pure committed
+ assertEqual "warm lookup executes once through the store"
+ 1
+ =<< IORef.readIORef warmCalls
+ assertEqual "warm path retains cached request IDs"
+ (Authority.CheckedSourceProof expectedRequests)
+ (case Declaration.committedBatchProofValidations warm of
+ [record] ->
+ Authority.validationDirectAuthorization
+ (Semantic.proofValidationRecordCertificate record)
+ records ->
+ error
+ ("unexpected warm validation records: "
+ <> show (length records)))
+
+ emptyProof <- runDriver fixture do
+ Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "empty-vampire-proof") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "empty-vampire-proof")
+ Declaration.authorizeVampireCandidate candidate
+ (pure ())
+ case emptyProof of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ Declaration.VampireProofHasNoAcceptedObligations)
+ prefix ->
+ assertEqual
+ "empty Vampire proof publishes no declaration"
+ 0
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed other) _prefix ->
+ assertFailure
+ ("unexpected empty-proof failure: " <> show other)
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed _failure) _prefix ->
+ assertFailure "unexpected ordinary driver failure"
+ Declaration.DriverSucceeded{} ->
+ assertFailure "empty Vampire proof was authorized"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "empty Vampire proof reached sealing"
+
+ invalidClosure <- expectRight
+ (Identity.validateObjectClosure
+ (Identity.theoryId (fixtureFoundation fixture))
+ [])
+ invalidTarget <- expectRight
+ (Identity.validatePropositionContent
+ invalidClosure
+ (Core.CImp Core.CFalsum Core.CFalsum))
+ invalidCalls <- IORef.newIORef (0 :: Int)
+ let invalidResolver =
+ Declaration.vampireResolver \prepared -> do
+ IORef.modifyIORef' invalidCalls (+ 1)
+ resolveAccepted executable prepared
+ invalid <- runDriverWithResolver fixture invalidResolver do
+ Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "invalid-vampire-target") do
+ candidate <- Declaration.reserveCandidate
+ (Declaration.candidateSpec
+ invalidTarget
+ Semantic.SearchEligible
+ [Semantic.semanticName
+ "invalid-vampire-target"])
+ Declaration.authorizeVampireCandidate candidate
+ (Declaration.acceptVampireObligation first)
+ assertEqual
+ "invalid prepared problem does not invoke Vampire"
+ 0
+ =<< IORef.readIORef invalidCalls
+ case invalid of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ Declaration.VampireTargetMismatch)
+ prefix ->
+ assertEqual
+ "invalid prepared problem publishes no declaration"
+ 0
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed other) _prefix ->
+ assertFailure
+ ("unexpected prepared-problem failure: " <> show other)
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed _failure) _prefix ->
+ assertFailure "unexpected ordinary driver failure"
+ Declaration.DriverSucceeded{} ->
+ assertFailure "invalid prepared problem was authorized"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "invalid prepared problem reached sealing"
+
+ let mismatchedResolver =
+ Declaration.vampireResolver \_prepared ->
+ resolveAccepted executable second
+ mismatch <- runDriverWithResolver fixture mismatchedResolver do
+ Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "mismatched-vampire-request") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "mismatched-vampire-request")
+ Declaration.authorizeVampireCandidate candidate
+ (Declaration.acceptVampireObligation first)
+ case mismatch of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ Declaration.VampireRequestMismatch)
+ prefix ->
+ assertEqual
+ "mismatch publishes no declaration"
+ 0
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed other) _prefix ->
+ assertFailure
+ ("unexpected mismatch failure: " <> show other)
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed _failure) _prefix ->
+ assertFailure "unexpected ordinary driver failure"
+ Declaration.DriverSucceeded{} ->
+ assertFailure "mismatched request was authorized"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "mismatched request reached sealing"
+
+ unrecorded <- runDriver fixture do
+ Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "unrecorded-omission") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "unrecorded-omission")
+ Declaration.authorizeOmittedCandidate candidate
+ (pure ())
+ case unrecorded of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ Declaration.OmittedProofDidNotRecordUse)
+ prefix ->
+ assertEqual
+ "unrecorded omission publishes no declaration"
+ 0
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed other) _prefix ->
+ assertFailure
+ ("unexpected unrecorded-omission failure: "
+ <> show other)
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed _failure) _prefix ->
+ assertFailure "unexpected ordinary driver failure"
+ Declaration.DriverSucceeded{} ->
+ assertFailure "unrecorded omission was authorized"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "unrecorded omission reached sealing"
+
+ calls <- IORef.newIORef (0 :: Int)
+ let countingResolver =
+ Declaration.vampireResolver \prepared -> do
+ IORef.modifyIORef' calls (+ 1)
+ resolveAccepted executable prepared
+ omittedBatch <- runSuccessfulWithResolver fixture countingResolver do
+ (_value, committed) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "omitted-after-obligations") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "omitted-after-obligations")
+ Declaration.authorizeOmittedCandidate candidate do
+ Declaration.acceptVampireObligation first
+ Declaration.acceptVampireObligation second
+ Declaration.recordOmittedUse
+ pure committed
+ assertEqual
+ "omitted proof still checks preceding obligations"
+ 2
+ =<< IORef.readIORef calls
+ case Declaration.committedBatchProofValidations omittedBatch of
+ [record] ->
+ assertEqual
+ "omitted direct authorization discards request IDs"
+ Authority.OmittedAuthorization
+ (Authority.validationDirectAuthorization
+ (Semantic.proofValidationRecordCertificate record))
+ records ->
+ assertFailure
+ ("unexpected omitted validation count: "
+ <> show (length records))
+
+validatesCompleteResolverBatchesBeforeRejection :: Assertion
+validatesCompleteResolverBatchesBeforeRejection =
+ withTemporaryDirectory "felix-declaration-batch-integrity" \root -> do
+ fixture <- makeFixture
+ let executable = root Posix.</> "vampire"
+ firstLocation = mkLocation (FileId 76) 1 1
+ secondLocation = mkLocation (FileId 76) 2 1
+ writeAcceptedVampire executable
+ mismatchedTask <-
+ makePreparedObligation
+ fixture
+ Foundation.EmptyCharacteristic
+ let integrityResolver =
+ Declaration.vampireBatchResolver \_tasks -> do
+ mismatched <- resolveAccepted executable mismatchedTask
+ pure
+ ( Right (Provers.CounterSatisfiable "earlier")
+ :| [mismatched]
+ )
+ integrityOutcome <-
+ (runDriverWithResolver fixture integrityResolver do
+ Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "batch-integrity-priority") do
+ candidates <- Declaration.reserveCandidateBatch
+ ( factSpec fixture "batch-integrity-first"
+ :| [factSpec fixture "batch-integrity-second"]
+ )
+ Declaration.authorizeVampireCandidateBatch
+ ( ( firstLocation
+ , NonEmpty.head candidates
+ , Declaration.prepareCurrentCandidateVampire
+ )
+ :| [ ( secondLocation
+ , NonEmpty.last candidates
+ , Declaration.prepareCurrentCandidateVampire
+ )
+ ]
+ )
+ :: IO
+ (Declaration.DriverResult Text
+ ((), Declaration.CommittedDeclarationBatch)))
+ case integrityOutcome of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.ProofObligationFailedAt
+ location
+ Declaration.VampireRequestMismatch))
+ prefix -> do
+ assertEqual
+ "later request mismatch retains its location"
+ secondLocation
+ location
+ assertEqual
+ "integrity failure rolls back the complete declaration"
+ 0
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("unexpected batch-integrity failure: " <> show failure)
+ Declaration.DriverSucceeded{} ->
+ assertFailure
+ "earlier ordinary rejection concealed no integrity failure"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "invalid batch reached module sealing"
+
+ prepared <-
+ makePreparedObligation
+ fixture
+ Foundation.EmptyCharacteristic
+ let excessResolver =
+ Declaration.vampireBatchResolver \_tasks ->
+ pure
+ ( Right (Provers.CounterSatisfiable "first")
+ :| [Right (Provers.CounterSatisfiable "excess")]
+ )
+ excessOutcome <-
+ (runDriverWithResolver fixture excessResolver do
+ Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "singleton-excess-result") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "singleton-excess-result")
+ Declaration.authorizeVampireCandidate candidate
+ (Declaration.acceptVampireObligation prepared)
+ :: IO
+ (Declaration.DriverResult Text
+ ((), Declaration.CommittedDeclarationBatch)))
+ case excessOutcome of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.VampireResolverBatchSizeMismatch 1 2))
+ prefix ->
+ assertEqual
+ "malformed singleton response publishes no declaration"
+ 0
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("unexpected singleton-cardinality failure: "
+ <> show failure)
+ Declaration.DriverSucceeded{} ->
+ assertFailure "singleton resolver ignored an excess result"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "malformed singleton reached module sealing"
+
+rejectsRetainedPlanAdmissionDrift :: Assertion
+rejectsRetainedPlanAdmissionDrift = do
+ fixture <- makeFixture
+ let checked =
+ Declaration.checkedProofDeclaration
+ (Semantic.proofSyntaxId "planned-admission-drift")
+ []
+ []
+ []
+ []
+ [ Declaration.checkedCandidate
+ (factSpec fixture "planned-admission-drift")
+ Declaration.checkedSourceAxiomPlanning
+ :| []
+ ]
+ ()
+ action = do
+ planned <-
+ Declaration.runProspectiveLoweringDriver
+ (Declaration.planCheckedDeclaration checked)
+ >>= either Declaration.failDeclarationDriver pure
+ Declaration.admitPlannedCheckedDeclaration planned
+ (\() stages ->
+ case concatMap toList stages of
+ [candidate] ->
+ Declaration.authorizeOmittedCandidate candidate
+ Declaration.recordOmittedUse
+ _ -> error "planned drift fixture candidate shape")
+ outcome <-
+ Exception.try (runDriver fixture action)
+ :: IO
+ (Either
+ Declaration.PlanningIntegrityError
+ (Declaration.DriverResult
+ Void
+ Declaration.CommittedDeclarationBatch))
+ case outcome of
+ Left (Declaration.PlanningIntegrityError diagnostic) ->
+ assertBool "fatal mismatch identifies prospective contract drift"
+ ("prospective contract" `Text.isInfixOf` diagnostic)
+ Right _ ->
+ assertFailure
+ "a changed admitted authority was accepted against its plan"
+
+preservesSourceAxiomSafetyThroughVampireValidation :: Assertion
+preservesSourceAxiomSafetyThroughVampireValidation =
+ withTemporaryDirectory "felix-declaration-source-axiom" \root -> do
+ fixture <- makeFixture
+ let executable = root Posix.</> "vampire"
+ writeAcceptedVampire executable
+ prepared <-
+ makePreparedObligationWithPremise
+ fixture
+ (fixtureSourceAxiomFingerprint fixture)
+ freshCalls <- IORef.newIORef (0 :: Int)
+ let freshResolver = Declaration.vampireResolver \task -> do
+ IORef.modifyIORef' freshCalls (+ 1)
+ resolveAccepted executable task
+ freshOutcome <-
+ (runDriverWithResolver fixture freshResolver
+ (sourceAxiomThenVampire fixture prepared)
+ :: IO
+ (Declaration.DriverResult Text
+ Declaration.CommittedDeclarationBatch))
+ assertEqual
+ "fresh source-axiom theorem invokes Vampire once"
+ 1
+ =<< IORef.readIORef freshCalls
+ freshBatch <-
+ case freshOutcome of
+ Declaration.DriverSucceeded batch _ _ _closure ->
+ pure batch
+ Declaration.DriverFailed failure _ ->
+ assertFailure
+ ("fresh source-axiom driver failed: "
+ <> show failure)
+ >> fail "unreachable"
+ Declaration.DriverSealFailed failure _ ->
+ assertFailure
+ ("fresh source-axiom driver did not seal: "
+ <> show failure)
+ >> fail "unreachable"
+ let freshRecord = singleProofValidation freshBatch
+ assertEqual
+ "fresh theorem retains source-axiom safety"
+ sourceAxiomSafety
+ (Authority.factAuthoritySafety
+ (Authority.validationTarget
+ (Semantic.proofValidationRecordCertificate freshRecord)))
+ separationCalls <- IORef.newIORef (0 :: Int)
+ let separationResolver = Declaration.vampireResolver \task -> do
+ IORef.modifyIORef' separationCalls (+ 1)
+ resolveAccepted executable task
+ separated <-
+ (runDriverWithResolver fixture separationResolver do
+ void
+ (Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "source-axiom") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "source-axiom")
+ Declaration.authorizeSourceAxiomCandidate candidate)
+ Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "atp-does-not-import") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "atp-does-not-import")
+ Declaration.authorizeKernelProofCandidate candidate do
+ Declaration.acceptVampireObligation prepared
+ pure
+ (Kernel.importedFactDerivation
+ (Kernel.importIx 0))
+ :: IO
+ (Declaration.DriverResult Text
+ ((), Declaration.CommittedDeclarationBatch)))
+ assertEqual "mixed proof executes its ATP obligation"
+ 1
+ =<< IORef.readIORef separationCalls
+ case separated of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.KernelCompletionFailed
+ (Kernel.KernelReplayImportOutOfBounds index)))
+ prefix -> do
+ assertEqual "ATP premise is absent from kernel imports"
+ (Kernel.importIx 0)
+ index
+ assertEqual "failed mixed proof retains only its prefix"
+ 1
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("unexpected mixed-proof failure: " <> show failure)
+ Declaration.DriverSucceeded{} ->
+ assertFailure "ATP premise entered the kernel import inventory"
+ Declaration.DriverSealFailed{} ->
+ assertFailure "mixed proof unexpectedly reached sealing"
+ withOpenedStore fixture root \store -> do
+ freshPrefix <-
+ case freshOutcome of
+ Declaration.DriverSucceeded _ _ prefix _closure ->
+ pure prefix
+ Declaration.DriverFailed failure _ ->
+ assertFailure
+ ("fresh source-axiom driver failed: "
+ <> show failure)
+ >> fail "unreachable"
+ Declaration.DriverSealFailed failure _ ->
+ assertFailure
+ ("fresh source-axiom driver did not seal: "
+ <> show failure)
+ >> fail "unreachable"
+ expectRightIO
+ (Store.writePendingModulePrefix store freshPrefix)
+ warmCalls <- IORef.newIORef (0 :: Int)
+ let storeLookup = proofOnlyValidationLookup \key -> do
+ IORef.modifyIORef' warmCalls (+ 1)
+ Store.loadProofValidation store key >>= expectRight
+ warmBatch <- runSuccessfulWithValidation fixture
+ storeLookup
+ (sourceAxiomThenVampire fixture prepared)
+ assertEqual
+ "warm source-axiom theorem performs one store lookup"
+ 1
+ =<< IORef.readIORef warmCalls
+ assertEqual
+ "warm theorem retains source-axiom safety"
+ sourceAxiomSafety
+ (Authority.factAuthoritySafety
+ (Authority.validationTarget
+ (Semantic.proofValidationRecordCertificate
+ (singleProofValidation warmBatch))))
+ where
+ sourceAxiomSafety =
+ Authority.authoritySafety
+ (Authority.singletonEscapeKind Authority.SourceAxiom)
+
+ singleProofValidation batch =
+ case Declaration.committedBatchProofValidations batch of
+ [record] -> record
+ records ->
+ error
+ ("unexpected proof validation count: "
+ <> show (length records))
+
+sourceAxiomThenVampire
+ :: Fixture
+ -> Provers.PreparedTypedProverTask
+ Semantic.SemanticFactOccurrenceFingerprint
+ Void
+ ()
+ Identity.ObjectId
+ -> Declaration.ModuleDriver failure
+ Declaration.CommittedDeclarationBatch
+sourceAxiomThenVampire fixture prepared = do
+ void
+ (Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "source-axiom") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "source-axiom")
+ Declaration.authorizeSourceAxiomCandidate candidate)
+ (_value, batch) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "source-axiom-vampire") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "source-axiom-vampire")
+ Declaration.authorizeVampireCandidate candidate
+ (Declaration.acceptVampireObligation prepared)
+ pure batch
+
+fixtureSourceAxiomFingerprint
+ :: Fixture
+ -> Semantic.SemanticFactOccurrenceFingerprint
+fixtureSourceAxiomFingerprint fixture =
+ Semantic.semanticFactOccurrenceFingerprint
+ (Semantic.factSlot
+ (fixtureOwner fixture)
+ (localFactOrdinal 0))
+ (Authority.factAuthority
+ (Identity.theoremRef
+ (Identity.theoryId (fixtureFoundation fixture))
+ (Identity.checkedPropositionId
+ (fixtureProposition fixture)))
+ (Authority.authoritySafety
+ (Authority.singletonEscapeKind Authority.SourceAxiom)))
+
+makePreparedObligationWithPremise
+ :: Fixture
+ -> Semantic.SemanticFactOccurrenceFingerprint
+ -> IO
+ (Provers.PreparedTypedProverTask
+ Semantic.SemanticFactOccurrenceFingerprint
+ Void
+ ()
+ Identity.ObjectId)
+makePreparedObligationWithPremise fixture fingerprint = do
+ claim <- expectRight
+ (Backend.supportedProposition
+ (Vector.empty :: Vector.Vector (Void, Core.CoreType))
+ (Core.embedClosedCore
+ []
+ (Identity.checkedPropositionTerm
+ (fixtureProposition fixture))))
+ factProposition <- expectRight
+ (Backend.supportedProposition
+ (Vector.empty :: Vector.Vector (Void, Core.CoreType))
+ (Core.embedClosedCore
+ []
+ (Identity.checkedPropositionTerm
+ (fixtureProposition fixture))))
+ capability <- expectRight
+ (Backend.classifySupportedProposition
+ (const Nothing)
+ factProposition)
+ problem <- expectRight
+ (Backend.planTypedProblem
+ (const Nothing)
+ (Vector.singleton
+ (Backend.typedBackendFact
+ fingerprint
+ factProposition
+ capability))
+ claim
+ []
+ []
+ Backend.FirstOrderLocals
+ Backend.ExplicitHigherOrderJustification)
+ expectRight
+ (Provers.prepareTypedProverTask
+ Provers.DirectTask
+ problem)
+
+makePreparedObligation
+ :: Fixture
+ -> Foundation.FoundationAxiomTag
+ -> IO
+ (Provers.PreparedTypedProverTask
+ Semantic.SemanticFactOccurrenceFingerprint
+ Void
+ ()
+ Identity.ObjectId)
+makePreparedObligation fixture tag = do
+ claim <- expectRight
+ (Backend.supportedProposition
+ (Vector.empty :: Vector.Vector (Void, Core.CoreType))
+ (Core.embedClosedCore
+ []
+ (Identity.checkedPropositionTerm
+ (fixtureProposition fixture))))
+ problem <- expectRight
+ (Backend.planTypedProblem
+ (const Nothing)
+ Vector.empty
+ claim
+ []
+ [Backend.typedFoundationAuxiliaryInput
+ (fixtureFoundation fixture)
+ tag]
+ Backend.CompleteLocals
+ Backend.ExplicitHigherOrderJustification)
+ expectRight
+ (Provers.prepareTypedProverTask
+ Provers.DirectTask
+ problem)
+
+acceptedResolver :: FilePath -> Declaration.VampireResolver
+acceptedResolver executable =
+ Declaration.vampireResolver (resolveAccepted executable)
+
+resolveAccepted
+ :: FilePath
+ -> Provers.PreparedTypedProverTask
+ ref local origin global
+ -> IO
+ (Either
+ Provers.ProverProcessError
+ Provers.ProverAnswer)
+resolveAccepted executable prepared =
+ Provers.runPreparedTypedProver
+ (Provers.vampire
+ executable
+ Provers.defaultTimeLimit
+ Provers.defaultMemoryLimit)
+ prepared
+
+writeAcceptedVampire :: FilePath -> IO ()
+writeAcceptedVampire executable = do
+ writeFile executable
+ (unlines
+ [ "#!/bin/sh"
+ , "cat >/dev/null"
+ , "printf '%s\\n' '% SZS status Theorem for typed'"
+ ])
+ permissions <- Directory.getPermissions executable
+ Directory.setPermissions executable
+ (Directory.setOwnerExecutable True permissions)
+
+validatesExactKernelConstructionDescriptors :: Assertion
+validatesExactKernelConstructionDescriptors = do
+ fixture <- makeFixture
+ proposition <- foundationProposition
+ fixture
+ Foundation.EmptyCharacteristic
+ let declaredObject = opaqueFixtureObject fixture
+ run descriptor =
+ runDriver fixture
+ (Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId
+ "kernel-construction-descriptor") do
+ Declaration.addDeclarationObject declaredObject
+ candidate <- Declaration.reserveCandidate
+ (Declaration.candidateSpec
+ proposition
+ Semantic.SearchEligible
+ [Semantic.semanticName "kernel-construction"])
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeKernelConstructionCandidate
+ descriptor
+ candidate
+ (pure
+ (Kernel.foundationFactDerivation
+ Foundation.EmptyCharacteristic))))
+ success <- run
+ (Authority.FoundationLeaf
+ Foundation.EmptyCharacteristic)
+ case success of
+ Declaration.DriverSucceeded (_value, batch) _interface _prefix _closure -> do
+ assertEqual
+ "new object is included in the checked declaration batch"
+ 1
+ (length (Declaration.committedBatchObjects batch))
+ case Declaration.committedBatchDeclarationValidation batch of
+ Just record ->
+ case Semantic.declarationValidationRecordCertificates
+ record of
+ [certificate] ->
+ assertEqual
+ "exact kernel descriptor is retained"
+ (Authority.CheckedKernelConstruction
+ (Authority.FoundationLeaf
+ Foundation.EmptyCharacteristic))
+ (Authority.validationDirectAuthorization
+ certificate)
+ certificates ->
+ assertFailure
+ ("unexpected kernel certificate count: "
+ <> show (length certificates))
+ Nothing ->
+ assertFailure "missing declaration validation"
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed failure) _prefix ->
+ assertFailure
+ ("valid kernel descriptor failed: " <> show failure)
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed _failure) _prefix ->
+ assertFailure "unexpected ordinary driver failure"
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure (show failure)
+
+ traverse_
+ (\(label, descriptor) -> do
+ outcome <- run descriptor
+ case outcome of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ Declaration.KernelConstructionDescriptorMismatch)
+ prefix ->
+ assertEqual
+ (label <> " publishes no declaration")
+ 0
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed other)
+ _prefix ->
+ assertFailure
+ (label <> ": unexpected error " <> show other)
+ Declaration.DriverFailed
+ (Declaration.DriverActionFailed _failure)
+ _prefix ->
+ assertFailure (label <> ": ordinary driver failure")
+ Declaration.DriverSucceeded{} ->
+ assertFailure (label <> ": mismatch was accepted")
+ Declaration.DriverSealFailed{} ->
+ assertFailure (label <> ": mismatch reached sealing"))
+ [ ( "wrong foundation leaf"
+ , Authority.FoundationLeaf
+ Foundation.PairSetCharacteristic
+ )
+ , ( "wrong construction family"
+ , Authority.GuardedFoundationRules
+ (Authority.guardedRuleSet
+ (Foundation.SetLfpBound :| []))
+ )
+ ]
+
+authorizesExactDatatypeCompilationFamilies :: Assertion
+authorizesExactDatatypeCompilationFamilies = do
+ fixture <- makeFixture
+ firstProposition <- foundationProposition
+ fixture
+ Foundation.EmptyCharacteristic
+ secondProposition <- foundationProposition
+ fixture
+ Foundation.PairSetCharacteristic
+ let carrier = datatypeFixtureObject fixture 0
+ constructor = datatypeFixtureObject fixture 1
+ carrierId = Identity.assertedObjectId carrier
+ constructorId = Identity.assertedObjectId constructor
+ references =
+ fmap
+ (Identity.theoremRef
+ (Identity.theoryId
+ (fixtureFoundation fixture))
+ . Identity.checkedPropositionId)
+ [firstProposition, secondProposition]
+ descriptor =
+ Authority.datatypeCompilationDescriptor
+ carrierId
+ (constructorId :| [])
+ references
+ action
+ :: Authority.DatatypeCompilationDescriptor
+ -> Declaration.ModuleDriver Text
+ ((), Declaration.CommittedDeclarationBatch)
+ action suppliedDescriptor =
+ Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "datatype-compilation") do
+ traverse_ Declaration.addDeclarationObject
+ [carrier, constructor]
+ candidates <-
+ Declaration.reserveCandidateBatch
+ ( Declaration.candidateSpec
+ firstProposition
+ Semantic.SearchEligible
+ [Semantic.semanticName "datatype-first"]
+ :| [ Declaration.candidateSpec
+ secondProposition
+ Semantic.SearchEligible
+ [Semantic.semanticName "datatype-second"]
+ ]
+ )
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeDatatypeCompilationCandidates
+ suppliedDescriptor
+ carrierId
+ (constructorId :| [])
+ candidates)
+
+ (_value, batch) <- runSuccessful fixture (action descriptor)
+ assertEqual "complete object family was published"
+ [carrier, constructor]
+ (Declaration.committedBatchObjects batch)
+ case Declaration.committedBatchDeclarationValidation batch of
+ Just record -> do
+ let certificates =
+ Semantic.declarationValidationRecordCertificates record
+ assertEqual "complete fact family was authorized" 2
+ (length certificates)
+ traverse_
+ (\certificate -> do
+ assertEqual "datatype authority is clean"
+ Authority.cleanAuthoritySafety
+ (Authority.factAuthoritySafety
+ (Authority.validationTarget certificate))
+ assertEqual "one descriptor protects every member"
+ (Authority.TrustedCompilation
+ (Authority.DatatypeCompilation descriptor))
+ (Authority.validationDirectAuthorization certificate))
+ certificates
+ Nothing ->
+ assertFailure "datatype compilation omitted validation"
+
+ let mismatched =
+ Authority.datatypeCompilationDescriptor
+ carrierId
+ (constructorId :| [])
+ (reverse references)
+ rejected <- runDriver fixture (action mismatched)
+ case rejected of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ Declaration.DatatypeCompilationDescriptorMismatch)
+ prefix ->
+ assertEqual "mismatched family publishes no declaration"
+ 0
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("unexpected datatype-family failure: " <> show failure)
+ Declaration.DriverSucceeded{} ->
+ assertFailure "mismatched datatype family was authorized"
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure
+ ("mismatched datatype family reached sealing: "
+ <> show failure)
+
+reusesExactCompiledDeclarationValidation :: Assertion
+reusesExactCompiledDeclarationValidation = do
+ fixture <- makeFixture
+ proposition <- foundationProposition
+ fixture
+ Foundation.EmptyCharacteristic
+ let declaredObject = opaqueFixtureObject fixture
+ syntax =
+ Semantic.declarationSyntaxId
+ "cached-kernel-construction"
+ action derivationTag =
+ Declaration.commitCompiledDeclaration syntax do
+ Declaration.addDeclarationObject declaredObject
+ candidate <- Declaration.reserveCandidate
+ (Declaration.candidateSpec
+ proposition
+ Semantic.SearchEligible
+ [Semantic.semanticName
+ "cached-kernel-construction"])
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeKernelConstructionCandidate
+ (Authority.FoundationLeaf
+ Foundation.EmptyCharacteristic)
+ candidate
+ (pure
+ (Kernel.foundationFactDerivation
+ derivationTag)))
+ freshBatch <- runSuccessful fixture
+ (snd <$> action Foundation.EmptyCharacteristic)
+ freshRecord <-
+ case Declaration.committedBatchDeclarationValidation freshBatch of
+ Just record -> pure record
+ Nothing ->
+ assertFailure "fresh compiled declaration omitted validation"
+ >> fail "unreachable"
+
+ missLookups <- IORef.newIORef (0 :: Int)
+ missBatch <- runSuccessfulWithValidation fixture
+ (compiledOnlyValidationLookup \_key -> do
+ IORef.modifyIORef' missLookups (+ 1)
+ pure Nothing)
+ (snd <$> action Foundation.EmptyCharacteristic)
+ assertEqual "compiled warm miss performs one exact lookup"
+ 1
+ =<< IORef.readIORef missLookups
+ assertBool "compiled miss publishes fresh validation"
+ (isJust
+ (Declaration.committedBatchDeclarationValidation missBatch))
+
+ hitLookups <- IORef.newIORef []
+ hitBatch <- runSuccessfulWithValidation fixture
+ (compiledOnlyValidationLookup \key -> do
+ IORef.modifyIORef' hitLookups (key :)
+ pure (Just freshRecord))
+ (snd <$> action Foundation.PairSetCharacteristic)
+ assertEqual "compiled warm hit performs one exact lookup"
+ [Semantic.declarationValidationRecordKey freshRecord]
+ . reverse
+ =<< IORef.readIORef hitLookups
+ case Declaration.committedBatchDeclarationValidation hitBatch of
+ Just record ->
+ assertEqual
+ "compiled hit republishes the exact validation"
+ freshRecord
+ record
+ Nothing ->
+ assertFailure "compiled hit omitted validation"
+
+foundationProposition
+ :: Fixture
+ -> Foundation.FoundationAxiomTag
+ -> IO Identity.CheckedPropositionContent
+foundationProposition fixture tag = do
+ closure <- expectRight
+ (Identity.validateObjectClosure
+ (Identity.theoryId (fixtureFoundation fixture))
+ [])
+ expectRight
+ (Identity.validatePropositionContent
+ closure
+ (Core.frozenCoreTerm
+ (Core.mapFrozenGlobals
+ absurd
+ (Foundation.foundationAxiomFrozen
+ (fixtureFoundation fixture)
+ tag))))
+
+opaqueFixtureObject :: Fixture -> Identity.AssertedObject
+opaqueFixtureObject fixture =
+ let theory = Identity.theoryId (fixtureFoundation fixture)
+ seed =
+ Identity.opaqueDeclarationSeed
+ (fixtureOwner fixture)
+ (localDeclarationOrdinal 0)
+ SignatureDeclaration
+ (generatedObjectSlot 0)
+ identity =
+ Identity.opaqueObjectId
+ theory
+ seed
+ Core.TySet
+ in Identity.assertedObject
+ identity
+ (Identity.OpaqueObjectContent
+ theory
+ seed
+ Core.TySet)
+
+datatypeFixtureObject
+ :: Fixture
+ -> Natural
+ -> Identity.AssertedObject
+datatypeFixtureObject fixture slot =
+ let theory = Identity.theoryId (fixtureFoundation fixture)
+ seed =
+ Identity.opaqueDeclarationSeed
+ (fixtureOwner fixture)
+ (localDeclarationOrdinal 0)
+ DatatypeDeclaration
+ (generatedObjectSlot slot)
+ identity =
+ Identity.opaqueObjectId theory seed Core.TySet
+ in Identity.assertedObject
+ identity
+ (Identity.OpaqueObjectContent theory seed Core.TySet)
+
+
+data Fixture = Fixture
+ { fixtureFoundation :: !Foundation.CheckedFoundation
+ , fixtureOwner :: !ModuleName
+ , fixtureProposition :: !Identity.CheckedPropositionContent
+ }
+
+makeFixture :: IO Fixture
+makeFixture =
+ makeNamedFixture "root"
+
+makeNamedFixture :: Text -> IO Fixture
+makeNamedFixture name = do
+ foundation <- expectRight Foundation.checkedFoundation
+ namespaceDigest <- expectRight
+ (hashCanonicalFields
+ "declaration-test-namespace"
+ [TextEncoding.encodeUtf8 name])
+ relative <- expectRight
+ (safeRelativePath
+ (Text.unpack name <> ".tex"))
+ let theory = Identity.theoryId foundation
+ owner =
+ moduleNameFromParts
+ (sourceNamespaceIdFromDigest namespaceDigest)
+ relative
+ closure <- expectRight
+ (Identity.validateObjectClosure theory [])
+ proposition <- expectRight
+ (Identity.validatePropositionContent closure Core.CFalsum)
+ pure
+ Fixture
+ { fixtureFoundation = foundation
+ , fixtureOwner = owner
+ , fixtureProposition = proposition
+ }
+
+factSpec :: Fixture -> Text -> Declaration.CandidateSpec
+factSpec fixture alias =
+ Declaration.candidateSpec
+ (fixtureProposition fixture)
+ Semantic.SearchEligible
+ [Semantic.semanticName alias]
+
+runDriver
+ :: Fixture
+ -> Declaration.ModuleDriver failure value
+ -> IO (Declaration.DriverResult failure value)
+runDriver fixture =
+ runDriverWithResolver fixture unavailableVampireResolver
+
+runDriverWithResolver
+ :: Fixture
+ -> Declaration.VampireResolver
+ -> Declaration.ModuleDriver failure value
+ -> IO (Declaration.DriverResult failure value)
+runDriverWithResolver fixture resolver action = do
+ result <- Declaration.runModuleDriver
+ (fixtureFoundation fixture)
+ (fixtureOwner fixture)
+ []
+ resolver
+ Declaration.FreshValidation
+ action
+ expectRight result
+
+runDriverWithValidation
+ :: Fixture
+ -> Declaration.ValidationLookup
+ -> Declaration.ModuleDriver failure value
+ -> IO (Declaration.DriverResult failure value)
+runDriverWithValidation fixture lookup action = do
+ runDriverWithValidationAndResolver
+ fixture
+ lookup
+ unavailableVampireResolver
+ action
+
+runDriverWithValidationAndResolver
+ :: Fixture
+ -> Declaration.ValidationLookup
+ -> Declaration.VampireResolver
+ -> Declaration.ModuleDriver failure value
+ -> IO (Declaration.DriverResult failure value)
+runDriverWithValidationAndResolver fixture lookup resolver action = do
+ result <- Declaration.runModuleDriver
+ (fixtureFoundation fixture)
+ (fixtureOwner fixture)
+ []
+ resolver
+ (Declaration.WarmValidation lookup)
+ action
+ expectRight result
+
+proofOnlyValidationLookup
+ :: (Semantic.ProofValidationKey
+ -> IO (Maybe Semantic.ProofValidationRecord))
+ -> Declaration.ValidationLookup
+proofOnlyValidationLookup lookupProof =
+ Declaration.validationLookup
+ lookupProof
+ (const (pure Nothing))
+
+compiledOnlyValidationLookup
+ :: (Semantic.DeclarationValidationKey
+ -> IO (Maybe Semantic.DeclarationValidationRecord))
+ -> Declaration.ValidationLookup
+compiledOnlyValidationLookup lookupDeclaration =
+ Declaration.validationLookup
+ (const (pure Nothing))
+ lookupDeclaration
+
+runDriverWithDirect
+ :: Fixture
+ -> [Semantic.SemanticInterfaceId]
+ -> Declaration.ModuleDriver failure value
+ -> IO (Declaration.DriverResult failure value)
+runDriverWithDirect fixture direct action = do
+ result <- Declaration.runModuleDriver
+ (fixtureFoundation fixture)
+ (fixtureOwner fixture)
+ direct
+ unavailableVampireResolver
+ Declaration.FreshValidation
+ action
+ expectRight result
+
+unavailableVampireResolver :: Declaration.VampireResolver
+unavailableVampireResolver =
+ Declaration.vampireResolver \_prepared ->
+ pure
+ (Left
+ (Provers.ProverLaunchFailed
+ "unused"
+ "Vampire resolver was not expected"))
+
+runSuccessful
+ :: Fixture
+ -> Declaration.ModuleDriver failure value
+ -> IO value
+runSuccessful fixture =
+ runSuccessfulWithResolver fixture unavailableVampireResolver
+
+runSuccessfulWithResolver
+ :: Fixture
+ -> Declaration.VampireResolver
+ -> Declaration.ModuleDriver failure value
+ -> IO value
+runSuccessfulWithResolver fixture resolver action = do
+ outcome <- runDriverWithResolver fixture resolver action
+ case outcome of
+ Declaration.DriverSucceeded value _interface _prefix _closure ->
+ pure value
+ Declaration.DriverFailed _failure _prefix ->
+ assertFailure "unexpected driver failure" >> fail "unreachable"
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure (show failure) >> fail "unreachable"
+
+runSuccessfulWithValidation
+ :: Fixture
+ -> Declaration.ValidationLookup
+ -> Declaration.ModuleDriver failure value
+ -> IO value
+runSuccessfulWithValidation fixture lookup action = do
+ outcome <- runDriverWithValidation fixture lookup action
+ case outcome of
+ Declaration.DriverSucceeded value _interface _prefix _closure ->
+ pure value
+ Declaration.DriverFailed _failure _prefix ->
+ assertFailure "unexpected driver failure" >> fail "unreachable"
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure (show failure) >> fail "unreachable"
+
+materializesSealedImport :: Assertion
+materializesSealedImport = do
+ fixture <- makeFixture
+ producer <- runDriver fixture do
+ (_value, batch) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "sealed-import-producer") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "producer-fact")
+ Declaration.authorizeOmittedCandidate candidate
+ Declaration.recordOmittedUse
+ pure batch
+ (producerInterface, evidence, fingerprint) <-
+ case producer of
+ Declaration.DriverSucceeded _ interface prefix _closure ->
+ let imported =
+ Declaration.freshImportedModuleEvidence
+ [] interface prefix
+ in case concatMap
+ Semantic.declarationDeltaFacts
+ (Semantic.semanticInterfaceDeclarations interface) of
+ [occurrence] ->
+ pure
+ ( interface
+ , imported
+ , Semantic.semanticFactFingerprint occurrence
+ )
+ occurrences ->
+ assertFailure
+ ("unexpected producer facts: "
+ <> show (length occurrences))
+ >> fail "unreachable"
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("producer failed: "
+ <> show
+ (failure
+ :: Declaration.DriverFailure
+ Declaration.DeclarationError))
+ >> fail "unreachable"
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure ("producer did not seal: " <> show failure)
+ >> fail "unreachable"
+ consumerNamespace <- expectRight
+ (hashCanonicalFields
+ "declaration-import-consumer"
+ ["consumer"])
+ consumerPath <- expectRight (safeRelativePath "consumer.tex")
+ let consumerFixture =
+ fixture
+ { fixtureOwner =
+ moduleNameFromParts
+ (sourceNamespaceIdFromDigest consumerNamespace)
+ consumerPath
+ }
+ consumer <- runDriverWithDirect consumerFixture
+ [Semantic.semanticInterfaceAssertedId producerInterface]
+ do
+ (_value, committed) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "sealed-import-consumer") do
+ Declaration.importSealedModule evidence
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "consumer-fact")
+ Declaration.authorizeOmittedCandidate candidate do
+ _ <- Declaration.useAuthorizedFact fingerprint
+ Declaration.recordOmittedUse
+ pure committed
+ case consumer of
+ Declaration.DriverSucceeded committed _ _ _ -> do
+ case Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta committed) of
+ [localOccurrence] -> do
+ assertEqual
+ "the first local fact keeps ordinal zero"
+ (localFactOrdinal 0)
+ (Semantic.factSlotOrdinal
+ (Semantic.semanticFactSlot localOccurrence))
+ assertEqual
+ "the local fact belongs to the consumer"
+ (fixtureOwner consumerFixture)
+ (Semantic.factSlotModule
+ (Semantic.semanticFactSlot localOccurrence))
+ facts ->
+ assertFailure
+ ("unexpected consumer fact count: "
+ <> show (length facts))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("consumer failed: "
+ <> show
+ (failure
+ :: Declaration.DriverFailure
+ Declaration.DeclarationError))
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure ("consumer did not seal: " <> show failure)
+
+elaboratesScopedExactPropositions :: Assertion
+elaboratesScopedExactPropositions = do
+ fixture <- makeNamedFixture "exact-scoped-proposition"
+ let x = Raw.NamedVar "x"
+ y = Raw.NamedVar "y"
+ statement =
+ Raw.SymbolicQuantified
+ Nowhere
+ Raw.Universally
+ (x :| [y])
+ Raw.Unbounded
+ Nothing
+ (Raw.StmtFormula
+ (Raw.FormulaChain
+ (Raw.ChainBase
+ (Raw.ExprVar x :| [])
+ Raw.Positive
+ (Raw.Relation
+ Nowhere
+ Raw.EqSymbol
+ [])
+ (Raw.ExprVar y :| []))))
+ action
+ :: Declaration.ModuleDriver Text
+ (Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition)
+ action =
+ Declaration.runProspectiveLoweringDriver
+ (Exact.prepareExactProposition
+ Exact.emptyExactBinderContext
+ statement)
+ outcome <- runDriver fixture action
+ case outcome of
+ Declaration.DriverSucceeded (Right prepared) _interface _prefix _closure ->
+ assertEqual
+ "source-order universal binders"
+ (Core.CForall Core.TySet
+ (Core.CForall Core.TySet
+ (Core.CEq Core.TySet
+ (Core.CBound 1)
+ (Core.CBound 0))))
+ (Core.scopedCoreTerm
+ (Exact.preparedExactPropositionCore prepared))
+ Declaration.DriverSucceeded (Left failure) _interface _prefix _closure ->
+ assertFailure
+ ("scoped exact elaboration failed: "
+ <> Text.unpack (Exact.renderExactCompileError failure))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure ("scoped exact driver failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure ("scoped exact driver did not seal: " <> show failure)
+
+lowersFixedEqualityAliases :: Assertion
+lowersFixedEqualityAliases = do
+ fixture <- makeNamedFixture "fixed-equality-aliases"
+ let x = Raw.NamedVar "x"
+ y = Raw.NamedVar "y"
+ z = Raw.NamedVar "z"
+ term variable = Raw.TermExpr (Raw.ExprVar variable)
+ equality left right =
+ Raw.StmtFormula
+ (Raw.FormulaChain
+ (Raw.ChainBase
+ (Raw.ExprVar left :| [])
+ Raw.Positive
+ (Raw.Relation Nowhere Raw.EqSymbol [])
+ (Raw.ExprVar right :| [])))
+ quantified variables statement =
+ Raw.SymbolicQuantified
+ Nowhere
+ Raw.Universally
+ variables
+ Raw.Unbounded
+ Nothing
+ statement
+ adjective =
+ Raw.Adj
+ Nowhere
+ Lexicon.builtinEqualityRightAdjective
+ [term y]
+ copular =
+ Raw.StmtVerbPhrase
+ (term x :| [])
+ (Raw.VPAdj (adjective :| []))
+ rightAttribute =
+ Raw.StmtNoun
+ (term x :| [])
+ (Raw.NounPhrase
+ []
+ (Raw.Noun Nowhere Lexicon.builtinSetNoun [])
+ Nothing
+ [ Raw.AdjR
+ Nowhere
+ Lexicon.builtinEqualityRightAdjective
+ [term y]
+ ]
+ Nothing)
+ rightAttributeExpected =
+ Raw.StmtNoun
+ (term x :| [])
+ (Raw.NounPhrase
+ []
+ (Raw.Noun Nowhere Lexicon.builtinSetNoun [])
+ Nothing
+ []
+ (Just (equality x y)))
+ verb argument =
+ Raw.Verb
+ Nowhere
+ Lexicon.builtinEqualityVerb
+ [term argument]
+ singular =
+ Raw.StmtVerbPhrase
+ (term x :| [])
+ (Raw.VPVerb (verb y))
+ negated =
+ Raw.StmtVerbPhrase
+ (term x :| [])
+ (Raw.VPVerbNot (verb y))
+ coordinated =
+ Raw.StmtVerbPhrase
+ (term x :| [term y])
+ (Raw.VPVerb (verb z))
+ coordinatedExpected =
+ Raw.StmtConnected
+ Raw.Conjunction
+ Nothing
+ (equality x z)
+ (equality y z)
+ comparisons =
+ [ ( "copular adjective"
+ , quantified (x :| [y]) copular
+ , quantified (x :| [y]) (equality x y)
+ )
+ , ( "right adjective"
+ , quantified (x :| [y]) rightAttribute
+ , quantified (x :| [y]) rightAttributeExpected
+ )
+ , ( "singular verb"
+ , quantified (x :| [y]) singular
+ , quantified (x :| [y]) (equality x y)
+ )
+ , ( "negated verb"
+ , quantified (x :| [y]) negated
+ , quantified
+ (x :| [y])
+ (Raw.StmtNeg Nowhere (equality x y))
+ )
+ , ( "quantified coordinated verb"
+ , quantified (x :| [y, z]) coordinated
+ , quantified (x :| [y, z]) coordinatedExpected
+ )
+ ]
+ action
+ :: Declaration.ModuleDriver Text
+ [ ( Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ , Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ )
+ ]
+ action =
+ Declaration.runProspectiveLoweringDriver
+ (traverse
+ (\(_label, alias, symbolic) ->
+ (,)
+ <$> Exact.prepareExactProposition
+ Exact.emptyExactBinderContext alias
+ <*> Exact.prepareExactProposition
+ Exact.emptyExactBinderContext symbolic)
+ comparisons)
+ runDriver fixture action >>= \case
+ Declaration.DriverSucceeded results _interface _prefix _closure ->
+ for_ (zip comparisons results) \((label, _alias, _symbolic), result) ->
+ case result of
+ (Right alias, Right symbolic) -> do
+ let aliasTerm =
+ Core.scopedCoreTerm
+ (Exact.preparedExactPropositionCore alias)
+ symbolicTerm =
+ Core.scopedCoreTerm
+ (Exact.preparedExactPropositionCore symbolic)
+ assertEqual
+ (label <> " checked core")
+ symbolicTerm
+ aliasTerm
+ assertEqual
+ (label <> " global support")
+ Set.empty
+ (Core.canonicalTermGlobals aliasTerm)
+ assertEqual
+ (label <> " foundation support")
+ Set.empty
+ (Foundation.foundationAxiomDependencies aliasTerm)
+ (Left failure, _) ->
+ assertFailure
+ (label <> " alias failed: "
+ <> Text.unpack
+ (Exact.renderExactCompileError failure))
+ (_, Left failure) ->
+ assertFailure
+ (label <> " symbolic comparison failed: "
+ <> Text.unpack
+ (Exact.renderExactCompileError failure))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure ("fixed equality driver failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure ("fixed equality driver did not seal: " <> show failure)
+
+ let internalEquality =
+ Internal.FormulaVerb
+ Nowhere
+ (Internal.EmptySet Nowhere)
+ Lexicon.builtinEqualityVerb
+ [Internal.EmptySet Nowhere]
+ internalResult
+ :: Either
+ Typed.TypedInductiveError
+ (Core.FrozenCheckedCore Void)
+ internalResult =
+ Typed.prepareTypedClosedFormula
+ absurd
+ (const Nothing)
+ internalEquality
+ case internalResult of
+ Right checked -> do
+ assertEqual
+ "internal fixed verb core"
+ (Core.CEq
+ Core.TySet
+ (Core.CIntrinsic Core.Empty)
+ (Core.CIntrinsic Core.Empty))
+ (Core.frozenCoreTerm checked)
+ assertEqual
+ "internal fixed verb global support"
+ Set.empty
+ (Core.frozenCoreGlobals checked)
+ Left failure ->
+ assertFailure
+ ("internal fixed verb failed: " <> show failure)
+
+scopesQuantifiedPropositionTerms :: Assertion
+scopesQuantifiedPropositionTerms = do
+ fixture <- makeNamedFixture "quantified-proposition-terms"
+ let x = Raw.NamedVar "x"
+ y = Raw.NamedVar "y"
+ term variable = Raw.TermExpr (Raw.ExprVar variable)
+ zero = Raw.TermExpr (Raw.ExprInteger Nowhere 0)
+ setNoun = Raw.Noun Nowhere Lexicon.builtinSetNoun []
+ setPhrase named = Raw.NounPhrase [] setNoun named [] Nothing
+ quantified quantifier variable =
+ Raw.TermQuantified
+ quantifier Nowhere (setPhrase (Just variable))
+ equalityVerb argument =
+ Raw.Verb Nowhere Lexicon.builtinEqualityVerb [argument]
+ equalityAdjective argument =
+ Raw.Adj
+ Nowhere Lexicon.builtinEqualityRightAdjective [argument]
+ equality left right = Core.CEq Core.TySet left right
+ notP proposition = Core.CImp proposition Core.CFalsum
+ andP left right = notP (Core.CImp left (notP right))
+ existsP body = notP (Core.CForall Core.TySet (notP body))
+ truth = Core.CImp Core.CFalsum Core.CFalsum
+ member left right =
+ Core.CApp
+ (Core.CApp (Core.CIntrinsic Core.Member) left)
+ right
+ soleSubject =
+ Raw.StmtNoun
+ (quantified Raw.Universally x :| [])
+ (setPhrase Nothing)
+ explicitSubject =
+ Raw.SymbolicQuantified
+ Nowhere Raw.Universally (x :| []) Raw.Unbounded Nothing
+ (Raw.StmtNoun (term x :| []) (setPhrase Nothing))
+ multipleSubjects =
+ Raw.StmtVerbPhrase
+ ( quantified Raw.Universally x
+ :| [quantified Raw.Existentially y]
+ )
+ (Raw.VPVerb (equalityVerb zero))
+ adjectiveArgument =
+ Raw.StmtVerbPhrase
+ (zero :| [])
+ (Raw.VPAdj
+ (equalityAdjective
+ (quantified Raw.Universally x) :| []))
+ nounArgument =
+ Raw.StmtNoun
+ (zero :| [])
+ (Raw.NounPhrase
+ []
+ (Raw.Noun
+ Nowhere Lexicon.builtinElementNoun
+ [quantified Raw.Universally x])
+ Nothing [] Nothing)
+ negatedSubject =
+ Raw.StmtVerbPhrase
+ (quantified Raw.Universally x :| [])
+ (Raw.VPVerbNot (equalityVerb zero))
+ negatedArgument =
+ Raw.StmtVerbPhrase
+ (zero :| [])
+ (Raw.VPVerbNot
+ (equalityVerb (quantified Raw.Universally x)))
+ nonexistentialArgument =
+ Raw.StmtVerbPhrase
+ (zero :| [])
+ (Raw.VPVerb
+ (equalityVerb (quantified Raw.Nonexistentially x)))
+ negatedStatement =
+ Raw.StmtNeg Nowhere soleSubject
+ siblingConstraints =
+ Raw.StmtNoun
+ (zero :| [])
+ (Raw.NounPhrase
+ []
+ (Raw.Noun
+ Nowhere Lexicon.builtinElementNoun
+ [quantified Raw.Universally x])
+ Nothing
+ [Raw.AdjR
+ Nowhere Lexicon.builtinEqualityRightAdjective
+ [quantified Raw.Universally y]]
+ Nothing)
+ constrainedSubject =
+ Raw.TermQuantified Raw.Universally Nowhere
+ (Raw.NounPhrase
+ []
+ (Raw.Noun
+ Nowhere Lexicon.builtinElementNoun [term x])
+ (Just x)
+ [Raw.AdjR
+ Nowhere Lexicon.builtinEqualityRightAdjective [term x]]
+ (Just
+ (Raw.StmtVerbPhrase
+ (term x :| [])
+ (Raw.VPVerb (equalityVerb (term x))))))
+ constrainedStatement =
+ Raw.StmtVerbPhrase
+ (constrainedSubject :| [])
+ (Raw.VPVerb (equalityVerb (term x)))
+ xEqualsX = equality (Core.CBound 0) (Core.CBound 0)
+ cases =
+ [ ( "sole quantified subject"
+ , soleSubject
+ , Core.CForall Core.TySet truth
+ )
+ , ( "explicit sole quantified subject"
+ , explicitSubject
+ , Core.CForall Core.TySet truth
+ )
+ , ( "multiple quantified subjects"
+ , multipleSubjects
+ , Core.CForall Core.TySet
+ (existsP
+ (andP
+ (equality
+ (Core.CBound 1) (Core.COpaqueInteger 0))
+ (equality
+ (Core.CBound 0) (Core.COpaqueInteger 0))))
+ )
+ , ( "quantified adjective argument"
+ , adjectiveArgument
+ , Core.CForall Core.TySet
+ (equality (Core.COpaqueInteger 0) (Core.CBound 0))
+ )
+ , ( "quantified noun argument"
+ , nounArgument
+ , Core.CForall Core.TySet
+ (member (Core.COpaqueInteger 0) (Core.CBound 0))
+ )
+ , ( "quantified subject outside negation"
+ , negatedSubject
+ , Core.CForall Core.TySet
+ (notP
+ (equality
+ (Core.CBound 0) (Core.COpaqueInteger 0)))
+ )
+ , ( "quantified argument inside negation"
+ , negatedArgument
+ , notP
+ (Core.CForall Core.TySet
+ (equality
+ (Core.COpaqueInteger 0) (Core.CBound 0)))
+ )
+ , ( "nonexistential quantified verb argument"
+ , nonexistentialArgument
+ , notP
+ (existsP
+ (equality
+ (Core.COpaqueInteger 0)
+ (Core.CBound 0)))
+ )
+ , ( "statement recursion bounds a quantified subject"
+ , negatedStatement
+ , notP (Core.CForall Core.TySet truth)
+ )
+ , ( "sibling constraints own their argument quantifiers"
+ , siblingConstraints
+ , andP
+ (Core.CForall Core.TySet
+ (member
+ (Core.COpaqueInteger 0)
+ (Core.CBound 0)))
+ (Core.CForall Core.TySet
+ (equality
+ (Core.COpaqueInteger 0)
+ (Core.CBound 0)))
+ )
+ , ( "quantified noun constraints share their binder"
+ , constrainedStatement
+ , Core.CForall Core.TySet
+ (Core.CImp
+ (andP
+ (member (Core.CBound 0) (Core.CBound 0))
+ (andP xEqualsX xEqualsX))
+ xEqualsX)
+ )
+ ]
+ prepare context statement =
+ Exact.prepareExactProposition context statement
+ activeContext <- expectRight
+ (Exact.extendExactBinderContext
+ ((Exact.exactLocalId 0, x) :| [])
+ Exact.emptyExactBinderContext)
+ let action
+ :: Declaration.ModuleDriver Text
+ ( [ Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ ]
+ , Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ )
+ action =
+ Declaration.runProspectiveLoweringDriver do
+ compiled <- traverse
+ (\(_label, statement, _expected) ->
+ prepare Exact.emptyExactBinderContext statement)
+ cases
+ collision <- prepare activeContext soleSubject
+ pure (compiled, collision)
+ runDriver fixture action >>= \case
+ Declaration.DriverSucceeded
+ (compiled, collision) _interface _prefix _closure -> do
+ for_ (zip cases compiled) \
+ ((label, _statement, expected), result) ->
+ case result of
+ Right prepared ->
+ assertEqual label expected
+ (Core.scopedCoreTerm
+ (Exact.preparedExactPropositionCore prepared))
+ Left failure ->
+ assertFailure
+ (label <> " failed: "
+ <> Text.unpack
+ (Exact.renderExactCompileError failure))
+ case collision of
+ Left (Exact.ExactDuplicateLocalBinder _location variable) ->
+ assertEqual "quantified binder collision" x variable
+ Left failure ->
+ assertFailure
+ ("unexpected quantified-binder collision: "
+ <> Text.unpack
+ (Exact.renderExactCompileError failure))
+ Right{} ->
+ assertFailure "an active quantified binder was shadowed"
+ case compiled of
+ Right sole : Right explicit : _ ->
+ assertEqual
+ "sole-subject lowering remains byte-for-byte identical"
+ (Exact.preparedExactPropositionCore sole)
+ (Exact.preparedExactPropositionCore explicit)
+ _ ->
+ assertFailure
+ "sole-subject equality comparison did not compile"
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("quantified proposition-term driver failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure
+ ("quantified proposition-term driver did not seal: "
+ <> show failure)
+
+preparesExactClaimEnvelopes :: Assertion
+preparesExactClaimEnvelopes = do
+ fixture <- makeNamedFixture "exact-claim-envelope"
+ let bLocation = mkLocation (FileId 78) 2 11
+ aLocation = mkLocation (FileId 78) 2 15
+ xLocation = mkLocation (FileId 78) 3 9
+ b = Raw.NamedVarAt bLocation "b"
+ a = Raw.NamedVarAt aLocation "a"
+ x = Raw.NamedVarAt xLocation "x"
+ c = Raw.NamedVarAt Nowhere "c"
+ d = Raw.NamedVarAt Nowhere "d"
+ z = Raw.NamedVarAt Nowhere "z"
+ equality left right =
+ Raw.StmtFormula
+ (Raw.FormulaChain
+ (Raw.ChainBase
+ (Raw.ExprVar left :| [])
+ Raw.Positive
+ (Raw.Relation Nowhere Raw.EqSymbol [])
+ (Raw.ExprVar right :| [])))
+ quantified variable body =
+ Raw.SymbolicQuantified
+ (locate variable)
+ Raw.Universally
+ (variable :| [])
+ Raw.Unbounded
+ Nothing
+ body
+ sourceAssumptions = [Raw.AsmSuppose (equality b a)]
+ sourceConclusion = quantified x (equality x b)
+ alphaAssumptions = [Raw.AsmSuppose (equality c d)]
+ alphaConclusion = quantified z (equality z c)
+ action
+ :: Declaration.ModuleDriver Text
+ ( Either
+ Exact.ExactCompileError
+ Exact.PreparedExactClaimEnvelope
+ , Either
+ Exact.ExactCompileError
+ Exact.PreparedExactClaimEnvelope
+ )
+ action =
+ Declaration.runProspectiveLoweringDriver do
+ source <- Exact.prepareExactClaimEnvelope
+ sourceAssumptions sourceConclusion
+ alpha <- Exact.prepareExactClaimEnvelope
+ alphaAssumptions alphaConclusion
+ pure (source, alpha)
+ expected =
+ Core.CForall Core.TySet
+ (Core.CForall Core.TySet
+ (Core.CImp
+ (Core.CEq Core.TySet
+ (Core.CBound 1)
+ (Core.CBound 0))
+ (Core.CForall Core.TySet
+ (Core.CEq Core.TySet
+ (Core.CBound 0)
+ (Core.CBound 2)))))
+ runDriver fixture action >>= \case
+ Declaration.DriverSucceeded
+ (Right source, Right alpha)
+ _interface _prefix _closure -> do
+ let sourceTarget = Exact.preparedExactClaimTarget source
+ alphaTarget = Exact.preparedExactClaimTarget alpha
+ assertEqual "closed claim envelope core"
+ expected
+ (Core.scopedCoreTerm sourceTarget)
+ assertEqual "claim envelope is closed"
+ []
+ (Core.scopedCoreContext sourceTarget)
+ assertEqual "first semantic occurrence binder order"
+ [bLocation, aLocation]
+ (locate <$> Exact.preparedExactClaimVariables source)
+ assertEqual "explicit binders are not generalized"
+ 2
+ (length (Exact.preparedExactClaimVariables source))
+ assertEqual "header antecedent count"
+ 1
+ (Exact.preparedExactClaimAntecedentCount source)
+ assertEqual "alpha-renaming preserves the checked target"
+ sourceTarget alphaTarget
+ assertEqual "alpha-renaming preserves proposition identity"
+ (Identity.propositionIdOf
+ (Core.scopedCoreTerm sourceTarget))
+ (Identity.propositionIdOf
+ (Core.scopedCoreTerm alphaTarget))
+ Declaration.DriverSucceeded result _interface _prefix _closure ->
+ assertFailure
+ ("exact claim envelope preparation failed: "
+ <> case result of
+ (Left failure, _) ->
+ Text.unpack
+ (Exact.renderExactCompileError failure)
+ (_, Left failure) ->
+ Text.unpack
+ (Exact.renderExactCompileError failure))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure ("claim envelope driver failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure
+ ("claim envelope driver did not seal: " <> show failure)
+
+lowersExactSeparationComprehensions :: Assertion
+lowersExactSeparationComprehensions = do
+ fixture <- makeNamedFixture "exact-separation-comprehension"
+ let binderLocation = mkLocation (FileId 73) 2 7
+ ambientLocation = mkLocation (FileId 73) 2 18
+ boundOccurrenceLocation = mkLocation (FileId 73) 3 14
+ x = Raw.NamedVarAt binderLocation "x"
+ a = Raw.NamedVarAt ambientLocation "A"
+ equality left right =
+ Raw.StmtFormula
+ (Raw.FormulaChain
+ (Raw.ChainBase
+ (left :| [])
+ Raw.Positive
+ (Raw.Relation Nowhere Raw.EqSymbol [])
+ (right :| [])))
+ separation bound =
+ Raw.ExprSep
+ binderLocation
+ x
+ bound
+ (equality (Raw.ExprVar x) (Raw.ExprVar a))
+ validStatement =
+ Raw.SymbolicQuantified
+ Nowhere
+ Raw.Universally
+ (a :| [])
+ Raw.Unbounded
+ Nothing
+ (equality
+ (separation (Raw.ExprVar a))
+ (Raw.ExprVar a))
+ boundOccurrence =
+ Raw.NamedVarAt boundOccurrenceLocation "x"
+ invalidStatement =
+ equality
+ (separation (Raw.ExprVar boundOccurrence))
+ (Raw.ExprVar a)
+ action
+ :: Declaration.ModuleDriver Text
+ ( Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ , Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ )
+ action =
+ Declaration.runProspectiveLoweringDriver do
+ valid <- Exact.prepareExactProposition
+ Exact.emptyExactBinderContext
+ validStatement
+ invalid <- Exact.prepareExactProposition
+ Exact.emptyExactBinderContext
+ invalidStatement
+ pure (valid, invalid)
+ outcome <- runDriver fixture action
+ case outcome of
+ Declaration.DriverSucceeded
+ (Right prepared, Left failure) _interface _prefix _closure -> do
+ assertEqual
+ "separation comprehension core"
+ (Core.CForall Core.TySet
+ (Core.CEq Core.TySet
+ (Core.CApp
+ (Core.CApp
+ (Core.CIntrinsic Core.Sep)
+ (Core.CBound 0))
+ (Core.CLam Core.TySet
+ (Core.CEq Core.TySet
+ (Core.CBound 0)
+ (Core.CBound 1))))
+ (Core.CBound 0)))
+ (Core.scopedCoreTerm
+ (Exact.preparedExactPropositionCore prepared))
+ assertEqual
+ "separation proposition type"
+ Core.TyProp
+ (Core.scopedCoreType
+ (Exact.preparedExactPropositionCore prepared))
+ assertEqual
+ "the separation binder is unavailable in its bound"
+ (Exact.ExactFreeVariable
+ boundOccurrenceLocation
+ boundOccurrence)
+ failure
+ Declaration.DriverSucceeded result _interface _prefix _closure ->
+ case result of
+ (Left validFailure, _) ->
+ assertFailure
+ ("valid separation failed: "
+ <> Text.unpack
+ (Exact.renderExactCompileError validFailure))
+ (_, Right{}) ->
+ assertFailure "invalid separation was accepted"
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure ("separation exact driver failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure ("separation exact driver did not seal: " <> show failure)
+
+lowersExactReplacementTelescopes :: Assertion
+lowersExactReplacementTelescopes = do
+ fixture <- makeNamedFixture "exact-replacement-telescope"
+ let location = mkLocation (FileId 74) 2 1
+ futureOccurrenceLocation = mkLocation (FileId 74) 7 19
+ a = Raw.NamedVarAt location "A"
+ x = Raw.NamedVarAt location "x"
+ y = Raw.NamedVarAt location "y"
+ futureY = Raw.NamedVarAt futureOccurrenceLocation "y"
+ equality left right =
+ Raw.StmtFormula
+ (Raw.FormulaChain
+ (Raw.ChainBase
+ (left :| [])
+ Raw.Positive
+ (Raw.Relation Nowhere Raw.EqSymbol [])
+ (right :| [])))
+ replacement firstDomain =
+ Raw.ExprReplace
+ location
+ (Raw.ExprVar y)
+ ( (x, firstDomain) :|
+ [(y, Raw.ExprVar x)]
+ )
+ (Just (equality (Raw.ExprVar x) (Raw.ExprVar y)))
+ validStatement =
+ Raw.SymbolicQuantified
+ Nowhere
+ Raw.Universally
+ (a :| [])
+ Raw.Unbounded
+ Nothing
+ (equality
+ (replacement (Raw.ExprVar a))
+ (Raw.ExprVar a))
+ invalidStatement =
+ equality
+ (replacement (Raw.ExprVar futureY))
+ (Raw.ExprInteger Nowhere 0)
+ predicateReplacementLocation = mkLocation (FileId 74) 9 3
+ predicateReplacementStatement =
+ equality
+ (Raw.ExprReplacePred
+ predicateReplacementLocation
+ y
+ x
+ (Raw.ExprInteger Nowhere 0)
+ (equality (Raw.ExprVar x) (Raw.ExprVar y)))
+ (Raw.ExprInteger Nowhere 0)
+ namedPredicateReplacement =
+ Raw.ExprReplacePred
+ predicateReplacementLocation
+ y
+ x
+ (Raw.ExprVar a)
+ (equality (Raw.ExprVar x) (Raw.ExprVar y))
+ app1 intrinsic argument =
+ Core.CApp (Core.CIntrinsic intrinsic) argument
+ app2 intrinsic first second =
+ Core.CApp (app1 intrinsic first) second
+ expected =
+ Core.CForall Core.TySet $
+ Core.CEq Core.TySet
+ (app1 Core.FamilyUnion $
+ app2 Core.Repl (Core.CBound 0) $
+ Core.CLam Core.TySet $
+ app2 Core.Repl
+ (app2 Core.Sep
+ (Core.CBound 0)
+ (Core.CLam Core.TySet $
+ Core.CEq Core.TySet
+ (Core.CBound 1)
+ (Core.CBound 0)))
+ (Core.CLam Core.TySet
+ (Core.CBound 0)))
+ (Core.CBound 0)
+ action
+ :: Declaration.ModuleDriver Text
+ ( Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ , Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ , Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition
+ , Either
+ Exact.ExactCompileError
+ Exact.PreparedExactSetExpression
+ )
+ action =
+ Declaration.runProspectiveLoweringDriver do
+ valid <- Exact.prepareExactProposition
+ Exact.emptyExactBinderContext
+ validStatement
+ invalid <- Exact.prepareExactProposition
+ Exact.emptyExactBinderContext
+ invalidStatement
+ predicateReplacement <- Exact.prepareExactProposition
+ Exact.emptyExactBinderContext
+ predicateReplacementStatement
+ namedContext <-
+ either
+ (impossible
+ . Text.unpack
+ . Exact.renderExactCompileError)
+ pure
+ (Exact.extendExactBinderContext
+ ((Exact.exactLocalId 0, a) :| [])
+ Exact.emptyExactBinderContext)
+ named <- Exact.prepareExactSetExpression
+ namedContext namedPredicateReplacement
+ pure (valid, invalid, predicateReplacement, named)
+ runDriver fixture action >>= \case
+ Declaration.DriverSucceeded
+ ( Right prepared
+ , Left failure
+ , Left predicateReplacementFailure
+ , Right named
+ ) _interface _prefix _closure -> do
+ assertEqual
+ "dependent replacement core"
+ expected
+ (Core.scopedCoreTerm
+ (Exact.preparedExactPropositionCore prepared))
+ assertEqual
+ "future replacement binder location"
+ (Exact.ExactFreeVariable futureOccurrenceLocation futureY)
+ failure
+ assertEqual
+ "predicate replacement remains unsupported at its location"
+ (Exact.ExactRelationalReplacementRequiresNamedDefinition
+ predicateReplacementLocation)
+ predicateReplacementFailure
+ case Exact.preparedExactSetExpressionConstruction named of
+ Just (Exact.PreparedRelationalSetConstruction construction) -> do
+ assertEqual "relational replacement canonical term"
+ expectedRelationalTerm
+ (Core.scopedCoreTerm
+ (SetConstruction.relationalSetConstructionTerm
+ construction))
+ assertEqual "relational replacement functionality"
+ expectedFunctionality
+ (Core.scopedCoreTerm
+ (SetConstruction.relationalSetConstructionFunctionality
+ construction))
+ let relationalObject =
+ Identity.assertedObjectId
+ (opaqueFixtureObject fixture)
+ closedFunctionality =
+ SetConstruction.relationalSetConstructionClosedFunctionality
+ construction
+ relationalFact <-
+ maybe
+ (assertFailure
+ "exact functionality did not unlock relational extensionality"
+ >> fail "unreachable")
+ pure
+ (SetConstruction.relationalSetConstructionObjectFact
+ (SetConstruction.checkedFoundationSetConstruction
+ (fixtureFoundation fixture))
+ relationalObject
+ construction
+ closedFunctionality)
+ assertEqual
+ "relational replacement flattened extensional proposition"
+ (expectedRelationalExtensional relationalObject)
+ (Core.frozenCoreTerm
+ (SetConstruction.relationalSetConstructionFactProposition
+ relationalFact))
+ assertEqual
+ "unrelated functionality cannot unlock the relational view"
+ Nothing
+ (SetConstruction.relationalSetConstructionLocalViews
+ (SetConstruction.checkedFoundationSetConstruction
+ (fixtureFoundation fixture))
+ construction
+ (Core.falsumScopedCore [Core.TySet]))
+ wrongClosed <- expectRight
+ (Core.checkCanonicalCore
+ (const Nothing)
+ Core.CFalsum)
+ assertBool
+ "malformed relational authority is rejected"
+ (isNothing
+ (SetConstruction.relationalSetConstructionObjectFact
+ (SetConstruction.checkedFoundationSetConstruction
+ (fixtureFoundation fixture))
+ relationalObject
+ construction
+ wrongClosed))
+ _ ->
+ assertFailure
+ "named predicate replacement lost its relational construction"
+ Declaration.DriverSucceeded
+ (Left validFailure, _, _, _) _interface _prefix _closure ->
+ assertFailure
+ ("valid replacement failed: "
+ <> Text.unpack
+ (Exact.renderExactCompileError validFailure))
+ Declaration.DriverSucceeded
+ (_, Right{}, _, _) _interface _prefix _closure ->
+ assertFailure "invalid replacement was accepted"
+ Declaration.DriverSucceeded
+ (_, _, Right{}, _) _interface _prefix _closure ->
+ assertFailure "predicate replacement was accepted"
+ Declaration.DriverSucceeded
+ (_, _, _, Left failure) _interface _prefix _closure ->
+ assertFailure
+ ("named predicate replacement failed: "
+ <> Text.unpack (Exact.renderExactCompileError failure))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("replacement driver failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure
+ ("replacement driver did not seal: " <> show failure)
+ where
+ relApp1 intrinsic argument =
+ Core.CApp (Core.CIntrinsic intrinsic) argument
+ relApp2 intrinsic first second =
+ Core.CApp (relApp1 intrinsic first) second
+ notP proposition = Core.CImp proposition Core.CFalsum
+ andP left right = notP (Core.CImp left (notP right))
+ existsP body = notP (Core.CForall Core.TySet (notP body))
+ relation = Core.CEq Core.TySet (Core.CBound 1) (Core.CBound 0)
+ restricted =
+ relApp2 Core.Sep (Core.CBound 0)
+ (Core.CLam Core.TySet (existsP relation))
+ expectedRelationalTerm =
+ relApp2 Core.Repl restricted
+ (Core.CLam Core.TySet
+ (relApp1 Core.SetChoose (Core.CLam Core.TySet relation)))
+ expectedFunctionality =
+ Core.CForall Core.TySet
+ (Core.CImp
+ (relApp2 Core.Member (Core.CBound 0) (Core.CBound 1))
+ (Core.CForall Core.TySet
+ (Core.CForall Core.TySet
+ (Core.CImp
+ (andP
+ (Core.CEq Core.TySet
+ (Core.CBound 2) (Core.CBound 1))
+ (Core.CEq Core.TySet
+ (Core.CBound 2) (Core.CBound 0)))
+ (Core.CEq Core.TySet
+ (Core.CBound 1) (Core.CBound 0))))))
+ expectedRelationalExtensional object =
+ Core.CForall Core.TySet
+ (Core.CForall Core.TySet
+ (Core.CEq Core.TyProp
+ (relApp2 Core.Member
+ (Core.CBound 0)
+ (Core.CApp
+ (Core.CGlobal object)
+ (Core.CBound 1)))
+ (existsP
+ (andP
+ (relApp2 Core.Member
+ (Core.CBound 0)
+ (Core.CBound 2))
+ (Core.CEq Core.TySet
+ (Core.CBound 0)
+ (Core.CBound 1))))))
+
+lowersExactFiniteSets :: Assertion
+lowersExactFiniteSets = do
+ fixture <- makeNamedFixture "exact-finite-set"
+ let location = mkLocation (FileId 75) 2 1
+ a = Raw.NamedVarAt location "a"
+ b = Raw.NamedVarAt location "b"
+ equality left right =
+ Raw.StmtFormula
+ (Raw.FormulaChain
+ (Raw.ChainBase
+ (left :| [])
+ Raw.Positive
+ (Raw.Relation Nowhere Raw.EqSymbol [])
+ (right :| [])))
+ statement =
+ Raw.SymbolicQuantified
+ Nowhere
+ Raw.Universally
+ (a :| [b])
+ Raw.Unbounded
+ Nothing
+ (equality
+ (Raw.ExprFiniteSet
+ location
+ (Raw.ExprVar a :| [Raw.ExprVar b]))
+ (Raw.ExprVar a))
+ app1 intrinsic argument =
+ Core.CApp (Core.CIntrinsic intrinsic) argument
+ app2 intrinsic first second =
+ Core.CApp (app1 intrinsic first) second
+ insert element rest =
+ app1 Core.FamilyUnion
+ (app2 Core.PairSet
+ (app2 Core.PairSet element element)
+ rest)
+ expected =
+ Core.CForall Core.TySet
+ (Core.CForall Core.TySet
+ (Core.CEq Core.TySet
+ (insert
+ (Core.CBound 1)
+ (insert
+ (Core.CBound 0)
+ (Core.CIntrinsic Core.Empty)))
+ (Core.CBound 1)))
+ action
+ :: Declaration.ModuleDriver Text
+ (Either
+ Exact.ExactCompileError
+ Exact.PreparedExactProposition)
+ action =
+ Declaration.runProspectiveLoweringDriver
+ (Exact.prepareExactProposition
+ Exact.emptyExactBinderContext
+ statement)
+ internal <-
+ expectRight
+ (evalState
+ (runExceptT (Meaning.glossStmt statement))
+ Meaning.initialGlossState)
+ reusable <-
+ expectRight
+ (Typed.prepareTypedClosedFormula
+ absurd
+ (const Nothing)
+ internal
+ :: Either
+ Typed.TypedInductiveError
+ (Core.FrozenCheckedCore Void))
+ assertEqual
+ "raw and reusable finite-set lowering"
+ expected
+ (Core.frozenCoreTerm reusable)
+ let internalSymbols = Internal.mentionedSymbols internal
+ assertBool
+ "finite-set meaning has no source-owned cons dependency"
+ (Internal.SymbolMixfix Raw.ConsSymbol
+ `Set.notMember` internalSymbols)
+ assertBool
+ "finite-set meaning retains fixed adjunction operations"
+ ( Set.fromList
+ [ Internal.SymbolMixfix Raw.UnionsSymbol
+ , Internal.SymbolMixfix Raw.UpairSymbol
+ ]
+ `Set.isSubsetOf` internalSymbols
+ )
+ case Vocabulary.classifyExactSymbol
+ (Internal.SymbolMixfix Raw.ConsSymbol) of
+ Vocabulary.ExactSourceGlobal{} -> pure ()
+ classification ->
+ assertFailure
+ ("explicit cons did not retain source ownership: "
+ <> show classification)
+ runDriver fixture action >>= \case
+ Declaration.DriverSucceeded
+ (Right prepared) _interface _prefix _closure ->
+ assertEqual
+ "source-order finite-set core"
+ expected
+ (Core.scopedCoreTerm
+ (Exact.preparedExactPropositionCore prepared))
+ Declaration.DriverSucceeded
+ (Left failure) _interface _prefix _closure ->
+ assertFailure
+ ("valid finite set failed: "
+ <> Text.unpack
+ (Exact.renderExactCompileError failure))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("finite-set driver failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure
+ ("finite-set driver did not seal: " <> show failure)
+
+lowersExactOrdinaryDeclarations :: Assertion
+lowersExactOrdinaryDeclarations = do
+ fixture <- makeNamedFixture "exact-lowering"
+ level <- expectRight (Syntax.mixfixLevel 2)
+ let makeSymbol command marker =
+ Raw.mkMixfixItem
+ [ Just (Raw.Command command)
+ , Just Raw.InvisibleBraceL
+ , Nothing
+ , Just Raw.InvisibleBraceR
+ ]
+ (Raw.Marker marker)
+ Raw.NonAssoc
+ opaqueSymbol = makeSymbol "phasefiveopaque" "opaque-label"
+ aliasSymbol = makeSymbol "phasefivealias" "alias-label"
+ definitionSymbol = makeSymbol "phasefivedef" "definition-label"
+ entry symbol =
+ Syntax.CanonicalExpressionFunction
+ (Raw.mixfixPattern symbol)
+ (Raw.mixfixMarker symbol)
+ (Syntax.Fixity Raw.NonAssoc level)
+ parameter = Raw.NamedVar "x"
+ exactSet =
+ Raw.NounPhrase
+ []
+ (Raw.Noun Nowhere Lexicon.builtinSetNoun [])
+ Nothing
+ []
+ Nothing
+ signature =
+ Raw.BlockSig
+ Nowhere Nothing (Raw.Marker "opaque-declaration") []
+ (Raw.SignatureSymbolic
+ (Raw.SymbolPattern opaqueSymbol [parameter])
+ exactSet)
+ application symbol =
+ Raw.ExprOp Nowhere symbol [Raw.ExprVar parameter]
+ abbreviation =
+ Raw.BlockAbbr
+ Nowhere Nothing (Raw.Marker "alias-declaration")
+ (Raw.AbbreviationEq
+ (Raw.SymbolPattern aliasSymbol [parameter])
+ (application opaqueSymbol))
+ definition =
+ Raw.BlockDefn
+ Nowhere Nothing (Raw.Marker "definition-declaration")
+ (Raw.DefnOp
+ (Raw.SymbolPattern definitionSymbol [parameter])
+ (application aliasSymbol))
+ compile block lexicalEntry = do
+ Declaration.runProspectiveLoweringDriver
+ (Exact.prepareExactDeclaration block [lexicalEntry]) >>= \case
+ Left failure ->
+ Declaration.failModuleDriver
+ (Exact.renderExactCompileError failure)
+ Right prepared -> pure prepared
+ admit prepared = do
+ lowered <-
+ Declaration.runProspectiveLoweringDriver
+ (Exact.lowerPreparedExactBinding prepared)
+ checked <-
+ either Declaration.failDeclarationDriver pure lowered
+ void
+ (Declaration.admitCheckedDeclaration
+ checked
+ Exact.authorizeCheckedExactBinding)
+ outcome <- runFixtureDriver fixture [] do
+ preparedSignature <-
+ compile signature (entry opaqueSymbol)
+ admit preparedSignature
+ preparedAbbreviation <-
+ compile abbreviation (entry aliasSymbol)
+ admit preparedAbbreviation
+ preparedDefinition <-
+ compile definition (entry definitionSymbol)
+ admit preparedDefinition
+ pure
+ ( preparedSignature
+ , preparedAbbreviation
+ , preparedDefinition
+ )
+ case outcome of
+ Declaration.DriverSucceeded
+ (preparedSignature, preparedAbbreviation, preparedDefinition)
+ interface prefix _closure -> do
+ assertEqual "three committed declarations"
+ 3
+ (length (Semantic.semanticInterfaceDeclarations interface))
+ assertEqual "three committed batches"
+ 3
+ (length (Declaration.pendingModulePrefixBatches prefix))
+ assertEqual "opaque signature family"
+ Identity.OpaqueObject
+ (Identity.objectIdFamily
+ (Exact.preparedExactObjectId preparedSignature))
+ assertEqual "transparent abbreviation family"
+ Identity.TransparentObject
+ (Identity.objectIdFamily
+ (Exact.preparedExactObjectId preparedAbbreviation))
+ assertEqual "transparent definition family"
+ Identity.TransparentObject
+ (Identity.objectIdFamily
+ (Exact.preparedExactObjectId preparedDefinition))
+ assertEqual "expanded definition coalesces with abbreviation"
+ (Exact.preparedExactObjectId preparedAbbreviation)
+ (Exact.preparedExactObjectId preparedDefinition)
+ case Exact.preparedExactObject preparedAbbreviation of
+ Just object ->
+ case Identity.assertedObjectContent object of
+ Identity.TransparentObjectContent
+ _theory coreType body -> do
+ assertEqual "definition type"
+ (Core.TyArrow Core.TySet Core.TySet)
+ coreType
+ assertEqual "expanded body retains opaque seed"
+ (Core.CLam Core.TySet
+ (Core.CApp
+ (Core.CGlobal
+ (Exact.preparedExactObjectId
+ preparedSignature))
+ (Core.CBound 0)))
+ body
+ content ->
+ assertFailure
+ ("unexpected definition content: " <> show content)
+ Nothing ->
+ assertFailure "new abbreviation object was not prepared"
+ assertEqual "coalesced definition adds no object"
+ Nothing
+ (Exact.preparedExactObject preparedDefinition)
+ case reverse (Declaration.pendingModulePrefixBatches prefix) of
+ definitionBatch : _ -> do
+ case Declaration.committedBatchDeclarationValidation
+ definitionBatch of
+ Just record ->
+ case Semantic.declarationValidationRecordCertificates
+ record of
+ [certificate] -> do
+ assertEqual "definition authority"
+ (Authority.CheckedKernelConstruction
+ (Authority.CheckedDefinitionEquation
+ (Exact.preparedExactObjectId
+ preparedDefinition)))
+ (Authority.validationDirectAuthorization
+ certificate)
+ assertEqual "definition authority is clean"
+ Authority.cleanAuthoritySafety
+ (Authority.factAuthoritySafety
+ (Authority.validationTarget
+ certificate))
+ certificates ->
+ assertFailure
+ ("unexpected definition certificate count: "
+ <> show (length certificates))
+ Nothing ->
+ assertFailure "definition has no declaration validation"
+ [] -> assertFailure "definition batch is absent"
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure ("exact lowering failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure ("exact lowering did not seal: " <> show failure)
+
+ let theory = Identity.theoryId (fixtureFoundation fixture)
+ mismatchBody = Core.COpaqueInteger 0
+ mismatchType = Core.TySet
+ mismatchId =
+ Identity.transparentObjectId theory mismatchType mismatchBody
+ mismatchObject =
+ Identity.assertedObject
+ mismatchId
+ (Identity.TransparentObjectContent
+ theory mismatchType mismatchBody)
+ let mismatchAction
+ :: Declaration.ModuleDriver Text
+ ((), Declaration.CommittedDeclarationBatch)
+ mismatchAction =
+ Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId
+ "mismatched-definition-equation") do
+ Declaration.addDeclarationObject mismatchObject
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "not-a-definition-equation")
+ Declaration.authorizeCompiledDeclaration
+ (Declaration.authorizeDefinitionEquationCandidate
+ mismatchId
+ candidate)
+ mismatch <- runDriver fixture mismatchAction
+ case mismatch of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ Declaration.DefinitionEquationCandidateMismatch)
+ prefix ->
+ assertEqual "mismatched equation publishes no batch"
+ 0
+ (length (Declaration.pendingModulePrefixBatches prefix))
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("unexpected mismatched-equation failure: " <> show failure)
+ Declaration.DriverSucceeded{} ->
+ assertFailure "mismatched definition equation was authorized"
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure
+ ("mismatched definition equation reached sealing: "
+ <> show failure)
+
+reconstructsImportedGlobalBindings :: Assertion
+reconstructsImportedGlobalBindings = do
+ producerFixture <- makeNamedFixture "global-producer"
+ consumerFixture <- makeNamedFixture "global-consumer"
+ conflictFixture <- makeNamedFixture "global-conflict"
+ rootFixture <- makeNamedFixture "global-root"
+ let key =
+ Semantic.SemanticExpressionFunction
+ (Raw.TokenCons (Raw.Command "phasefive") Raw.End)
+ asserted = opaqueFixtureObject producerFixture
+ target = Identity.assertedObjectId asserted
+ publishWith targetMode fixture object = do
+ (batch, sealed) <- sealFixture fixture [] do
+ (_value, committed) <-
+ Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "global-binding") do
+ Declaration.addDeclarationObject object
+ Declaration.stageSemanticGlobalBinding
+ key
+ (targetMode
+ (Identity.assertedObjectId object))
+ Declaration.authorizeCompiledDeclaration (pure ())
+ pure committed
+ pure (batch, sealed)
+ (producerBatch, freshProducer) <-
+ publishWith Semantic.GlobalReference producerFixture asserted
+ let FixtureSealed producerInterface _freshEvidence = freshProducer
+ objects = Declaration.committedBatchObjects producerBatch
+ cachedEvidence <- expectRight
+ (Declaration.validateImportedModuleEvidence
+ (Identity.theoryId
+ (fixtureFoundation producerFixture))
+ []
+ producerInterface
+ objects
+ [])
+ let cachedProducer = FixtureSealed producerInterface cachedEvidence
+ resolveThrough label parent = do
+ outcome <- runFixtureDriver consumerFixture [parent] do
+ fst <$> Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId
+ (TextEncoding.encodeUtf8 (Text.pack label))) do
+ found <- Declaration.resolveVisibleGlobal key
+ Declaration.authorizeCompiledDeclaration (pure ())
+ pure found
+ case outcome of
+ Declaration.DriverSucceeded found _interface _prefix _closure ->
+ assertEqual label
+ (Just
+ ( Semantic.GlobalReference target
+ , Core.TySet
+ ))
+ found
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("global binding consumer failed: " <> show failure)
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure
+ ("global binding consumer did not seal: " <> show failure)
+ resolveThrough "fresh-global-binding" freshProducer
+ resolveThrough "cached-global-binding" cachedProducer
+
+ missingEnvironment <- expectRight
+ (Semantic.semanticEnvironmentDelta
+ [Semantic.semanticGlobalBinding
+ key
+ (Semantic.GlobalReference target)])
+ missingDelta <- expectRight
+ (Semantic.declarationInterfaceDelta
+ (Semantic.declarationSlot
+ (fixtureOwner producerFixture)
+ (localDeclarationOrdinal 0))
+ []
+ []
+ []
+ []
+ missingEnvironment)
+ missingInterface <- expectRight
+ (Semantic.semanticInterface
+ (fixtureOwner producerFixture)
+ []
+ [missingDelta])
+ case Declaration.validateImportedModuleEvidence
+ (Identity.theoryId
+ (fixtureFoundation producerFixture))
+ []
+ missingInterface
+ []
+ [] of
+ Left (Declaration.ImportedGlobalTargetInvalid
+ actualKey actualTarget
+ (Semantic.SemanticGlobalTargetMissing missingTarget)) -> do
+ assertEqual "missing target key" key actualKey
+ assertEqual "missing target mode"
+ (Semantic.GlobalReference target)
+ actualTarget
+ assertEqual "missing target object" target missingTarget
+ Left failure ->
+ assertFailure
+ ("unexpected missing-target failure: " <> show failure)
+ Right _evidence ->
+ assertFailure "cached evidence accepted a missing target object"
+
+ expansionEnvironment <- expectRight
+ (Semantic.semanticEnvironmentDelta
+ [Semantic.semanticGlobalBinding
+ key
+ (Semantic.TransparentExpansion target)])
+ expansionDelta <- expectRight
+ (Semantic.declarationInterfaceDelta
+ (Semantic.declarationSlot
+ (fixtureOwner producerFixture)
+ (localDeclarationOrdinal 0))
+ [] [] [target] [] expansionEnvironment)
+ expansionInterface <- expectRight
+ (Semantic.semanticInterface
+ (fixtureOwner producerFixture) [] [expansionDelta])
+ case Declaration.validateImportedModuleEvidence
+ (Identity.theoryId
+ (fixtureFoundation producerFixture))
+ []
+ expansionInterface
+ [asserted]
+ [] of
+ Left (Declaration.ImportedGlobalTargetInvalid
+ actualKey actualTarget
+ (Semantic.SemanticGlobalExpansionNotTransparent
+ invalidTarget)) -> do
+ assertEqual "nontransparent target key" key actualKey
+ assertEqual "nontransparent target mode"
+ (Semantic.TransparentExpansion target)
+ actualTarget
+ assertEqual "nontransparent target object" target invalidTarget
+ Left failure ->
+ assertFailure
+ ("unexpected nontransparent-target failure: "
+ <> show failure)
+ Right _evidence ->
+ assertFailure "cached evidence accepted a nontransparent expansion"
+
+ let intrinsicTarget =
+ Identity.intrinsicObjectId
+ (Identity.theoryId
+ (fixtureFoundation producerFixture))
+ Core.Empty
+ Core.TySet
+ intrinsicObject =
+ Identity.assertedObject
+ intrinsicTarget
+ (Identity.IntrinsicObjectContent
+ (Identity.theoryId
+ (fixtureFoundation producerFixture))
+ Core.Empty
+ Core.TySet)
+ intrinsicFailure <- runFixtureDriver producerFixture [] do
+ Declaration.commitCompiledDeclaration
+ (Semantic.declarationSyntaxId "intrinsic-global-binding") do
+ Declaration.addDeclarationObject intrinsicObject
+ Declaration.stageSemanticGlobalBinding
+ key
+ (Semantic.GlobalReference intrinsicTarget)
+ Declaration.authorizeCompiledDeclaration (pure ())
+ case intrinsicFailure of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.DeclarationGlobalTargetInvalid
+ actualKey actualTarget
+ (Semantic.SemanticGlobalTargetIsIntrinsic
+ invalidTarget)))
+ _prefix -> do
+ assertEqual "intrinsic target key" key actualKey
+ assertEqual "intrinsic target mode"
+ (Semantic.GlobalReference intrinsicTarget)
+ actualTarget
+ assertEqual "intrinsic target object"
+ intrinsicTarget invalidTarget
+ other ->
+ assertFailure
+ (case other of
+ Declaration.DriverSucceeded{} ->
+ "ordinary binding accepted an intrinsic target"
+ Declaration.DriverFailed failure _prefix ->
+ "unexpected intrinsic-target failure: " <> show failure
+ Declaration.DriverSealFailed failure _prefix ->
+ "intrinsic target reached sealing: " <> show failure)
+
+ conflictObject <- pure (opaqueFixtureObject conflictFixture)
+ (_conflictBatch, conflicting) <-
+ publishWith Semantic.GlobalReference conflictFixture conflictObject
+ collision <- runFixtureDriver rootFixture
+ [freshProducer, conflicting]
+ (pure ())
+ case collision of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.ImportedGlobalCollision
+ actualKey firstTarget secondTarget))
+ _prefix -> do
+ assertEqual "colliding global key" key actualKey
+ assertEqual "first imported target"
+ (Semantic.GlobalReference target)
+ firstTarget
+ assertEqual "second imported target"
+ (Semantic.GlobalReference
+ (Identity.assertedObjectId conflictObject))
+ secondTarget
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure
+ ("unexpected imported collision: " <> show failure)
+ Declaration.DriverSucceeded{} ->
+ assertFailure "unequal imported bindings did not collide"
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure
+ ("global collision reached sealing: " <> show failure)
+
+ let theory = Identity.theoryId (fixtureFoundation producerFixture)
+ transparentBody = Core.COpaqueInteger 0
+ transparentTarget =
+ Identity.transparentObjectId
+ theory Core.TySet transparentBody
+ transparentObject =
+ Identity.assertedObject
+ transparentTarget
+ (Identity.TransparentObjectContent
+ theory Core.TySet transparentBody)
+ (_referenceBatch, referenceProducer) <-
+ publishWith
+ Semantic.GlobalReference
+ producerFixture
+ transparentObject
+ (_expansionBatch, expansionProducer) <-
+ publishWith
+ Semantic.TransparentExpansion
+ conflictFixture
+ transparentObject
+ modeCollision <- runFixtureDriver rootFixture
+ [referenceProducer, expansionProducer]
+ (pure ())
+ case modeCollision of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.ImportedGlobalCollision
+ actualKey firstTarget secondTarget))
+ _prefix -> do
+ assertEqual "mode collision key" key actualKey
+ assertEqual "reference target"
+ (Semantic.GlobalReference transparentTarget)
+ firstTarget
+ assertEqual "expansion target"
+ (Semantic.TransparentExpansion transparentTarget)
+ secondTarget
+ other ->
+ assertFailure
+ (case other of
+ Declaration.DriverSucceeded{} ->
+ "different global target modes did not collide"
+ Declaration.DriverFailed failure _prefix ->
+ "unexpected mode-collision failure: " <> show failure
+ Declaration.DriverSealFailed failure _prefix ->
+ "mode collision reached sealing: " <> show failure)
+
+data FixtureSealed = FixtureSealed
+ !Semantic.SemanticInterface
+ !Declaration.ImportedModuleEvidence
+
+foldsTransitiveAndDiamondEvidence :: Assertion
+foldsTransitiveAndDiamondEvidence = do
+ baseFixture <- makeNamedFixture "base"
+ middleFixture <- makeNamedFixture "middle"
+ transitiveFixture <- makeNamedFixture "transitive"
+ leftFixture <- makeNamedFixture "left"
+ rightFixture <- makeNamedFixture "right"
+ diamondFixture <- makeNamedFixture "diamond"
+ conflictLeftFixture <- makeNamedFixture "conflict-left"
+ conflictRightFixture <- makeNamedFixture "conflict-right"
+ conflictRootFixture <- makeNamedFixture "conflict-root"
+
+ (base, baseFingerprint) <-
+ sealFactFixture baseFixture [] "transitive-shared"
+ middle <- snd <$> sealFixture middleFixture [base] (pure ())
+ transitive <- sealUsingImportedFact
+ transitiveFixture [middle] baseFingerprint
+ assertLocalFactOrdinalZero "transitive importer" transitive
+
+ left <- snd <$> sealFixture leftFixture [base] (pure ())
+ right <- snd <$> sealFixture rightFixture [base] (pure ())
+ diamond <- sealUsingImportedFact
+ diamondFixture [left, right] baseFingerprint
+ assertLocalFactOrdinalZero "diamond importer" diamond
+
+ (conflictLeft, leftFingerprint) <-
+ sealFactFixture conflictLeftFixture [] "diamond-conflict"
+ (conflictRight, rightFingerprint) <-
+ sealFactFixture conflictRightFixture [] "diamond-conflict"
+ conflict <- runFixtureDriver
+ conflictRootFixture
+ [conflictLeft, conflictRight]
+ (pure ())
+ case conflict of
+ Declaration.DriverFailed
+ (Declaration.DriverDeclarationFailed
+ (Declaration.ImportedAliasCollision
+ alias
+ (Declaration.ImportedAliasOrigin
+ _leftSlot firstTarget)
+ (Declaration.ImportedAliasOrigin
+ _rightSlot secondTarget)))
+ _prefix -> do
+ assertEqual "conflicting alias"
+ (Semantic.semanticName "diamond-conflict")
+ alias
+ assertEqual "first alias origin"
+ leftFingerprint
+ firstTarget
+ assertEqual "second alias origin"
+ rightFingerprint
+ secondTarget
+ _ ->
+ assertFailure "conflicting diamond alias was not rejected"
+ where
+ sealUsingImportedFact fixture parents fingerprint = do
+ (batch, _sealed) <- sealFixture fixture parents do
+ (_value, committed) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId "use-transitive-import") do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture "local-after-import")
+ Declaration.authorizeOmittedCandidate candidate do
+ void (Declaration.useAuthorizedFact fingerprint)
+ Declaration.recordOmittedUse
+ pure committed
+ pure batch
+
+ assertLocalFactOrdinalZero label batch =
+ case Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta batch) of
+ [occurrence] ->
+ assertEqual label
+ (localFactOrdinal 0)
+ (Semantic.factSlotOrdinal
+ (Semantic.semanticFactSlot occurrence))
+ facts ->
+ assertFailure
+ (label <> ": unexpected fact count "
+ <> show (length facts))
+
+sealFactFixture
+ :: Fixture
+ -> [FixtureSealed]
+ -> Text
+ -> IO
+ ( FixtureSealed
+ , Semantic.SemanticFactOccurrenceFingerprint
+ )
+sealFactFixture fixture parents alias = do
+ (batch, sealed) <- sealFixture fixture parents do
+ (_value, committed) <- Declaration.commitProofDeclaration
+ (Semantic.proofSyntaxId
+ (TextEncoding.encodeUtf8 alias)) do
+ candidate <- Declaration.reserveCandidate
+ (factSpec fixture alias)
+ Declaration.authorizeSourceAxiomCandidate candidate
+ pure committed
+ case Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta batch) of
+ [occurrence] ->
+ pure
+ ( sealed
+ , Semantic.semanticFactFingerprint occurrence
+ )
+ facts ->
+ assertFailure
+ ("unexpected sealed fact count: " <> show (length facts))
+ >> fail "unreachable"
+
+sealFixture
+ :: Fixture
+ -> [FixtureSealed]
+ -> Declaration.ModuleDriver Text value
+ -> IO (value, FixtureSealed)
+sealFixture fixture parents action = do
+ outcome <- runFixtureDriver fixture parents action
+ case outcome of
+ Declaration.DriverSucceeded value interface prefix _closure ->
+ pure
+ ( value
+ , FixtureSealed
+ interface
+ (Declaration.freshImportedModuleEvidence
+ [ evidence
+ | FixtureSealed _interface evidence <- parents
+ ]
+ interface
+ prefix)
+ )
+ Declaration.DriverFailed failure _prefix ->
+ assertFailure ("fixture failed: " <> show failure)
+ >> fail "unreachable"
+ Declaration.DriverSealFailed failure _prefix ->
+ assertFailure ("fixture did not seal: " <> show failure)
+ >> fail "unreachable"
+
+runFixtureDriver
+ :: Fixture
+ -> [FixtureSealed]
+ -> Declaration.ModuleDriver Text value
+ -> IO (Declaration.DriverResult Text value)
+runFixtureDriver fixture parents action = do
+ result <- Declaration.runModuleDriver
+ (fixtureFoundation fixture)
+ (fixtureOwner fixture)
+ [ Semantic.semanticInterfaceAssertedId interface
+ | FixtureSealed interface _evidence <- parents
+ ]
+ unavailableVampireResolver
+ Declaration.FreshValidation
+ do
+ traverse_
+ (\(FixtureSealed _interface evidence) ->
+ Declaration.importSealedModuleDriver evidence)
+ parents
+ action
+ expectRight result
+
+requireSingleOccurrence
+ :: Declaration.CommittedDeclarationBatch
+ -> Declaration.ModuleDriver
+ Declaration.DeclarationError
+ Semantic.SemanticFactOccurrence
+requireSingleOccurrence batch =
+ case Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta batch) of
+ [occurrence] ->
+ pure occurrence
+ _ ->
+ Declaration.failModuleDriver
+ Declaration.ProofDeclarationMustProduceOneFact
+
+expectRight :: Show error => Either error value -> IO value
+expectRight = \case
+ Left err ->
+ assertFailure (show err) >> fail "unreachable"
+ Right value ->
+ pure value
+
+expectRightIO :: Show error => IO (Either error value) -> IO value
+expectRightIO action =
+ action >>= expectRight
+
+withOpenedStore
+ :: Fixture
+ -> FilePath
+ -> (Store.Store -> IO value)
+ -> IO value
+withOpenedStore fixture root action =
+ bracket
+ (expectRightIO
+ (Store.openStore
+ (root Posix.</> "store.sqlite")
+ (Identity.theoryId (fixtureFoundation fixture))))
+ (Store.closeStore . snd)
+ (action . snd)
+
+withTemporaryDirectory :: String -> (FilePath -> IO a) -> IO a
+withTemporaryDirectory template =
+ bracket create Directory.removePathForcibly
+ where
+ create = do
+ root <- Directory.getTemporaryDirectory
+ (path, handle) <- openTempFile root template
+ hClose handle
+ Directory.removeFile path
+ Directory.createDirectory path
+ pure path