summaryrefslogtreecommitdiff
path: root/source/Test
diff options
context:
space:
mode:
Diffstat (limited to 'source/Test')
-rw-r--r--source/Test/Golden.hs43
-rw-r--r--source/Test/Unit.hs17
-rw-r--r--source/Test/Unit/Backend.hs245
-rw-r--r--source/Test/Unit/Checking.hs1982
-rw-r--r--source/Test/Unit/CommandLine.hs181
-rw-r--r--source/Test/Unit/Core.hs127
-rw-r--r--source/Test/Unit/Declaration.hs108
-rw-r--r--source/Test/Unit/Encoding.hs363
-rw-r--r--source/Test/Unit/Html.hs47
-rw-r--r--source/Test/Unit/HtmlOutput.hs114
-rw-r--r--source/Test/Unit/Kernel.hs8
-rw-r--r--source/Test/Unit/Migration.hs161
-rw-r--r--source/Test/Unit/Module.hs2665
-rw-r--r--source/Test/Unit/Provers.hs287
-rw-r--r--source/Test/Unit/Semantic.hs56
-rw-r--r--source/Test/Unit/Source.hs1930
-rw-r--r--source/Test/Unit/Store.hs26
-rw-r--r--source/Test/Unit/Symdiff.hs132
-rw-r--r--source/Test/Unit/Token.hs20
19 files changed, 2725 insertions, 5787 deletions
diff --git a/source/Test/Golden.hs b/source/Test/Golden.hs
index a62df9e..e230c26 100644
--- a/source/Test/Golden.hs
+++ b/source/Test/Golden.hs
@@ -5,14 +5,8 @@ module Test.Golden where
import Api qualified
-import Provers qualified
-import Tptp.UnsortedFirstOrder (toText)
import Base
-import Provers (defaultTimeLimit)
-import Control.Monad.Logger
-import Data.Text qualified as Text
-import Data.Text.IO qualified as TextIO
import Data.Text.Lazy.IO qualified as LazyTextIO
import System.Directory
import System.FilePath
@@ -20,7 +14,6 @@ import Test.Tasty
import Test.Tasty.Golden (goldenVsFile, findByExtension)
import Text.Pretty.Simple (pShowNoColor)
import UnliftIO
-import UnliftIO.Environment
goldenTests :: IO TestTree
goldenTests = goldenTestGroup
@@ -29,10 +22,6 @@ goldenTestGroup = testGroup "golden tests" <$> sequence
[ tokenizing
, scanning
, parsing
- , glossing
- , generatingTasks
- , encodingTasks
- , verification
]
@@ -93,35 +82,3 @@ parsing :: MonadUnliftIO io => io TestTree
parsing = makeGoldenTest "parsing" $ \Triple{..} -> do
parseResult <- Api.parse input
liftIO (LazyTextIO.writeFile output (pShowNoColor parseResult))
-
-
-glossing :: MonadUnliftIO io => io TestTree
-glossing = makeGoldenTest "glossing" $ \Triple{..} -> do
- interpretationResult <- Api.gloss input
- liftIO (LazyTextIO.writeFile output (pShowNoColor interpretationResult))
-
-
-generatingTasks :: MonadUnliftIO io => io TestTree
-generatingTasks = makeGoldenTest "generating tasks" $ \Triple{..} -> do
- tasks <- Api.generateTasks input
- liftIO $ LazyTextIO.writeFile output (pShowNoColor tasks)
-
-
-encodingTasks :: MonadUnliftIO io => io TestTree
-encodingTasks = makeGoldenTest "encoding tasks" $ \Triple{..} -> do
- tasks <- Api.encodeTasks input
- liftIO (TextIO.writeFile output (Text.intercalate "\n------------------\n" (toText <$> tasks)))
-
-
-verification :: MonadUnliftIO io => io TestTree
-verification = makeGoldenTest "verification" $ \Triple{..} -> do
- vampirePathPath <- (?? "vampire") <$> lookupEnv "NAPROCHE_ZF_VAMPIRE"
- let defaultVampire =
- Provers.vampire
- vampirePathPath
- Provers.defaultTimeLimit
- Provers.defaultMemoryLimit
- answers <-
- runNoLoggingT (Api.verify defaultVampire input)
- >>= either throwIO pure
- liftIO (LazyTextIO.writeFile output (pShowNoColor answers))
diff --git a/source/Test/Unit.hs b/source/Test/Unit.hs
index 302a6cf..3e5817c 100644
--- a/source/Test/Unit.hs
+++ b/source/Test/Unit.hs
@@ -2,15 +2,12 @@ module Test.Unit where
import Test.Tasty
-import Test.Tasty.HUnit
import Test.Unit.Abstract qualified as Abstract
import Test.Unit.Backend qualified as Backend
-import Test.Unit.Checking qualified as Checking
import Test.Unit.CommandLine qualified as CommandLine
import Test.Unit.Concrete qualified as Concrete
import Test.Unit.Core qualified as Core
import Test.Unit.Declaration qualified as Declaration
-import Test.Unit.Encoding qualified as Encoding
import Test.Unit.Foundation qualified as Foundation
import Test.Unit.Identity qualified as Identity
import Test.Unit.Html qualified as Html
@@ -21,26 +18,21 @@ import Test.Unit.Lexicon qualified as Lexicon
import Test.Unit.Meaning qualified as Meaning
import Test.Unit.Materialization qualified as Materialization
import Test.Unit.Module qualified as Module
-import Test.Unit.Migration qualified as Migration
import Test.Unit.OutputPlan qualified as OutputPlan
import Test.Unit.Provers qualified as Provers
import Test.Unit.Semantic qualified as Semantic
import Test.Unit.Source qualified as Source
import Test.Unit.Store qualified as Store
-import Test.Unit.Symdiff qualified as Symdiff
import Test.Unit.Token qualified as Token
unitTests :: TestTree
unitTests = testGroup "unit tests"
- [testCase "filter" filtersWell
- , Abstract.unitTests
+ [ Abstract.unitTests
, Backend.unitTests
- , Checking.unitTests
, CommandLine.unitTests
, Concrete.unitTests
, Core.unitTests
, Declaration.unitTests
- , Encoding.unitTests
, Foundation.unitTests
, Identity.unitTests
, Html.unitTests
@@ -51,7 +43,6 @@ unitTests = testGroup "unit tests"
, Meaning.unitTests
, Materialization.unitTests
, Module.unitTests
- , Migration.unitTests
, OutputPlan.unitTests
, Provers.unitTests
, Semantic.unitTests
@@ -59,9 +50,3 @@ unitTests = testGroup "unit tests"
, Store.unitTests
, Token.unitTests
]
-
-
-filtersWell :: Assertion
-filtersWell = do
- assertBool "Filter works on symdiff problem" Symdiff.filtersWell
- assertBool "Filter handles struct/app syntax" Symdiff.handlesStructAndApply
diff --git a/source/Test/Unit/Backend.hs b/source/Test/Unit/Backend.hs
index 0c4ff71..11c36b8 100644
--- a/source/Test/Unit/Backend.hs
+++ b/source/Test/Unit/Backend.hs
@@ -4,18 +4,14 @@
module Test.Unit.Backend (unitTests) where
import Base hiding (Empty)
-import Checking.Backend.Connection qualified as Connection
import Checking.Backend.Problem
import Checking.Backend.Tptp
import Checking.Core
import Checking.Foundation qualified as Foundation
-import Checking.Kernel.Derivation qualified as Derivation
import Provers
import Tptp.UnsortedFirstOrder qualified as Tptp
-import Control.Monad (unless)
import Data.Map.Strict qualified as Map
-import Data.Set qualified as Set
import Data.Text qualified as Text
import Data.Vector (Vector)
import Data.Vector qualified as Vector
@@ -58,9 +54,6 @@ unitTests =
, testCase
"renders checked FOF and TH0 problems"
rendersCheckedProblems
- , testCase
- "replays bounded Horn connection choices"
- replaysHornConnections
]
classifiesPropositionEquality :: Assertion
@@ -450,216 +443,6 @@ rendersCheckedProblems = do
globalPolicy
localPolicy)
-replaysHornConnections :: Assertion
-replaysHornConnections = do
- premiseP <- closedFrozen atomP
- premisePtoQ <-
- closedFrozen
- (CImp atomP
- (CImp atomP atomQ))
- premiseQtoR <-
- closedFrozen (CImp atomQ atomR)
- target <- closedFrozen atomR
- facts <-
- Vector.fromList
- <$> sequence
- [ checkedBackendFact
- (0 :: Int)
- atomP
- , checkedBackendFact
- 1
- (CImp atomP
- (CImp atomP atomQ))
- , checkedBackendFact
- 2
- (CImp atomQ atomR)
- ]
- claim <-
- checkedClosedProposition atomR
- problem <-
- either
- (assertFailure . show)
- pure
- (planTypedProblem
- testGlobalType
- facts
- claim
- []
- []
- ImplicitFofPremises
- FirstOrderLocals)
- connectionProblem <-
- either
- (assertFailure . show)
- pure
- (Connection.prepareConnectionProblem
- problem)
- threeNodeLimits <-
- either
- (assertFailure . show)
- pure
- (Connection.connectionLimits 100 3 8)
- case Connection.searchConnectionProblem
- threeNodeLimits
- connectionProblem of
- Connection.ConnectionSearchExhausted
- (Connection.ConnectionTraceNodesExhausted 3)
- _stats ->
- pure ()
- result ->
- assertFailure
- ("expected expanded-node exhaustion, got "
- <> show result)
- fourNodeLimits <-
- either
- (assertFailure . show)
- pure
- (Connection.connectionLimits 100 4 8)
- (foundTrace, searchStats) <-
- case Connection.searchConnectionProblem
- fourNodeLimits
- connectionProblem of
- Connection.ConnectionSearchFound
- found
- stats ->
- pure (found, stats)
- result ->
- assertFailure
- ("expected a Horn connection, got "
- <> show result)
- >> fail "unreachable"
- assertEqual
- "eleven charged search operations"
- 11
- (Connection.connectionSearchWork
- searchStats)
- assertEqual
- "three derived atoms"
- 3
- (Connection.connectionSearchDerivedAtomCount
- searchStats)
- assertEqual
- "candidate depth"
- 3
- (Connection.connectionSearchMaximumCandidateDepth
- searchStats)
- let root =
- Connection.connectionTraceRoot
- foundTrace
- assertEqual
- "claim uses the final rule"
- 2
- (Connection.connectionChoicePremiseOrdinal
- root)
- replayed <-
- either
- (assertFailure . show)
- pure
- (Connection.replayConnectionTrace
- fourNodeLimits
- connectionProblem
- foundTrace)
- assertEqual
- "replay uses every exact premise"
- (Set.fromList
- [ Derivation.importIx 0
- , Derivation.importIx 1
- , Derivation.importIx 2
- ])
- (Connection.replayedConnectionImportUses
- replayed)
- assertEqual
- "expanded replay nodes"
- 4
- (Connection.replayedConnectionNodeCount
- replayed)
- assertEqual
- "replay depth"
- 3
- (Connection.replayedConnectionMaximumDepth
- replayed)
- checkedFoundationValue <-
- either
- (assertFailure . show)
- pure
- Foundation.checkedFoundation
- imports <-
- traverse
- (either
- (assertFailure . show)
- pure
- . Derivation.derivationImportJudgment)
- [ premiseP
- , premisePtoQ
- , premiseQtoR
- ]
- kernelReplay <-
- either
- (assertFailure . show)
- pure
- (Derivation.replayKernelDerivation
- checkedFoundationValue
- Derivation.defaultKernelReplayLimits
- testGlobalType
- (Vector.fromList imports)
- target
- (Connection.replayedConnectionDerivation
- replayed))
- assertEqual
- "connection lifting proves the exact claim"
- target
- (Derivation.replayedKernelTarget
- kernelReplay)
- let wrongRoot =
- Connection.connectionTrace
- (Connection.connectionChoice
- 1
- [])
- case Connection.replayConnectionTrace
- fourNodeLimits
- connectionProblem
- wrongRoot of
- Left
- (Connection.ConnectionReplayRejected
- (Connection.ConnectionReplayGoalMismatch 1)) ->
- pure ()
- result ->
- assertFailure
- ("expected changed-choice rejection, got "
- <> case result of
- Left err -> show err
- Right _ -> "successful replay")
- case Connection.replayConnectionTrace
- threeNodeLimits
- connectionProblem
- foundTrace of
- Left
- (Connection.ConnectionReplayExhausted
- (Connection.ConnectionTraceNodesExhausted 3)) ->
- pure ()
- result ->
- assertFailure
- ("expected bounded replay exhaustion, got "
- <> case result of
- Left err -> show err
- Right _ -> "successful replay")
- tightWorkLimits <-
- either
- (assertFailure . show)
- pure
- (Connection.connectionLimits 10 4 8)
- case Connection.searchConnectionProblem
- tightWorkLimits
- connectionProblem of
- Connection.ConnectionSearchExhausted
- (Connection.ConnectionSearchWorkExhausted 10)
- _stats ->
- pure ()
- result ->
- assertFailure
- ("expected bounded search exhaustion, got "
- <> show result)
-
firstOrderClaim :: CanonicalTerm TestGlobal
firstOrderClaim =
CApp
@@ -675,18 +458,6 @@ higherOrderClaim =
(CGlobal FirstOrderPredicate)
(CBound 0)))
-atomP, atomQ, atomR :: CanonicalTerm TestGlobal
-atomP =
- firstOrderClaim
-atomQ =
- CApp
- (CGlobal FirstOrderPredicate)
- (COpaqueInteger 1)
-atomR =
- CApp
- (CGlobal FirstOrderPredicate)
- (COpaqueInteger 2)
-
checkedProposition
:: Vector (TestLocal, CoreType)
-> CanonicalTerm TestGlobal
@@ -750,22 +521,6 @@ checkedBackendFact reference term = do
proposition
capability)
-closedFrozen
- :: CanonicalTerm TestGlobal
- -> IO (FrozenCheckedCore TestGlobal)
-closedFrozen term = do
- checked <-
- either
- (assertFailure . show)
- pure
- (checkCanonicalCore
- testGlobalType
- term)
- unless
- (frozenCoreType checked == TyProp)
- (assertFailure "fixture is not a proposition")
- pure checked
-
checkedLocalPremise
:: Natural
-> Text
diff --git a/source/Test/Unit/Checking.hs b/source/Test/Unit/Checking.hs
deleted file mode 100644
index 13499a3..0000000
--- a/source/Test/Unit/Checking.hs
+++ /dev/null
@@ -1,1982 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module Test.Unit.Checking (unitTests) where
-
-import Base
-import Checking
-import Checking.Dependencies qualified as Dependencies
-import Checking.Facts qualified as Facts
-import Checking.Legacy
-import Checking.Obligation
-import Checking.Structure qualified as Structure
-import Encoding (contractionTask, encodeTaskText)
-import Report.Location
-import Syntax.Internal
-import Syntax.Lexicon (_Onesorted, pattern ApplySymbol)
-
-import Bound.Scope (bindings, fromScope, toScope)
-import Bound.Var (Var(..))
-import Control.Exception (try)
-import Control.Monad.State (runStateT)
-import Data.HashSet qualified as HS
-import Data.IORef (modifyIORef', newIORef, readIORef)
-import Data.Set qualified as Set
-import Data.Text qualified as Text
-import Test.Tasty
-import Test.Tasty.HUnit
-
-unitTests :: TestTree
-unitTests = testGroup "Checking"
- [ testCase "renders checking context without constructors" do
- let rendered =
- renderCheckingError
- (DuplicateMarker Nowhere (Marker "labelled"))
- assertEqual
- "checking diagnostic"
- "<nowhere> -1:-1 in labelled: marker is already registered"
- rendered
- assertBool
- "internal Marker constructor is absent"
- (not ("Marker" `Text.isInfixOf` rendered))
- , testCase "TPTP encoding excludes task provenance" do
- registration <-
- registerFilePathWithDisplay
- "/tmp/f24-source.tex"
- "quote\"\nfof(injected,axiom,$false).\nλ.tex"
- fileId <- either
- (assertFailure . ("location registration failed: " <>) . show)
- pure
- registration
- let expected = "fof(zf_q0,conjecture,$true)."
- plainTask = Task
- { taskDirectness = Direct
- , taskHypotheses = []
- , taskConjectureLabel = Marker "provenance_test"
- , taskLocation = Nowhere
- , taskConjecture = PropositionalConstant IsTop
- }
- adversarialTask = plainTask
- { taskDirectness =
- Indirect (PropositionalConstant IsBottom)
- , taskLocation = mkLocation fileId 12 34
- }
- assertEqual "three-argument TPTP" expected (encodeTaskText plainTask)
- assertEqual
- "path, span, and directness do not affect proof bytes"
- (encodeTaskText plainTask)
- (encodeTaskText adversarialTask)
- , testCase "prepares complete ordered obligation batches"
- preparesCompleteObligationBatches
- , testCase "replacement conditions remain existentially scoped" do
- let x = NamedVar "x"
- y = NamedVar "y"
- replacement =
- makeReplacementIff
- (TermVar (F (NamedVar "image")))
- ((x, TermVar (NamedVar "X"))
- :| [(y, TermVar (NamedVar "Y"))])
- (abstractVarSymbols [x, y] (TermVar x))
- (abstractVarSymbols
- [x, y]
- (Equals Nowhere (TermVar x) (TermVar y)))
- case replacement of
- Quantified Universally outerScope -> do
- assertEqual
- "outer binders"
- [NamedVar "frv"]
- (nubOrd (bindings outerScope))
- case fromScope outerScope of
- Connected
- Equivalence
- _
- (Quantified Existentially innerScope) ->
- case fromScope innerScope of
- And _ (And _ (Equals _ left right)) -> do
- assertEqual
- "condition left operand"
- (TermVar (B x))
- left
- assertEqual
- "condition right operand"
- (TermVar (B y))
- right
- body ->
- assertFailure
- ( "expected replacement condition equality, got "
- <> show body
- )
- body ->
- assertFailure
- ("expected replacement equivalence, got "
- <> show body)
- formula ->
- assertFailure
- ("expected replacement universal, got " <> show formula)
- , testCase "fix rejects shadowing theorem-local variables" do
- expectCheckingError "already in scope" (lemmaBlocks "bad_fix" badFixLemma badFixProof)
- , testCase "define rejects shadowing local variables" do
- expectCheckingError "already in scope" (lemmaBlocks "bad_define" badDefineLemma badDefineProof)
- , testCase "take rejects shadowing theorem-local variables" do
- expectCheckingError "already in scope" (lemmaBlocks "bad_take" badTakeLemma badTakeProof)
- , testCase "have rejects new free variables" do
- expectCheckingError "not in scope" (lemmaBlocks "bad_have" badHaveLemma badHaveProof)
- , testCase "define function rejects shadowing function name" do
- expectCheckingError "already in scope" (lemmaBlocks "bad_define_function_name" badDefineFunctionNameLemma badDefineFunctionNameProof)
- , testCase "define function rejects shadowing argument name" do
- expectCheckingError "shadow local variable" (lemmaBlocks "bad_define_function_arg" badDefineFunctionArgLemma badDefineFunctionArgProof)
- , testCase "free theorem goal variables are local in proofs" do
- expectChecks (lemmaBlocks "free_goal_local" freeGoalLocalLemma freeGoalLocalProof)
- , testCase "fix accepts fresh local variables" do
- expectChecks (lemmaBlocks "fresh_fix" freshFixLemma freshFixProof)
- , testCase "take accepts fresh witnesses" do
- expectChecks (lemmaBlocks "fresh_take" freshTakeLemma freshTakeProof)
- , testCase "assume rejects disjunctive goals" do
- expectMismatchedAssume unsoundDisjunctionAssumeBlocks
- , assumptionGoalReductionTests
- , proofShapeErrorTests
- , testCase "struct axioms recursively rewrite carrier labels" do
- text <- encodedTasksText structCarrierRewriteBlocks
- assertContains "rewritten struct-rule carrier" "zf_u0(zf_f1,zf_s0(zf_f0))" text
- assertNotContains "raw struct-rule carrier" "zf_u0(zf_f1,zf_f0)" text
- , testCase "struct axioms annotate operations from the same structure" do
- text <- encodedTasksText structOperationRewriteBlocks
- assertContains "annotated struct operation in rule" "zf_u0(zf_s1(zf_f0),zf_s0(zf_f0))" text
- , testCase "structure terms fail before task encoding" do
- unresolved <-
- try
- (check
- WithoutDumpPremselTraining
- unresolvedStructOperationBlocks)
- :: IO (Either CheckingError [Task])
- case unresolved of
- Left
- (UnresolvedStructureOperation
- actualSymbol
- actualLocation
- actualMarker) -> do
- assertEqual
- "structure operation"
- fooOp
- actualSymbol
- assertEqual
- "block location"
- structureTermErrorLocation
- actualLocation
- assertEqual
- "block marker"
- "unresolved_structure_operation"
- actualMarker
- Left err ->
- assertFailure
- ("expected unresolved structure operation, got "
- <> show err)
- Right _ ->
- assertFailure
- "expected unresolved structure operation to fail"
- expectCheckingError
- "Nested comprehensions are not supported"
- nestedStructComprehensionBlocks
- , testCase "exact structure claims introduce carrier labels for continuations" do
- text <- encodedTasksText structClaimIntroducesContextBlocks
- assertContains "claim continuation carrier" "conjecture,zf_u0(zf_f1,zf_s0(zf_f0))" text
- , testCase "bound variables do not inherit outer carrier labels" do
- text <- encodedTasksText boundStructLabelBlocks
- assertContains "bound carrier label remains raw" "![V0]:zf_u0(zf_f1,V0)" text
- assertNotContains "bound carrier label not rewritten" "![V0]:zf_u0(zf_f1,zf_s0(V0))" text
- , structureTransactionTests
- , testCase "abbreviations reject direct self-reference" do
- expectCheckingError "self-referential" directSelfReferentialAbbrBlocks
- , testCase "abbreviations reject indirect self-reference after expansion" do
- expectCheckingError "self-referential" indirectSelfReferentialAbbrBlocks
- , testCase "predicate definitions reject direct self-reference" do
- expectCheckingError "self-referential" directSelfReferentialPredicateDefinitionBlocks
- , testCase "function definitions reject direct self-reference" do
- expectCheckingError "self-referential" directSelfReferentialFunctionDefinitionBlocks
- , testCase "operator definitions reject direct self-reference" do
- expectCheckingError "self-referential" directSelfReferentialOperatorDefinitionBlocks
- , testCase "definitions reject abbreviation-hidden self-reference" do
- expectCheckingError "self-referential" abbreviationHiddenSelfReferentialDefinitionBlocks
- , testCase "definitions reject abbreviation-hidden self-reference in assumptions" do
- expectCheckingError "self-referential" assumptionHiddenSelfReferentialDefinitionBlocks
- , testCase "ordinary definitions accept non-recursive bodies" do
- expectChecks nonRecursiveDefinitionBlocks
- , testCase "definitions reject builtin mixfix marker collisions" do
- expectCheckingError "object-symbol marker pow is already owned by builtin" [builtinMixfixMarkerCollisionBlock]
- , testCase "definitions reject builtin predicate marker collisions" do
- expectCheckingError "object-symbol marker elem is already owned by builtin" [builtinPredicateMarkerCollisionBlock]
- , testCase "abbreviations reject builtin marker collisions" do
- expectCheckingError "object-symbol marker pow is already owned by builtin" [builtinAbbreviationMarkerCollisionBlock]
- , testCase "builtin object markers do not reserve proof labels" do
- expectChecks [builtinMarkerProofLabelBlock]
- , testCase "subseteq remains user-definable" do
- expectChecks [subseteqDefinitionBlock]
- , testCase "datatype accepts bootstrap propositional fragment" do
- expectChecks [goodDatatypeBlock]
- , testCase "datatype treats a carrier alias as direct recursion" do
- directFacts <-
- datatypePreparedFacts [goodDatatypeBlock]
- aliasedFacts <-
- datatypePreparedFacts directRecursionAliasDatatypeBlocks
- assertEqual
- "generated datatype facts"
- directFacts
- aliasedFacts
- , testCase "datatype rejects powerset recursion through aliases" do
- for_
- [ oneHopPowersetAliasDatatypeBlocks
- , multiHopPowersetAliasDatatypeBlocks
- ]
- (expectCheckingError "recursive premise must be direct")
- , testCase "datatype rejects nested recursive premise" do
- expectCheckingError "recursive premise must be direct" [badNestedRecursiveDatatypeBlock]
- , testCase "datatype rejects missing constructor premise" do
- expectCheckingError "missing premise" [badMissingPremiseDatatypeBlock]
- , testCase "datatype rejects duplicate constructor patterns" do
- expectCheckingError "constructor patterns must be distinct" [badDuplicateConstructorDatatypeBlock]
- , testCase "datatype rejects open premise domains" do
- expectCheckingError "closed terms" [badOpenDomainDatatypeBlock]
- , testCase "datatype rejects application-shaped constructors" do
- expectCheckingError "function application" [badApplyConstructorDatatypeBlock]
- , testCase "datatype generates trusted fact markers" do
- expectFactMarkers datatypeGeneratedMarkers [goodDatatypeBlock]
- , testCase "datatype generated fact markers are reserved globally" do
- expectDefinedMarkers datatypeGeneratedMarkers [goodDatatypeBlock]
- , testCase "datatype generated intro facts are usable by reference" do
- expectChecks datatypeIntroReferenceBlocks
- , testCase "datatype generated distinctness fact is usable by reference" do
- expectChecks datatypeDistinctReferenceBlocks
- , testCase "datatype generated injective fact is usable by reference" do
- expectChecks datatypeInjectiveReferenceBlocks
- , testCase "datatype generated fact markers cannot be reused by later blocks" do
- expectDuplicateMarker "propform_cases" datatypeGeneratedMarkerReuseBlocks
- , testCase "datatype rejects duplicate constructor markers" do
- expectCheckingError "object-symbol marker dup is already owned by datatype constructor" [badDuplicateConstructorMarkerDatatypeBlock]
- , testCase "signature predicate declares symbols for later facts" do
- expectChecks signaturePredicateUsageBlocks
- , testCase "signature formula declares symbolic operators for later facts" do
- expectChecks signatureFormulaUsageBlocks
- , testCase "signature formula rejects unrecoverable declarations" do
- expectCheckingError "could not recover the declared symbol" [badSignatureFormulaBlock]
- , testCase "inductive accepts bounded fin fragment" do
- expectChecks goodInductiveBlocks
- , testCase "inductive generates trusted fact markers" do
- expectFactMarkers inductiveGeneratedMarkers goodInductiveBlocks
- , testCase "inductive generated fact markers are reserved globally" do
- expectDefinedMarkers inductiveGeneratedMarkers goodInductiveBlocks
- , testCase "inductive generated intro and domain facts are usable by reference" do
- expectChecks inductiveIntroAndDomainReferenceBlocks
- , testCase "inductive generated cases fact is usable by reference" do
- expectChecks inductiveCasesReferenceBlocks
- , testCase "inductive generated induction fact is usable by reference" do
- expectChecks inductiveInductReferenceBlocks
- , testCase "inductive generates monotonicity obligations for recursive carriers" do
- text <- encodedTasksText goodMonotoneInductiveBlocks
- assertContains "monotonicity antecedent expands subset" "zf_u1(V2,V0)=>zf_u1(V2,V1)" text
- assertContains "monotonicity conclusion expands subset" "zf_u1(V3,zf_u0(V0))=>zf_u1(V3,zf_u0(V1))" text
- , testCase "inductive rejects recursive premises outside carrier positions" do
- expectCheckingError "carrier of a membership premise" [badRecursiveTermInductiveBlock]
- , testCase "inductive rejects malformed recursive premises" do
- expectCheckingError "direct membership condition" [badRecursiveFormulaInductiveBlock]
- , testCase "inductive rejects malformed results" do
- expectCheckingError "form t \\in F(args)" [badInductiveResultBlock]
- , testCase "inductive rejects recursive occurrences with the wrong arguments" do
- expectCheckingError "wrong arguments" [badInductiveWrongArgsBlock]
- , testCase "inductive validates generated markers before emitting obligations" do
- tasksRef <- newIORef []
- result <-
- try
- (runCheckingBlocks
- [ BlockAxiom
- Nowhere
- "fin_cases"
- (Axiom [] Top)
- , goodInductiveBlock
- ]
- ( initialCheckingState
- WithoutDumpPremselTraining
- (\task -> modifyIORef' tasksRef (task :))
- ))
- :: IO (Either CheckingError CheckingState)
- case result of
- Left (DuplicateMarker _ actualMarker) ->
- assertEqual
- "duplicate marker"
- "fin_cases"
- actualMarker
- Left err ->
- assertFailure
- ("expected DuplicateMarker, got " <> show err)
- Right _ ->
- assertFailure
- "expected generated marker validation to fail"
- tasks <- readIORef tasksRef
- assertBool
- "failed inductive obligations"
- (null tasks)
- , testCase "inductive rejects duplicate carrier ownership" do
- expectCheckingError "already owned" duplicateInductiveCarrierBlocks
- , testCase "inductive rejects operator definitions with the same carrier symbol" do
- expectCheckingError "already owned" operatorThenInductiveBlocks
- , testCase "inductive rejects prior axiom mentions of the carrier" do
- expectCheckingError "without prior ownership" priorInductiveCarrierAxiomBlocks
- , testCase "inductive rejects direct recursive domains" do
- expectCheckingError "independent of the inductive symbol" [badInductiveSelfDomainBlock]
- , testCase "inductive rejects abbreviation-hidden recursive domains" do
- expectCheckingError "independent of the inductive symbol" hiddenSelfDomainBlocks
- , testCase "inductive rejects prior ordinary-definition mentions of the carrier via domains" do
- expectCheckingError "without prior ownership" hiddenDefinitionDomainBlocks
- , testCase "inductive rejects prior ordinary-definition mentions of the carrier via side-condition aliases" do
- expectCheckingError "without prior ownership" hiddenCarrierSideConditionBlocks
- , testCase "datatype rejects prior signature mentions of the datatype head" do
- expectCheckingError "already owned" priorDatatypeHeadSignatureBlocks
- , testCase "datatype rejects prior theorem mentions of constructors" do
- expectCheckingError "without prior ownership" priorDatatypeConstructorLemmaBlocks
- , testCase "datatype constructor ownership blocks later operator definitions" do
- expectCheckingError "already owned" datatypeConstructorThenOperatorBlocks
- , testCase "inductive freezes mentioned symbols against later definitions" do
- expectCheckingError "already owned by signature formula" frozenSymbolDefinitionBlocks
- , testCase "inductive freezes symbols from canonicalized domains" do
- expectCheckingError "already owned by signature formula" canonicalizedDomainFreezeBlocks
- , testCase "inductive freezes transitive definition dependencies" do
- expectCheckingError "already owned by signature formula" transitiveFrozenDefinitionBlocks
- ]
-
-preparesCompleteObligationBatches :: Assertion
-preparesCompleteObligationBatches = do
- registry <-
- case
- Facts.registerStagedFacts
- ( Facts.stageFact
- ("known_fact" :| [])
- (Facts.factOrigin Nowhere "known_block")
- (Facts.prepareSemanticFact Top)
- :| []
- )
- Facts.emptyFactRegistry of
- Left marker ->
- assertFailure
- ("could not register premise " <> show marker)
- Right preparedRegistry ->
- pure preparedRegistry
- batchesRef <- newIORef []
- let initial =
- ( initialCheckingStateWithTaskPreparation
- WithoutDumpPremselTraining
- contractionTask
- (\batch ->
- modifyIORef' batchesRef (batch :))
- )
- { checkingFacts = registry
- , checkingGoals = [Top `Iff` Top, Bottom]
- , blockLabel = "batch_claim"
- , stepLocation = Nowhere
- }
- (_result, afterGoals) <- runStateT tellTasks initial
- (_emptyResult, afterEmpty) <-
- runStateT
- tellTasks
- afterGoals{checkingGoals = []}
- batches <- reverse <$> readIORef batchesRef
- case batches of
- [goalBatch, emptyBatch] -> do
- assertEqual "batch marker"
- "batch_claim"
- (preparedBatchMarker goalBatch)
- assertEqual "batch location"
- Nowhere
- (preparedBatchLocation goalBatch)
- assertEqual "stable declaration-local ordinals"
- [0, 1]
- ( legacyObligationOrdinalValue
- . preparedObligationOrdinal
- <$> toList
- (preparedBatchObligations goalBatch)
- )
- assertEqual "prepared contracted goals"
- [Top, Bottom]
- ( taskConjecture
- . preparedObligationTask
- <$> toList
- (preparedBatchObligations goalBatch)
- )
- case toList (preparedBatchPremises goalBatch) of
- [premise] -> do
- assertEqual "premise marker"
- "known_fact"
- (hypothesisMarker
- (preparedPremiseHypothesis premise))
- assertEqual "premise provenance"
- (RegisteredFactPremise
- (Facts.factOrigin
- Nowhere
- "known_block"))
- (preparedPremiseOrigin premise)
- premises ->
- assertFailure
- ("expected one premise, got "
- <> show (length premises))
- assertBool "empty batch callback"
- (null (preparedBatchObligations emptyBatch))
- assertEqual "empty batch does not consume an ordinal"
- 2
- (legacyObligationOrdinalValue
- (checkingNextObligationOrdinal afterEmpty))
- _ ->
- assertFailure
- ("expected one goal batch and one empty batch, got "
- <> show (length batches))
-
-structureTransactionTests :: TestTree
-structureTransactionTests =
- testGroup "structure transactions"
- [ testCase "reject positive and negative direct self-reference" do
- for_ [fooStructPredicate "A", Not Nowhere (fooStructPredicate "A")]
- \assumption ->
- expectCheckingError
- "self-referential"
- [fooStructBlock "self_struct" [("self_rule", assumption)]]
- , testCase "reject abbreviation-hidden self-reference" do
- expectCheckingError
- "self-referential"
- hiddenSelfReferentialStructBlocks
- , testCase "report unknown and forward parents as located errors" do
- expectUnknownStructureParent
- unknownStruct
- [testStructBlock "unknown_child" childStruct (Set.singleton unknownStruct) []]
- expectUnknownStructureParent
- fooStruct
- [ testStructBlock "forward_child" childStruct (Set.singleton fooStruct) []
- , fooStructBlock "forward_parent" []
- ]
- expectUnknownStructureParent
- fooStruct
- [testStructBlock "self_parent" fooStruct (Set.singleton fooStruct) []]
- , testCase "reject every local structure marker collision" do
- for_
- [ ( "same_marker"
- , fooStructBlock "same_marker" [("same_marker", Top)]
- )
- , ( "duplicate_rule"
- , fooStructBlock
- "duplicate_rules"
- [("duplicate_rule", Top), ("duplicate_rule", Top)]
- )
- , ( "inherit_collisioninherit"
- , fooStructBlock
- "inherit_collision"
- [("inherit_collisioninherit", Top)]
- )
- ]
- \(duplicate, block) ->
- expectDuplicateMarker duplicate [block]
- , testCase "reject collisions before and after a structure" do
- expectDuplicateMarker
- "prior_rule"
- [ BlockAxiom Nowhere "prior_rule" (Axiom [] Top)
- , fooStructBlock "prior_collision" [("prior_rule", Top)]
- ]
- expectDuplicateMarker
- "later_collisioninherit"
- [ fooStructBlock "later_collision" []
- , BlockAxiom
- Nowhere
- "later_collisioninherit"
- (Axiom [] Top)
- ]
- , testCase "commit exact prepared facts and backward dependencies" do
- case preparedFooStructure "prepared_struct" of
- Left err ->
- assertFailure
- ("could not prepare structure: " <> show err)
- Right checked -> do
- let context = BlockContext Nowhere "prepared_struct"
- initial =
- initialCheckingState
- WithoutDumpPremselTraining
- (\_task -> pure ())
- case commitCheckedStructDefn context checked initial of
- Left err ->
- assertFailure
- ("could not commit structure: " <> show err)
- Right committed -> do
- assertBool
- "fact registry invariant"
- (Facts.factRegistryInvariant
- (checkingFacts committed))
- for_
- (zip
- (toList
- (Structure.checkedStructMarkers checked))
- (toList
- (Structure.checkedStructSemanticFacts checked)))
- \(factMarker, prepared) ->
- assertEqual
- ("prepared fact " <> show factMarker)
- (Just prepared)
- (Facts.lookupPreparedFact
- factMarker
- (checkingFacts committed))
- assertEqual
- "structure dependencies"
- (Just
- (Set.singleton
- (SymbolPredicate
- (PredicateNounStruct _Onesorted))))
- (Dependencies.lookupDependencies
- (Structure.checkedStructSymbol checked)
- (checkingDependencies committed))
- ]
-
-preparedFooStructure
- :: Marker
- -> Either
- Structure.StructurePreparationError
- Structure.CheckedStructDefn
-preparedFooStructure marker =
- Structure.prepareCheckedStructDefn
- Nowhere
- marker
- (fooStructDefn [("prepared_rule", Top)])
- (Set.singleton _Onesorted)
- (Set.singleton CarrierSymbol)
-
-expectUnknownStructureParent
- :: StructPhrase
- -> [Block]
- -> Assertion
-expectUnknownStructureParent expected blocks = do
- result <-
- try (check WithoutDumpPremselTraining blocks)
- :: IO (Either CheckingError [Task])
- case result of
- Left (UnknownStructureParent actual Nowhere _) ->
- assertEqual "unknown structure parent" expected actual
- Left err ->
- assertFailure
- ("expected UnknownStructureParent, got " <> show err)
- Right _ ->
- assertFailure "expected an unknown structure parent"
-
-assumptionGoalReductionTests :: TestTree
-assumptionGoalReductionTests =
- testGroup "assumption goal reductions"
- [ testCase "introduces an implication antecedent" do
- assertGoalReduction
- (ImplicationIntroduction propositionA propositionC)
- propositionA
- (propositionA `Implies` propositionC)
- propositionC
- , testCase "curries an assumed left conjunct" do
- assertGoalReduction
- (CurryLeftConjunct propositionA propositionB propositionC)
- propositionA
- ((propositionA `And` propositionB) `Implies` propositionC)
- (propositionB `Implies` propositionC)
- , testCase "curries an assumed right conjunct" do
- assertGoalReduction
- (CurryRightConjunct propositionA propositionB propositionC)
- propositionB
- ((propositionA `And` propositionB) `Implies` propositionC)
- (propositionA `Implies` propositionC)
- , testCase "does not reduce a disjunction" do
- assertEqual "disjunction reduction"
- Nothing
- (reduceGoalWithAssumption
- propositionA
- (propositionA `Or` propositionB))
- ]
-
-proofShapeErrorTests :: TestTree
-proofShapeErrorTests =
- testCase "malformed proof shapes return located errors" do
- for_ cases \(label, expectedError, action) -> do
- result <- try action :: IO (Either CheckingError ())
- assertEqual label (Left expectedError) result
- where
- cases =
- [ ( "ordinal induction goal"
- , ByOrdInductionSyntacticMismatch
- proofShapeLocation
- "bad_ordinal_induction"
- , checkAsUnit
- (proofBlocks
- "bad_ordinal_induction"
- Top
- (ByOrdInduction
- proofShapeLocation
- (Omitted proofShapeLocation)))
- )
- , ( "set extensionality with take"
- , SetExtensionalityWithTake
- proofShapeLocation
- "bad_take_setext"
- , checkAsUnit
- (proofBlocks
- "bad_take_setext"
- Top
- (Take
- proofShapeLocation
- ("witness" :| [])
- Top
- JustificationSetExt
- (Omitted proofShapeLocation)))
- )
- ]
-
- checkAsUnit =
- void . check WithoutDumpPremselTraining
-
- proofBlocks marker goal proof =
- [ BlockLemma
- proofShapeLocation
- marker
- (Lemma [] goal)
- , BlockProof
- proofShapeLocation
- proofShapeLocation
- proof
- ]
-
- proofShapeLocation =
- mkLocation (FileId 47) 6 11
-
-assertGoalReduction
- :: GoalReduction
- -> Formula
- -> Formula
- -> Formula
- -> Assertion
-assertGoalReduction expected assumption original residual =
- case reduceGoalWithAssumption assumption original of
- Nothing ->
- assertFailure "expected a goal reduction"
- Just reduction -> do
- assertEqual "trusted rule" expected reduction
- assertEqual "introduced assumption"
- assumption
- (goalReductionAssumption reduction)
- assertEqual "residual goal"
- residual
- (goalReductionResidual reduction)
- assertReductionSound original reduction
-
-assertReductionSound :: Formula -> GoalReduction -> Assertion
-assertReductionSound original reduction =
- for_ propositionAssignments \assignment -> do
- let discharged =
- goalReductionAssumption reduction
- `Implies` goalReductionResidual reduction
- soundness = discharged `Implies` original
- assertBool
- ( "reduction is not sound under "
- <> show assignment
- <> ": "
- <> show reduction
- )
- (evaluateProposition assignment soundness)
-
-type PropositionAssignment = (Bool, Bool, Bool)
-
-evaluateProposition :: PropositionAssignment -> Formula -> Bool
-evaluateProposition assignment@(a, b, c) = \case
- Atomic _location (PredicateSymbol name) [] ->
- case name of
- "A" -> a
- "B" -> b
- "C" -> c
- _ -> error ("missing proposition value for " <> show name)
- left `And` right ->
- evaluateProposition assignment left
- && evaluateProposition assignment right
- left `Or` right ->
- evaluateProposition assignment left
- || evaluateProposition assignment right
- left `Implies` right ->
- not (evaluateProposition assignment left)
- || evaluateProposition assignment right
- Not _location formula ->
- not (evaluateProposition assignment formula)
- Top ->
- True
- Bottom ->
- False
- formula ->
- error
- ( "not a propositional test formula under "
- <> show assignment
- <> ": "
- <> show formula
- )
-
-propositionAssignments :: [PropositionAssignment]
-propositionAssignments =
- [ (a, b, c)
- | a <- [False, True]
- , b <- [False, True]
- , c <- [False, True]
- ]
-
-propositionA, propositionB, propositionC :: Formula
-propositionA = proposition "A"
-propositionB = proposition "B"
-propositionC = proposition "C"
-
-proposition :: Text -> Formula
-proposition name =
- Atomic Nowhere (PredicateSymbol name) []
-
-expectChecks :: [Block] -> Assertion
-expectChecks blocks = do
- _tasks <- check WithoutDumpPremselTraining blocks
- pure ()
-
-encodedTasksText :: [Block] -> IO Text
-encodedTasksText blocks = do
- tasks <- check WithoutDumpPremselTraining blocks
- if null tasks
- then assertFailure "expected at least one generated task"
- else pure ()
- pure (Text.intercalate "\n------------------\n" (encodeTaskText <$> tasks))
-
-expectCheckingError :: Text -> [Block] -> Assertion
-expectCheckingError fragment blocks = do
- result <- try (check WithoutDumpPremselTraining blocks) :: IO (Either CheckingError [Task])
- case result of
- Right _ ->
- assertFailure "expected a CheckingError, but checking succeeded"
- Left err@(CheckingError msg _ _) ->
- assertBool ("expected error containing " <> show fragment <> ", got " <> show err) (fragment `Text.isInfixOf` msg)
- Left err ->
- assertFailure ("expected generic CheckingError, got " <> show err)
-
-expectMismatchedAssume :: [Block] -> Assertion
-expectMismatchedAssume blocks = do
- result <- try (check WithoutDumpPremselTraining blocks) :: IO (Either CheckingError [Task])
- case result of
- Right _ ->
- assertFailure "expected a MismatchedAssume error, but checking succeeded"
- Left (MismatchedAssume _assumption _goal _location _marker) ->
- pure ()
- Left err ->
- assertFailure ("expected MismatchedAssume, got " <> show err)
-
-expectFactMarkers :: [Marker] -> [Block] -> Assertion
-expectFactMarkers markers blocks = do
- checkingState <- runCheckingBlocks blocks (initialCheckingState WithoutDumpPremselTraining (\_task -> pure ()))
- let facts = checkingFacts checkingState
- for_ markers \marker ->
- assertBool
- ("expected generated fact marker " <> show marker)
- (isJust (Facts.lookupPreparedFact marker facts))
-
-datatypePreparedFacts
- :: [Block]
- -> IO [Facts.PreparedSemanticFact]
-datatypePreparedFacts blocks = do
- checkingState <-
- runCheckingBlocks
- blocks
- ( initialCheckingState
- WithoutDumpPremselTraining
- (\_task -> pure ())
- )
- traverse
- (lookupFact (checkingFacts checkingState))
- datatypeGeneratedMarkers
- where
- lookupFact facts marker =
- case Facts.lookupPreparedFact marker facts of
- Just fact ->
- pure fact
- Nothing -> do
- assertFailure
- ("missing generated datatype fact " <> show marker)
- pure
- (impossible
- "assertFailure returned while looking up a datatype fact")
-
-expectDefinedMarkers :: [Marker] -> [Block] -> Assertion
-expectDefinedMarkers markers blocks = do
- checkingState <- runCheckingBlocks blocks (initialCheckingState WithoutDumpPremselTraining (\_task -> pure ()))
- let reserved = definedMarkers checkingState
- for_ markers \marker ->
- assertBool ("expected reserved marker " <> show marker) (HS.member marker reserved)
-
-expectDuplicateMarker :: Marker -> [Block] -> Assertion
-expectDuplicateMarker expectedMarker blocks = do
- result <- try (check WithoutDumpPremselTraining blocks) :: IO (Either CheckingError [Task])
- case result of
- Right _ ->
- assertFailure "expected a DuplicateMarker error, but checking succeeded"
- Left (DuplicateMarker _ actualMarker) ->
- assertEqual "duplicate marker" expectedMarker actualMarker
- Left err ->
- assertFailure ("expected DuplicateMarker, got " <> show err)
-
-assertContains :: String -> Text -> Text -> Assertion
-assertContains label needle haystack =
- assertBool (label <> ": expected to find " <> show needle <> " in " <> Text.unpack haystack) (needle `Text.isInfixOf` haystack)
-
-assertNotContains :: String -> Text -> Text -> Assertion
-assertNotContains label needle haystack =
- assertBool (label <> ": expected not to find " <> show needle <> " in " <> Text.unpack haystack) (not (needle `Text.isInfixOf` haystack))
-
-lemmaBlocks :: Marker -> Lemma -> Proof -> [Block]
-lemmaBlocks marker lemma proof =
- [BlockLemma Nowhere marker lemma, BlockProof Nowhere Nowhere proof]
-
-badFixLemma :: Lemma
-badFixLemma =
- Lemma [Asm (var "a" `eq` var "b")] (makeForall ["x"] (var "x" `eq` var "b"))
-
-badFixProof :: Proof
-badFixProof =
- Fix Nowhere ("a" :| []) Top (Qed (Just Nowhere) JustificationLocal)
-
-badDefineLemma :: Lemma
-badDefineLemma =
- Lemma [] (makeForall ["x"] (var "x" `eq` emptySet))
-
-badDefineProof :: Proof
-badDefineProof =
- Fix Nowhere ("x" :| []) Top (Define Nowhere "x" emptySet (Qed (Just Nowhere) JustificationLocal))
-
-badTakeLemma :: Lemma
-badTakeLemma =
- Lemma [Asm (makeExists ["x"] (var "x" `neq` var "b"))] (var "a" `neq` var "b")
-
-badTakeProof :: Proof
-badTakeProof =
- Take Nowhere ("a" :| []) (var "a" `neq` var "b") JustificationLocal (Qed (Just Nowhere) JustificationLocal)
-
-badHaveLemma :: Lemma
-badHaveLemma =
- Lemma [] Top
-
-badHaveProof :: Proof
-badHaveProof =
- Have Nowhere (var "c" `eq` var "c") JustificationEmpty (Qed (Just Nowhere) JustificationEmpty)
-
-badDefineFunctionNameLemma :: Lemma
-badDefineFunctionNameLemma =
- Lemma [] (var "f" `eq` var "f")
-
-badDefineFunctionNameProof :: Proof
-badDefineFunctionNameProof =
- DefineFunction Nowhere "f" "x" (var "x") emptySet (Qed (Just Nowhere) JustificationLocal)
-
-badDefineFunctionArgLemma :: Lemma
-badDefineFunctionArgLemma =
- Lemma [] (var "x" `eq` var "x")
-
-badDefineFunctionArgProof :: Proof
-badDefineFunctionArgProof =
- DefineFunction Nowhere "f" "x" (var "x") emptySet (Qed (Just Nowhere) JustificationLocal)
-
-freeGoalLocalLemma :: Lemma
-freeGoalLocalLemma =
- Lemma [] (var "b" `eq` var "b")
-
-freeGoalLocalProof :: Proof
-freeGoalLocalProof =
- Qed (Just Nowhere) JustificationEmpty
-
-freshFixLemma :: Lemma
-freshFixLemma =
- Lemma [] (makeForall ["x"] (var "x" `eq` var "x"))
-
-freshFixProof :: Proof
-freshFixProof =
- Fix Nowhere ("x" :| []) Top (Qed (Just Nowhere) JustificationEmpty)
-
-freshTakeLemma :: Lemma
-freshTakeLemma =
- Lemma [Asm (makeExists ["x"] (var "x" `eq` var "b"))] (var "b" `eq` var "b")
-
-freshTakeProof :: Proof
-freshTakeProof =
- Take Nowhere ("y" :| []) (var "y" `eq` var "b") JustificationLocal (Qed (Just Nowhere) JustificationEmpty)
-
-unsoundDisjunctionAssumeBlocks :: [Block]
-unsoundDisjunctionAssumeBlocks =
- [ BlockAxiom Nowhere "membership_asymmetry"
- (Axiom [] (membershipXY `Implies` Not Nowhere membershipYX))
- , BlockLemma Nowhere "membership_totality"
- (Lemma [] (membershipXY `Or` membershipYX))
- , BlockProof Nowhere Nowhere
- (Assume Nowhere membershipXY
- (Qed (Just Nowhere)
- (JustificationRef ("membership_asymmetry" :| []))))
- ]
- where
- membershipXY = var "x" `isElementOf` var "y"
- membershipYX = var "y" `isElementOf` var "x"
-
-structCarrierRewriteBlocks :: [Block]
-structCarrierRewriteBlocks =
- [ fooStructBlock "foo_struct" [("foo_rule", makeForall ["x"] ((var "x" `isElementOf` var "A") `Implies` (var "x" `isElementOf` var "A")))]
- , BlockLemma Nowhere "foo_test" (Lemma [AsmStruct "A" fooStruct, Asm (var "x" `isElementOf` var "A")] (var "x" `isElementOf` var "A"))
- , BlockProof Nowhere Nowhere (Qed (Just Nowhere) (JustificationRef ("foo_rule" :| [])))
- ]
-
-structOperationRewriteBlocks :: [Block]
-structOperationRewriteBlocks =
- [ fooStructBlock "foo_op_struct" [("foo_op_rule", TermSymbolStruct fooOp Nothing `isElementOf` var "A")]
- , BlockLemma Nowhere "foo_op_test" (Lemma [AsmStruct "A" fooStruct] (TermSymbolStruct fooOp Nothing `isElementOf` var "A"))
- , BlockProof Nowhere Nowhere (Qed (Just Nowhere) (JustificationRef ("foo_op_rule" :| [])))
- ]
-
-unresolvedStructOperationBlocks :: [Block]
-unresolvedStructOperationBlocks =
- [ fooStructBlock "unresolved_structure_definition" []
- , BlockAxiom
- structureTermErrorLocation
- "unresolved_structure_operation"
- (Axiom []
- (TermSymbolStruct fooOp Nothing
- `eq` TermSymbolStruct fooOp Nothing))
- ]
-
-nestedStructComprehensionBlocks :: [Block]
-nestedStructComprehensionBlocks =
- [ fooStructBlock "nested_structure_definition" []
- , BlockAxiom
- structureTermErrorLocation
- "nested_structure_comprehension"
- (Axiom []
- (nestedOperation `eq` nestedOperation))
- ]
- where
- nestedOperation =
- TermSymbolStruct
- fooOp
- (Just
- (TermSep
- "x"
- emptySet
- (toScope Top)))
-
-structureTermErrorLocation :: Location
-structureTermErrorLocation =
- mkLocation (FileId 50) 7 1
-
-structClaimIntroducesContextBlocks :: [Block]
-structClaimIntroducesContextBlocks =
- [ fooStructBlock "foo_claim_struct" []
- , BlockLemma Nowhere "foo_claim_test" (Lemma [] ((var "A" `eq` var "A") `And` (var "x" `eq` var "x")))
- , BlockProof Nowhere Nowhere $
- Have Nowhere (fooStructPredicate "A") JustificationEmpty $
- Have Nowhere (var "x" `isElementOf` var "A") JustificationEmpty (Omitted Nowhere)
- ]
-
-boundStructLabelBlocks :: [Block]
-boundStructLabelBlocks =
- [ fooStructBlock "foo_bound_struct" []
- , BlockLemma Nowhere "foo_bound_test" (Lemma [AsmStruct "A" fooStruct] (makeForall ["A"] (var "x" `isElementOf` var "A")))
- , BlockProof Nowhere Nowhere (Qed (Just Nowhere) JustificationEmpty)
- ]
-
-fooStructBlock :: Marker -> [(Marker, Formula)] -> Block
-fooStructBlock marker assumes =
- BlockStruct Nowhere marker (fooStructDefn assumes)
-
-fooStructDefn :: [(Marker, Formula)] -> StructDefn
-fooStructDefn assumes =
- StructDefn
- { structPhrase = fooStruct
- , structParents = Set.singleton _Onesorted
- , structDefnLabel = "A"
- , structDefnFixes = Set.singleton fooOp
- , structDefnAssumes = assumes
- }
-
-testStructBlock
- :: Marker
- -> StructPhrase
- -> Set StructPhrase
- -> [(Marker, Formula)]
- -> Block
-testStructBlock marker phrase parents assumes =
- BlockStruct Nowhere marker StructDefn
- { structPhrase = phrase
- , structParents = parents
- , structDefnLabel = "A"
- , structDefnFixes = mempty
- , structDefnAssumes = assumes
- }
-
-fooStruct :: StructPhrase
-fooStruct =
- mkLexicalItemSgPl (unsafeReadPhraseSgPl "foo[/s]") "foo"
-
-childStruct :: StructPhrase
-childStruct =
- mkLexicalItemSgPl
- (unsafeReadPhraseSgPl "child[/s]")
- "child"
-
-unknownStruct :: StructPhrase
-unknownStruct =
- mkLexicalItemSgPl
- (unsafeReadPhraseSgPl "unknown[/s]")
- "unknown"
-
-fooOp :: StructSymbol
-fooOp =
- StructSymbol "fooop"
-
-fooStructPredicate :: VarSymbol -> Formula
-fooStructPredicate x =
- TermSymbol Nowhere (SymbolPredicate (PredicateNounStruct fooStruct)) [TermVar x]
-
-hiddenSelfReferentialStructBlocks :: [Block]
-hiddenSelfReferentialStructBlocks =
- [ BlockAbbr Nowhere "struct_alias_a"
- ( Abbreviation
- (SymbolPredicate structAliasA)
- (toScope
- (TermSymbol
- Nowhere
- (SymbolPredicate (PredicateNounStruct fooStruct))
- [TermVar (B 0)]))
- )
- , BlockAbbr Nowhere "struct_alias_b"
- ( Abbreviation
- (SymbolPredicate structAliasB)
- (toScope
- (TermSymbol
- Nowhere
- (SymbolPredicate structAliasA)
- [TermVar (B 0)]))
- )
- , fooStructBlock
- "hidden_self_struct"
- [("hidden_self_rule", structAliasFormula structAliasB (var "A"))]
- ]
-
-structAliasA :: Predicate
-structAliasA =
- PredicateSymbol "struct_alias_a"
-
-structAliasB :: Predicate
-structAliasB =
- PredicateSymbol "struct_alias_b"
-
-structAliasFormula :: Predicate -> Term -> Formula
-structAliasFormula predicate term =
- TermSymbol Nowhere (SymbolPredicate predicate) [term]
-
-var :: VarSymbol -> Term
-var = TermVar
-
-emptySet :: Term
-emptySet = EmptySet Nowhere
-
-eq :: Term -> Term -> Formula
-eq = Equals Nowhere
-
-neq :: Term -> Term -> Formula
-neq = NotEquals Nowhere
-
-directSelfReferentialAbbrBlocks :: [Block]
-directSelfReferentialAbbrBlocks =
- [ BlockAbbr Nowhere "bad_abbr_direct" (Abbreviation abbrSymbolA (toScope (TermSymbol Nowhere abbrSymbolA [])))
- ]
-
-indirectSelfReferentialAbbrBlocks :: [Block]
-indirectSelfReferentialAbbrBlocks =
- [ BlockAbbr Nowhere "bad_abbr_indirect_a" (Abbreviation abbrSymbolA (toScope (TermSymbol Nowhere abbrSymbolB [])))
- , BlockAbbr Nowhere "bad_abbr_indirect_b" (Abbreviation abbrSymbolB (toScope (TermSymbol Nowhere abbrSymbolA [])))
- ]
-
-directSelfReferentialPredicateDefinitionBlocks :: [Block]
-directSelfReferentialPredicateDefinitionBlocks =
- [ BlockDefn Nowhere "bad_predicate_definition_direct"
- ( DefnPredicate
- []
- definitionTestPredicate
- ("x" :| [])
- (Not Nowhere (definitionTestPredicateFormula (var "x")))
- )
- ]
-
-directSelfReferentialFunctionDefinitionBlocks :: [Block]
-directSelfReferentialFunctionDefinitionBlocks =
- [ BlockDefn Nowhere "bad_function_definition_direct"
- ( DefnFun
- []
- definitionTestFunction
- ["x"]
- (definitionTestFunctionTerm (var "x"))
- )
- ]
-
-directSelfReferentialOperatorDefinitionBlocks :: [Block]
-directSelfReferentialOperatorDefinitionBlocks =
- [ BlockDefn Nowhere "bad_operator_definition_direct"
- (DefnOp definitionTestOperator ["x"] (termSymbol definitionTestOperator [var "x"]))
- ]
-
-abbreviationHiddenSelfReferentialDefinitionBlocks :: [Block]
-abbreviationHiddenSelfReferentialDefinitionBlocks =
- [ BlockAbbr Nowhere "bad_definition_body_alias"
- ( Abbreviation
- (SymbolMixfix selfDefinitionBodyAlias)
- (toScope (TermSymbol Nowhere (SymbolMixfix definitionTestOperator) [TermVar (B 0)]))
- )
- , BlockDefn Nowhere "bad_definition_body_target"
- (DefnOp definitionTestOperator ["x"] (termSymbol selfDefinitionBodyAlias [var "x"]))
- ]
-
-assumptionHiddenSelfReferentialDefinitionBlocks :: [Block]
-assumptionHiddenSelfReferentialDefinitionBlocks =
- [ BlockAbbr Nowhere "bad_definition_assumption_alias"
- ( Abbreviation
- (SymbolPredicate selfDefinitionAssumptionAlias)
- (toScope (TermSymbol Nowhere (SymbolPredicate definitionTestPredicate) [TermVar (B 0)]))
- )
- , BlockDefn Nowhere "bad_definition_assumption_target"
- ( DefnPredicate
- [Asm (selfDefinitionAssumptionAliasFormula (var "x"))]
- definitionTestPredicate
- ("x" :| [])
- (var "x" `eq` var "x")
- )
- ]
-
-nonRecursiveDefinitionBlocks :: [Block]
-nonRecursiveDefinitionBlocks =
- [ BlockDefn Nowhere "good_predicate_definition"
- (DefnPredicate [] definitionTestPredicate ("x" :| []) (var "x" `eq` var "x"))
- , BlockDefn Nowhere "good_function_definition"
- (DefnFun [] definitionTestFunction ["x"] emptySet)
- , BlockDefn Nowhere "good_operator_definition"
- (DefnOp definitionTestOperator ["x"] emptySet)
- ]
-
-definitionTestPredicate :: Predicate
-definitionTestPredicate =
- PredicateSymbol "definition_test_predicate"
-
-definitionTestPredicateFormula :: Term -> Formula
-definitionTestPredicateFormula expr =
- TermSymbol Nowhere (SymbolPredicate definitionTestPredicate) [expr]
-
-definitionTestFunction :: LexicalItemSgPl
-definitionTestFunction =
- mkLexicalItemSgPl
- (unsafeReadPhraseSgPl "definition test function[/s] of ?")
- "definition_test_function"
-
-definitionTestFunctionTerm :: Term -> Term
-definitionTestFunctionTerm expr =
- TermSymbol Nowhere (SymbolFun definitionTestFunction) [expr]
-
-definitionTestOperator :: FunctionSymbol
-definitionTestOperator =
- unarySymbol "definition_test_operator"
-
-selfDefinitionBodyAlias :: FunctionSymbol
-selfDefinitionBodyAlias =
- unarySymbol "self_definition_body_alias"
-
-selfDefinitionAssumptionAlias :: Predicate
-selfDefinitionAssumptionAlias =
- PredicateSymbol "self_definition_assumption_alias"
-
-selfDefinitionAssumptionAliasFormula :: Term -> Formula
-selfDefinitionAssumptionAliasFormula expr =
- TermSymbol Nowhere (SymbolPredicate selfDefinitionAssumptionAlias) [expr]
-
-builtinMixfixMarkerCollisionBlock :: Block
-builtinMixfixMarkerCollisionBlock =
- BlockDefn Nowhere "pow" (DefnOp powHijackSym ["A"] emptySet)
-
-powHijackSym :: FunctionSymbol
-powHijackSym =
- mkMixfixItem
- [Just (Command "powhijack"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR]
- "pow"
- NonAssoc
-
-builtinPredicateMarkerCollisionBlock :: Block
-builtinPredicateMarkerCollisionBlock =
- BlockDefn Nowhere "elem"
- ( DefnPredicate
- []
- (PredicateRelation
- (RelationSymbol
- (Command "elemhijack")
- zeroParameterArity
- "elem"))
- ("A" :| ["B"])
- (var "A" `eq` var "B")
- )
-
-builtinAbbreviationMarkerCollisionBlock :: Block
-builtinAbbreviationMarkerCollisionBlock =
- BlockAbbr Nowhere "pow"
- ( Abbreviation
- (SymbolMixfix (constSymbolWithMarker "powabbr" "pow"))
- (toScope (TermSymbol Nowhere (SymbolInteger 0) []))
- )
-
-builtinMarkerProofLabelBlock :: Block
-builtinMarkerProofLabelBlock =
- BlockAxiom Nowhere "pow" (Axiom [] (emptySet `eq` emptySet))
-
-subseteqDefinitionBlock :: Block
-subseteqDefinitionBlock =
- BlockDefn Nowhere "subseteq"
- ( DefnPredicate
- []
- (PredicateRelation SubseteqSymbol)
- ("A" :| ["B"])
- (var "A" `eq` var "B")
- )
-
-goodDatatypeBlock :: Block
-goodDatatypeBlock =
- datatypeBlock "good_datatype" goodDatatypeClauses
-
-directRecursionAliasDatatypeBlocks :: [Block]
-directRecursionAliasDatatypeBlocks =
- [ closedDatatypeAliasBlock
- "direct_recursion_alias"
- directRecursionAliasSym
- (closedTermSymbol propformSym [])
- , datatypeBlock
- "aliased_recursive_datatype"
- ( DatatypeClause
- (SymbolPattern propbotSym [])
- []
- :| [ DatatypeClause
- (SymbolPattern propvarSym ["n"])
- [("n", naturalsTerm)]
- , DatatypeClause
- (SymbolPattern proptoSym ["p", "q"])
- [ ("p", termSymbol directRecursionAliasSym [])
- , ("q", termSymbol directRecursionAliasSym [])
- ]
- ]
- )
- ]
-
-oneHopPowersetAliasDatatypeBlocks :: [Block]
-oneHopPowersetAliasDatatypeBlocks =
- [ closedDatatypeAliasBlock
- "powerset_recursion_alias"
- powersetRecursionAliasSym
- ( closedTermSymbol
- powSym
- [closedTermSymbol propformSym []]
- )
- , datatypeBlock
- "one_hop_powerset_recursive_datatype"
- ( DatatypeClause
- (SymbolPattern propvarSym ["n"])
- [("n", termSymbol powersetRecursionAliasSym [])]
- :| []
- )
- ]
-
-multiHopPowersetAliasDatatypeBlocks :: [Block]
-multiHopPowersetAliasDatatypeBlocks =
- [ closedDatatypeAliasBlock
- "powerset_recursion_alias"
- powersetRecursionAliasSym
- ( closedTermSymbol
- powSym
- [closedTermSymbol propformSym []]
- )
- , closedDatatypeAliasBlock
- "indirect_powerset_recursion_alias"
- indirectPowersetRecursionAliasSym
- (closedTermSymbol powersetRecursionAliasSym [])
- , datatypeBlock
- "multi_hop_powerset_recursive_datatype"
- ( DatatypeClause
- (SymbolPattern propvarSym ["n"])
- [("n", termSymbol indirectPowersetRecursionAliasSym [])]
- :| []
- )
- ]
-
-closedDatatypeAliasBlock
- :: Marker
- -> FunctionSymbol
- -> ExprOf (Var Int Void)
- -> Block
-closedDatatypeAliasBlock marker symbol body =
- BlockAbbr
- Nowhere
- marker
- (Abbreviation (SymbolMixfix symbol) (toScope body))
-
-closedTermSymbol
- :: FunctionSymbol
- -> [ExprOf (Var Int Void)]
- -> ExprOf (Var Int Void)
-closedTermSymbol symbol =
- TermSymbol Nowhere (SymbolMixfix symbol)
-
-datatypeGeneratedMarkers :: [Marker]
-datatypeGeneratedMarkers =
- [ "propform_propbot_intro"
- , "propform_propvar_intro"
- , "propform_propto_intro"
- , "propform_propbot_propvar_distinct"
- , "propform_propbot_propto_distinct"
- , "propform_propvar_propto_distinct"
- , "propform_propvar_injective"
- , "propform_propto_injective"
- , "propform_cases"
- , "propform_induct"
- ]
-
-datatypeIntroReferenceBlocks :: [Block]
-datatypeIntroReferenceBlocks =
- [ goodDatatypeBlock
- , BlockLemma Nowhere "datatype_propbot_intro_ref"
- (Lemma [] (propbotTerm `isElementOf` propformTerm))
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("propform_propbot_intro" :| [])))
- , BlockLemma Nowhere "datatype_propvar_intro_ref"
- (Lemma [Asm (var "n" `isElementOf` naturalsTerm)] (termSymbol propvarSym [var "n"] `isElementOf` propformTerm))
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("propform_propvar_intro" :| [])))
- , BlockLemma Nowhere "datatype_propto_intro_ref"
- (Lemma [Asm (propbotTerm `isElementOf` propformTerm)] (proptoTerm propbotTerm propbotTerm `isElementOf` propformTerm))
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("propform_propto_intro" :| [])))
- ]
-
-datatypeDistinctReferenceBlocks :: [Block]
-datatypeDistinctReferenceBlocks =
- [ goodDatatypeBlock
- , BlockLemma Nowhere "datatype_distinct_ref"
- (Lemma [] (propbotTerm `neq` proptoTerm propbotTerm propbotTerm))
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("propform_propbot_propto_distinct" :| [])))
- ]
-
-datatypeInjectiveReferenceBlocks :: [Block]
-datatypeInjectiveReferenceBlocks =
- [ goodDatatypeBlock
- , BlockLemma Nowhere "datatype_injective_ref"
- (Lemma [] (makeForall ["m", "n"] ((termSymbol propvarSym [var "m"] `eq` termSymbol propvarSym [var "n"]) `Implies` (var "m" `eq` var "n"))))
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("propform_propvar_injective" :| [])))
- ]
-
-datatypeGeneratedMarkerReuseBlocks :: [Block]
-datatypeGeneratedMarkerReuseBlocks =
- [ goodDatatypeBlock
- , BlockLemma Nowhere "propform_cases" (Lemma [] Top)
- ]
-
-badDuplicateConstructorMarkerDatatypeBlock :: Block
-badDuplicateConstructorMarkerDatatypeBlock =
- datatypeBlock "propform"
- ( DatatypeClause (SymbolPattern (unarySymbol "dup") ["n"]) [("n", naturalsTerm)] :|
- [ DatatypeClause (SymbolPattern (infixSymbol "dup") ["p", "q"]) [("p", propformTerm), ("q", propformTerm)]
- ]
- )
-
-badNestedRecursiveDatatypeBlock :: Block
-badNestedRecursiveDatatypeBlock =
- datatypeBlock "bad_nested_recursive_datatype"
- (DatatypeClause (SymbolPattern proptoSym ["p", "q"]) [("p", wrapPropformTerm), ("q", propformTerm)] :| [])
-
-badMissingPremiseDatatypeBlock :: Block
-badMissingPremiseDatatypeBlock =
- datatypeBlock "bad_missing_premise_datatype"
- (DatatypeClause (SymbolPattern propvarSym ["n"]) [] :| [])
-
-badDuplicateConstructorDatatypeBlock :: Block
-badDuplicateConstructorDatatypeBlock =
- datatypeBlock "bad_duplicate_constructor_datatype"
- ( DatatypeClause (SymbolPattern propbotSym []) [] :|
- [ DatatypeClause (SymbolPattern propbotSym []) []
- ]
- )
-
-badOpenDomainDatatypeBlock :: Block
-badOpenDomainDatatypeBlock =
- datatypeBlock "bad_open_domain_datatype"
- (DatatypeClause (SymbolPattern propvarSym ["n"]) [("n", TermVar "A")] :| [])
-
-badApplyConstructorDatatypeBlock :: Block
-badApplyConstructorDatatypeBlock =
- datatypeBlock "bad_apply_constructor_datatype"
- (DatatypeClause (SymbolPattern ApplySymbol ["f", "x"]) [("f", naturalsTerm), ("x", naturalsTerm)] :| [])
-
-goodInductiveBlock :: Block
-goodInductiveBlock =
- BlockInductive Nowhere "fin" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = powTerm (var "A")
- , inductiveIntros =
- IntroRule [] (emptySet `isElementOf` finTerm (var "A")) :|
- [ IntroRule
- [ var "a" `isElementOf` var "A"
- , var "B" `isElementOf` finTerm (var "A")
- ]
- (consTerm (var "a") (var "B") `isElementOf` finTerm (var "A"))
- ]
- }
-
-goodInductiveBlocks :: [Block]
-goodInductiveBlocks =
- [ goodInductiveBlock
- ]
-
-goodMonotoneInductiveBlock :: Block
-goodMonotoneInductiveBlock =
- BlockInductive Nowhere "acc" Inductive
- { inductiveSymbol = accSym
- , inductiveParams = ["R"]
- , inductiveDomain = wrapTerm (var "R")
- , inductiveIntros =
- IntroRule
- [ var "x" `isElementOf` wrapTerm (accTerm (var "R")) ]
- (var "x" `isElementOf` accTerm (var "R"))
- :| []
- }
-
-goodMonotoneInductiveBlocks :: [Block]
-goodMonotoneInductiveBlocks =
- [ wrapSignatureBlock
- , goodMonotoneInductiveBlock
- ]
-
-inductiveGeneratedMarkers :: [Marker]
-inductiveGeneratedMarkers =
- [ "fin_intro_1"
- , "fin_intro_2"
- , "fin_dom_subset"
- , "fin_cases"
- , "fin_induct"
- ]
-
-inductiveIntroAndDomainReferenceBlocks :: [Block]
-inductiveIntroAndDomainReferenceBlocks =
- goodInductiveBlocks
- <> [ BlockLemma Nowhere "inductive_intro_ref"
- (Lemma [] (makeForall ["A"] (emptySet `isElementOf` finTerm (var "A"))))
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("fin_intro_1" :| [])))
- , BlockLemma Nowhere "inductive_dom_subset_ref"
- (Lemma [] $
- makeForall ["A"] $
- semanticSubsetFormula (Set.fromList ["A"]) (finTerm (var "A")) (powTerm (var "A")))
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("fin_dom_subset" :| [])))
- ]
-
-inductiveCasesReferenceBlocks :: [Block]
-inductiveCasesReferenceBlocks =
- goodInductiveBlocks
- <> [ BlockLemma Nowhere "inductive_cases_ref"
- (Lemma [] finCasesFormula)
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("fin_cases" :| [])))
- ]
-
-inductiveInductReferenceBlocks :: [Block]
-inductiveInductReferenceBlocks =
- goodInductiveBlocks
- <> [ BlockLemma Nowhere "inductive_induct_ref"
- (Lemma [] finInductFormula)
- , BlockProof Nowhere Nowhere
- (Qed (Just Nowhere) (JustificationRef ("fin_induct" :| [])))
- ]
-
-duplicateInductiveCarrierBlocks :: [Block]
-duplicateInductiveCarrierBlocks =
- goodInductiveBlocks
- <> [ BlockInductive Nowhere "fin_again" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = wrapTerm (var "A")
- , inductiveIntros =
- IntroRule [] (emptySet `isElementOf` finTerm (var "A")) :| []
- }
- ]
-
-operatorThenInductiveBlocks :: [Block]
-operatorThenInductiveBlocks =
- [ BlockDefn Nowhere "fin_operator_definition" (DefnOp finSym ["A"] emptySet)
- , goodInductiveBlock
- ]
-
-signaturePredicateUsageBlocks :: [Block]
-signaturePredicateUsageBlocks =
- [ BlockSig Nowhere "sig_predicate" [] (SignaturePredicate signaturePredicate ("x" :| []))
- , BlockLemma Nowhere "sig_predicate_use"
- (Lemma [] (makeForall ["x"] (signaturePredicateFormula (var "x") `Implies` signaturePredicateFormula (var "x"))))
- ]
-
-signatureFormulaUsageBlocks :: [Block]
-signatureFormulaUsageBlocks =
- [ BlockSig Nowhere "sig_formula" [] (SignatureFormula recoverableSignatureFormula)
- , BlockLemma Nowhere "sig_formula_use"
- (Lemma [] (makeForall ["A"] (signatureDeclaredTerm (var "A") `eq` signatureDeclaredTerm (var "A"))))
- ]
-
-badSignatureFormulaBlock :: Block
-badSignatureFormulaBlock =
- BlockSig Nowhere "bad_signature_formula" [] (SignatureFormula Top)
-
-priorInductiveCarrierAxiomBlocks :: [Block]
-priorInductiveCarrierAxiomBlocks =
- [ BlockAxiom Nowhere "pre_fin_axiom" (Axiom [] (emptySet `isElementOf` finTerm emptySet))
- , goodInductiveBlock
- ]
-
-badInductiveSelfDomainBlock :: Block
-badInductiveSelfDomainBlock =
- BlockInductive Nowhere "bad_inductive_self_domain" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = finTerm (var "A")
- , inductiveIntros =
- IntroRule [] (emptySet `isElementOf` finTerm (var "A")) :| []
- }
-
-hiddenSelfDomainBlocks :: [Block]
-hiddenSelfDomainBlocks =
- [ BlockAbbr Nowhere "hidden_self_domain_abbr"
- (Abbreviation
- (SymbolMixfix hiddenSelfDomainSym)
- (toScope (TermSymbol Nowhere (SymbolMixfix finSym) [TermVar (B 0)])))
- , BlockInductive Nowhere "hidden_self_domain_inductive" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = hiddenSelfDomainTerm (var "A")
- , inductiveIntros =
- IntroRule [] (emptySet `isElementOf` finTerm (var "A")) :| []
- }
- ]
-
-hiddenDefinitionDomainBlocks :: [Block]
-hiddenDefinitionDomainBlocks =
- [ BlockDefn Nowhere "ordinary_domain_alias_definition" (DefnOp ordinaryDomainAliasSym ["A"] (finTerm (var "A")))
- , BlockInductive Nowhere "ordinary_definition_hidden_domain_inductive" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = ordinaryDomainAliasTerm (var "A")
- , inductiveIntros =
- IntroRule [] (emptySet `isElementOf` finTerm (var "A")) :| []
- }
- ]
-
-hiddenCarrierSideConditionBlocks :: [Block]
-hiddenCarrierSideConditionBlocks =
- [ BlockDefn Nowhere "hidden_carrier_definition" (DefnOp hiddenCarrierSym ["A"] (finTerm (var "A")))
- , BlockInductive Nowhere "ordinary_definition_hidden_side_condition_inductive" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = powTerm (var "A")
- , inductiveIntros =
- IntroRule
- [ var "x" `isElementOf` hiddenCarrierTerm (var "A") ]
- (emptySet `isElementOf` finTerm (var "A"))
- :| []
- }
- ]
-
-priorDatatypeHeadSignatureBlocks :: [Block]
-priorDatatypeHeadSignatureBlocks =
- [ BlockSig Nowhere "pre_propform_signature" [] (SignatureFormula propformSignatureFormula)
- , goodDatatypeBlock
- ]
-
-priorDatatypeConstructorLemmaBlocks :: [Block]
-priorDatatypeConstructorLemmaBlocks =
- [ BlockLemma Nowhere "pre_propbot_lemma" (Lemma [] (propbotTerm `eq` propbotTerm))
- , goodDatatypeBlock
- ]
-
-datatypeConstructorThenOperatorBlocks :: [Block]
-datatypeConstructorThenOperatorBlocks =
- [ goodDatatypeBlock
- , BlockDefn Nowhere "propbot_operator_definition" (DefnOp propbotSym [] emptySet)
- ]
-
-frozenSymbolDefinitionBlocks :: [Block]
-frozenSymbolDefinitionBlocks =
- [ laterSignatureBlock
- , freezingInductiveBlock
- , BlockDefn Nowhere "later_operator_definition" (DefnOp laterSym ["A"] emptySet)
- ]
-
-freezingInductiveBlock :: Block
-freezingInductiveBlock =
- BlockInductive Nowhere "freeze_inductive" Inductive
- { inductiveSymbol = freezeCarrierSym
- , inductiveParams = ["A"]
- , inductiveDomain = powTerm (var "A")
- , inductiveIntros =
- IntroRule
- [ var "x" `eq` laterTerm (var "A") ]
- (emptySet `isElementOf` freezeCarrierTerm (var "A"))
- :| []
- }
-
-canonicalizedDomainFreezeBlocks :: [Block]
-canonicalizedDomainFreezeBlocks =
- [ laterSignatureBlock
- , BlockAbbr Nowhere "domain_alias_abbr"
- (Abbreviation
- (SymbolMixfix domainAliasSym)
- (toScope (TermSymbol Nowhere (SymbolMixfix laterSym) [TermVar (B 0)])))
- , BlockInductive Nowhere "canonicalized_domain_freeze_inductive" Inductive
- { inductiveSymbol = freezeCarrierSym
- , inductiveParams = ["A"]
- , inductiveDomain = domainAliasTerm (var "A")
- , inductiveIntros =
- IntroRule [] (emptySet `isElementOf` freezeCarrierTerm (var "A")) :| []
- }
- , BlockDefn Nowhere "later_operator_definition_after_canonicalized_domain" (DefnOp laterSym ["A"] emptySet)
- ]
-
-transitiveFrozenDefinitionBlocks :: [Block]
-transitiveFrozenDefinitionBlocks =
- [ laterSignatureBlock
- , BlockDefn Nowhere "middle_later_alias_definition" (DefnOp middleLaterAliasSym ["A"] (laterTerm (var "A")))
- , BlockDefn Nowhere "indirect_later_alias_definition" (DefnOp indirectLaterAliasSym ["A"] (middleLaterAliasTerm (var "A")))
- , BlockInductive Nowhere "transitive_freeze_inductive" Inductive
- { inductiveSymbol = freezeCarrierSym
- , inductiveParams = ["A"]
- , inductiveDomain = powTerm (var "A")
- , inductiveIntros =
- IntroRule
- [ var "x" `isElementOf` indirectLaterAliasTerm (var "A") ]
- (emptySet `isElementOf` freezeCarrierTerm (var "A"))
- :| []
- }
- , BlockDefn Nowhere "later_operator_definition_after_transitive_freeze" (DefnOp laterSym ["A"] emptySet)
- ]
-
-badRecursiveTermInductiveBlock :: Block
-badRecursiveTermInductiveBlock =
- BlockInductive Nowhere "bad_recursive_term_inductive" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = powTerm (var "A")
- , inductiveIntros =
- IntroRule
- [ finTerm (var "A") `isElementOf` powTerm (var "A") ]
- (emptySet `isElementOf` finTerm (var "A"))
- :| []
- }
-
-badRecursiveFormulaInductiveBlock :: Block
-badRecursiveFormulaInductiveBlock =
- BlockInductive Nowhere "bad_recursive_formula_inductive" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = powTerm (var "A")
- , inductiveIntros =
- IntroRule
- [ Not Nowhere (emptySet `isElementOf` finTerm (var "A")) ]
- (emptySet `isElementOf` finTerm (var "A"))
- :| []
- }
-
-badInductiveResultBlock :: Block
-badInductiveResultBlock =
- BlockInductive Nowhere "bad_inductive_result" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = powTerm (var "A")
- , inductiveIntros =
- IntroRule [] (emptySet `isElementOf` powTerm (var "A")) :| []
- }
-
-badInductiveWrongArgsBlock :: Block
-badInductiveWrongArgsBlock =
- BlockInductive Nowhere "bad_inductive_wrong_args" Inductive
- { inductiveSymbol = finSym
- , inductiveParams = ["A"]
- , inductiveDomain = powTerm (var "A")
- , inductiveIntros =
- IntroRule
- [ var "B" `isElementOf` finTerm (var "B") ]
- (emptySet `isElementOf` finTerm (var "A"))
- :| []
- }
-
-finCasesFormula :: Formula
-finCasesFormula =
- makeForall ["A", "x"]
- ((var "x" `isElementOf` finTerm (var "A")) `Implies` makeDisjunction
- [ var "x" `eq` emptySet
- , makeExists ["a", "B"]
- (makeConjunction
- [ var "a" `isElementOf` var "A"
- , var "B" `isElementOf` finTerm (var "A")
- , var "x" `eq` consTerm (var "a") (var "B")
- ])
- ])
-
-finInductFormula :: Formula
-finInductFormula =
- makeForall ["A", "S"]
- (makeConjunction
- [ emptySet `isElementOf` var "S"
- , makeForall ["a", "B"]
- ((makeConjunction
- [ var "a" `isElementOf` var "A"
- , var "B" `isElementOf` var "S"
- ])
- `Implies`
- (consTerm (var "a") (var "B") `isElementOf` var "S"))
- ]
- `Implies`
- semanticSubsetFormula
- (Set.fromList ["A", "S"])
- (finTerm (var "A"))
- (var "S"))
-
-goodDatatypeClauses :: NonEmpty DatatypeClause
-goodDatatypeClauses =
- DatatypeClause (SymbolPattern propbotSym []) [] :|
- [ DatatypeClause (SymbolPattern propvarSym ["n"]) [("n", naturalsTerm)]
- , DatatypeClause (SymbolPattern proptoSym ["p", "q"]) [("p", propformTerm), ("q", propformTerm)]
- ]
-
-datatypeBlock :: Marker -> NonEmpty DatatypeClause -> Block
-datatypeBlock marker clauses =
- BlockData Nowhere marker (Datatype (SymbolPattern propformSym []) clauses)
-
-propformTerm :: Term
-propformTerm =
- termSymbol propformSym []
-
-propbotTerm :: Term
-propbotTerm =
- termSymbol propbotSym []
-
-naturalsTerm :: Term
-naturalsTerm =
- termSymbol naturalsSym []
-
-wrapPropformTerm :: Term
-wrapPropformTerm =
- termSymbol wrapSym [propformTerm]
-
-powTerm :: Term -> Term
-powTerm expr =
- termSymbol powSym [expr]
-
-finTerm :: Term -> Term
-finTerm expr =
- termSymbol finSym [expr]
-
-accTerm :: Term -> Term
-accTerm expr =
- termSymbol accSym [expr]
-
-wrapTerm :: Term -> Term
-wrapTerm expr =
- termSymbol wrapSym [expr]
-
-laterTerm :: Term -> Term
-laterTerm expr =
- termSymbol laterSym [expr]
-
-freezeCarrierTerm :: Term -> Term
-freezeCarrierTerm expr =
- termSymbol freezeCarrierSym [expr]
-
-domainAliasTerm :: Term -> Term
-domainAliasTerm expr =
- termSymbol domainAliasSym [expr]
-
-hiddenSelfDomainTerm :: Term -> Term
-hiddenSelfDomainTerm expr =
- termSymbol hiddenSelfDomainSym [expr]
-
-ordinaryDomainAliasTerm :: Term -> Term
-ordinaryDomainAliasTerm expr =
- termSymbol ordinaryDomainAliasSym [expr]
-
-hiddenCarrierTerm :: Term -> Term
-hiddenCarrierTerm expr =
- termSymbol hiddenCarrierSym [expr]
-
-middleLaterAliasTerm :: Term -> Term
-middleLaterAliasTerm expr =
- termSymbol middleLaterAliasSym [expr]
-
-indirectLaterAliasTerm :: Term -> Term
-indirectLaterAliasTerm expr =
- termSymbol indirectLaterAliasSym [expr]
-
-signatureDeclaredTerm :: Term -> Term
-signatureDeclaredTerm expr =
- termSymbol signatureDeclaredSym [expr]
-
-signaturePredicateFormula :: Term -> Formula
-signaturePredicateFormula expr =
- TermSymbol Nowhere (SymbolPredicate signaturePredicate) [expr]
-
-recoverableSignatureFormula :: Formula
-recoverableSignatureFormula =
- makeForall ["z"]
- ((var "z" `eq` signatureDeclaredTerm (var "A")) `Implies` (var "z" `eq` var "z"))
-
-propformSignatureFormula :: Formula
-propformSignatureFormula =
- makeForall ["z"]
- ((var "z" `eq` propformTerm) `Implies` (var "z" `eq` var "z"))
-
-wrapSignatureBlock :: Block
-wrapSignatureBlock =
- mixfixSignatureBlock "wrap_signature" wrapSym ["A"]
-
-laterSignatureBlock :: Block
-laterSignatureBlock =
- mixfixSignatureBlock "later_signature" laterSym ["A"]
-
-mixfixSignatureBlock :: Marker -> FunctionSymbol -> [VarSymbol] -> Block
-mixfixSignatureBlock marker symbol args =
- BlockSig Nowhere marker [] (SignatureFormula (recoverableMixfixSignatureFormula symbol args))
-
-recoverableMixfixSignatureFormula :: FunctionSymbol -> [VarSymbol] -> Formula
-recoverableMixfixSignatureFormula symbol args =
- makeForall ["z"]
- ((var "z" `eq` termSymbol symbol (var <$> args)) `Implies` (var "z" `eq` var "z"))
-
-consTerm :: Term -> Term -> Term
-consTerm left right =
- termSymbol consSym [left, right]
-
-termSymbol :: FunctionSymbol -> [Term] -> Term
-termSymbol sym args =
- TermSymbol Nowhere (SymbolMixfix sym) args
-
-proptoTerm :: Term -> Term -> Term
-proptoTerm left right =
- termSymbol proptoSym [left, right]
-
-propformSym :: FunctionSymbol
-propformSym =
- constSymbol "propform"
-
-propbotSym :: FunctionSymbol
-propbotSym =
- constSymbol "propbot"
-
-propvarSym :: FunctionSymbol
-propvarSym =
- unarySymbol "propvar"
-
-proptoSym :: FunctionSymbol
-proptoSym =
- infixSymbol "propto"
-
-directRecursionAliasSym :: FunctionSymbol
-directRecursionAliasSym =
- constSymbol "directrecursionalias"
-
-powersetRecursionAliasSym :: FunctionSymbol
-powersetRecursionAliasSym =
- constSymbol "powersetrecursionalias"
-
-indirectPowersetRecursionAliasSym :: FunctionSymbol
-indirectPowersetRecursionAliasSym =
- constSymbol "indirectpowersetrecursionalias"
-
-naturalsSym :: FunctionSymbol
-naturalsSym =
- constSymbol "naturals"
-
-powSym :: FunctionSymbol
-powSym =
- unarySymbol "pow"
-
-finSym :: FunctionSymbol
-finSym =
- unarySymbol "fin"
-
-accSym :: FunctionSymbol
-accSym =
- unarySymbol "acc"
-
-consSym :: FunctionSymbol
-consSym =
- ConsSymbol
-
-wrapSym :: FunctionSymbol
-wrapSym =
- unarySymbol "wrap"
-
-laterSym :: FunctionSymbol
-laterSym =
- unarySymbol "later"
-
-freezeCarrierSym :: FunctionSymbol
-freezeCarrierSym =
- unarySymbol "freezecarrier"
-
-domainAliasSym :: FunctionSymbol
-domainAliasSym =
- unarySymbol "domainalias"
-
-hiddenSelfDomainSym :: FunctionSymbol
-hiddenSelfDomainSym =
- unarySymbol "hiddenselfdomain"
-
-ordinaryDomainAliasSym :: FunctionSymbol
-ordinaryDomainAliasSym =
- unarySymbol "ordinarydomainalias"
-
-hiddenCarrierSym :: FunctionSymbol
-hiddenCarrierSym =
- unarySymbol "hiddencarrier"
-
-middleLaterAliasSym :: FunctionSymbol
-middleLaterAliasSym =
- unarySymbol "middlelateralias"
-
-indirectLaterAliasSym :: FunctionSymbol
-indirectLaterAliasSym =
- unarySymbol "indirectlateralias"
-
-signatureDeclaredSym :: FunctionSymbol
-signatureDeclaredSym =
- unarySymbol "signaturedeclared"
-
-signaturePredicate :: Predicate
-signaturePredicate =
- PredicateSymbol "signaturepredicate"
-
-constSymbol :: Text -> FunctionSymbol
-constSymbol name =
- mkMixfixItem [Just (Command name)] (Marker name) NonAssoc
-
-constSymbolWithMarker :: Text -> Marker -> FunctionSymbol
-constSymbolWithMarker name marker =
- mkMixfixItem [Just (Command name)] marker NonAssoc
-
-unarySymbol :: Text -> FunctionSymbol
-unarySymbol name =
- mkMixfixItem [Just (Command name), Just InvisibleBraceL, Nothing, Just InvisibleBraceR] (Marker name) NonAssoc
-
-infixSymbol :: Text -> FunctionSymbol
-infixSymbol name =
- mkMixfixItem [Nothing, Just (Command name), Nothing] (Marker name) NonAssoc
-
-abbrSymbolA :: Symbol
-abbrSymbolA = abbrSymbol "unit_test_abbr_a"
-
-abbrSymbolB :: Symbol
-abbrSymbolB = abbrSymbol "unit_test_abbr_b"
-
-abbrSymbol :: Text -> Symbol
-abbrSymbol name =
- SymbolMixfix (MixfixItem (TokenCons (Command name) End) (Marker name) NonAssoc)
diff --git a/source/Test/Unit/CommandLine.hs b/source/Test/Unit/CommandLine.hs
index ba31934..eeefbc3 100644
--- a/source/Test/Unit/CommandLine.hs
+++ b/source/Test/Unit/CommandLine.hs
@@ -3,10 +3,11 @@
module Test.Unit.CommandLine (unitTests) where
import Base
-import Api (VerificationReport(..), VerificationRoute(..))
+import Api (VerificationReport(..))
import CommandLine
import Felix.Source (safeRelativePath)
import Felix.Store qualified as Store
+import Provers qualified
import Render.Html.Output qualified as HtmlOutput
import Report.Location (pattern Nowhere)
@@ -67,8 +68,7 @@ unitTests =
(exitCode, stdout, stderr) <-
runCliWithSourceAndConfiguredVampire
cliGapSource
- \vampirePath ->
- writeFile vampirePath "not executable"
+ writeNonExecutableFile
exitCode `shouldBe` ExitSuccess
stdout `shouldBe` ""
stderr `shouldContain`
@@ -95,8 +95,7 @@ unitTests =
"UnsuccessfulVampireExit (ExitFailure 7)"
, testCase "prover launch failure exits as infrastructure failure" do
(exitCode, stdout, stderr) <-
- runCliWithConfiguredVampire \vampirePath ->
- writeFile vampirePath "not executable"
+ runCliWithConfiguredVampire writeNonExecutableFile
exitCode `shouldBe` ExitFailure 2
stdout `shouldBe` ""
stderr `shouldContain` "ProverLaunchFailed"
@@ -110,8 +109,13 @@ unitTests =
dumpAndHtmlVerifyOnce
, testCase "semantic failure publishes no HTML"
semanticFailurePublishesNoHtml
+ , testCase "fresh and cached presentation publish equal HTML"
+ freshAndCachedPresentationAgree
, testCase "missing renderer data is a typed failure"
missingRendererDataIsTyped
+ , testCase
+ "post-verification HTML failure retains authorization report"
+ htmlFailureRetainsAuthorizationReport
]
]
@@ -142,6 +146,17 @@ parsesClosedCommands = do
assertFailure
("unexpected default verify parse: "
<> showParserResult other)
+ case parseCommandArguments ["input.tex", "--jobs", "3"] of
+ Success
+ (Verify
+ (Input "input.tex")
+ VerificationOptions
+ { verificationJobsOverride = Just jobs
+ }) ->
+ Provers.effectiveJobsValue jobs `shouldBe` 3
+ other ->
+ assertFailure
+ ("unexpected jobs parse: " <> showParserResult other)
case parseCommandArguments ["input.tex", "--fresh"] of
Success
(Verify
@@ -159,6 +174,7 @@ rejectsConflictingOptions :: Assertion
rejectsConflictingOptions = do
for_
[ ["input.tex", "--parseonly", "--fresh"]
+ , ["input.tex", "--parseonly", "--jobs", "2"]
, ["input.tex", "--parseonly", "--dump", "dump"]
, ["input.tex", "--parseonly", "--html"]
, ["input.tex", "--store", "store.sqlite", "--fresh"]
@@ -173,6 +189,12 @@ rejectsConflictingOptions = do
<> show arguments
<> " as "
<> showParserResult other)
+ case parseCommandArguments ["input.tex", "--jobs", "0"] of
+ Failure _failure -> pure ()
+ other ->
+ assertFailure
+ ("non-positive jobs were accepted as "
+ <> showParserResult other)
showParserResult :: ParserResult Command -> String
showParserResult = \case
@@ -195,10 +217,8 @@ versionNeedsNoInputOrStore =
parseOnlyUsesNoAuthority :: Assertion
parseOnlyUsesNoAuthority =
- withCliFixture cliSource \fixture -> do
- writeFile
- (cliFixtureVampire fixture)
- "not executable"
+ withCliFixture cliPreludeSyntaxSource \fixture -> do
+ writeNonExecutableFile (cliFixtureVampire fixture)
(exitCode, stdout, stderr) <-
runCliFixture
fixture
@@ -307,6 +327,7 @@ removesFailedDumpTemporary =
dumpsExactExecutedRequest :: Assertion
dumpsExactExecutedRequest =
withCliFixture cliSource \fixture -> do
+ seedPackagedPreludeCache fixture
let captured = cliFixtureRoot fixture </> "captured.p"
writeExecutableScript
(cliFixtureVampire fixture)
@@ -316,31 +337,28 @@ dumpsExactExecutedRequest =
(exitCode, _stdout, stderr) <-
runCliFixture fixture
[ "input.tex"
- , "--fresh"
, "--dump"
, "dump"
]
exitCode `shouldBe` ExitSuccess
stderr `shouldContain` "Verification successful."
dumped <- ByteString.readFile
- (cliFixtureRoot fixture </> "dump" </> "1.p")
+ (cliFixtureRoot fixture </> "dump" </> "1-1.p")
sent <- ByteString.readFile captured
assertEqual "dump is the exact process input" sent dumped
assertBool "request is dumped only once"
. not
=<< Directory.doesPathExist
- (cliFixtureRoot fixture </> "dump" </> "2.p")
+ (cliFixtureRoot fixture </> "dump" </> "1-2.p")
launchFailureDumpsNoRequest :: Assertion
launchFailureDumpsNoRequest =
withCliFixture cliSource \fixture -> do
- writeFile
- (cliFixtureVampire fixture)
- "not executable"
+ seedPackagedPreludeCache fixture
+ writeNonExecutableFile (cliFixtureVampire fixture)
(exitCode, _stdout, stderr) <-
runCliFixture fixture
[ "input.tex"
- , "--fresh"
, "--dump"
, "dump"
]
@@ -349,11 +367,12 @@ launchFailureDumpsNoRequest =
assertBool "no request was dumped before process launch"
. not
=<< Directory.doesPathExist
- (cliFixtureRoot fixture </> "dump" </> "1.p")
+ (cliFixtureRoot fixture </> "dump" </> "1-1.p")
dumpsOnlyExecutedPrefix :: Assertion
dumpsOnlyExecutedPrefix =
withCliFixture cliTwoSource \fixture -> do
+ seedPackagedPreludeCache fixture
writeExecutableScript
(cliFixtureVampire fixture)
[ "cat >/dev/null"
@@ -362,7 +381,6 @@ dumpsOnlyExecutedPrefix =
(exitCode, _stdout, stderr) <-
runCliFixture fixture
[ "input.tex"
- , "--fresh"
, "--dump"
, "dump"
]
@@ -370,15 +388,16 @@ dumpsOnlyExecutedPrefix =
stderr `shouldContain` "prover found countermodel"
assertBool "executed request was dumped"
=<< Directory.doesFileExist
- (cliFixtureRoot fixture </> "dump" </> "1.p")
+ (cliFixtureRoot fixture </> "dump" </> "1-1.p")
assertBool "unexecuted request was not dumped"
. not
=<< Directory.doesPathExist
- (cliFixtureRoot fixture </> "dump" </> "2.p")
+ (cliFixtureRoot fixture </> "dump" </> "1-2.p")
dumpAndHtmlVerifyOnce :: Assertion
dumpAndHtmlVerifyOnce =
withCliFixture cliSource \fixture -> do
+ seedPackagedPreludeCache fixture
let countPath = cliFixtureRoot fixture </> "vampire-runs"
writeExecutableScript
(cliFixtureVampire fixture)
@@ -389,7 +408,6 @@ dumpAndHtmlVerifyOnce =
(exitCode, _stdout, stderr) <-
runCliFixture fixture
[ "input.tex"
- , "--fresh"
, "--dump"
, "dump"
, "--html"
@@ -400,7 +418,7 @@ dumpAndHtmlVerifyOnce =
assertEqual "one semantic verification" ["run"] runs
assertBool "request dump was published"
=<< Directory.doesFileExist
- (cliFixtureRoot fixture </> "dump" </> "1.p")
+ (cliFixtureRoot fixture </> "dump" </> "1-1.p")
assertBool "root HTML page was published"
=<< Directory.doesFileExist
(cliFixtureRoot fixture </> "html" </> "input.html")
@@ -414,6 +432,7 @@ dumpAndHtmlVerifyOnce =
semanticFailurePublishesNoHtml :: Assertion
semanticFailurePublishesNoHtml =
withCliFixture cliSource \fixture -> do
+ seedPackagedPreludeCache fixture
writeExecutableScript
(cliFixtureVampire fixture)
[ "cat >/dev/null"
@@ -421,17 +440,56 @@ semanticFailurePublishesNoHtml =
]
(exitCode, _stdout, stderr) <-
runCliFixture fixture
- ["input.tex", "--fresh", "--html"]
+ [ "input.tex"
+ , "--dump"
+ , "dump"
+ , "--html"
+ ]
exitCode `shouldBe` ExitFailure 1
stderr `shouldContain` "prover found countermodel"
+ assertBool "semantic failure retains the executed request dump"
+ =<< Directory.doesFileExist
+ (cliFixtureRoot fixture </> "dump" </> "1-1.p")
assertBool "semantic failure publishes no HTML"
. not
=<< Directory.doesPathExist
(cliFixtureRoot fixture </> "html")
+freshAndCachedPresentationAgree :: Assertion
+freshAndCachedPresentationAgree =
+ withCliFixture cliSource \fixture -> do
+ seedPackagedPreludeCache fixture
+ writeExecutableScript
+ (cliFixtureVampire fixture)
+ [ "cat >/dev/null"
+ , "printf '%s\\n' '% SZS status Theorem for cli'"
+ ]
+ (freshExit, _freshStdout, freshStderr) <-
+ runCliFixture fixture ["input.tex", "--html"]
+ freshExit `shouldBe` ExitSuccess
+ freshStderr `shouldContain` "Verification successful."
+ let htmlRoot = cliFixtureRoot fixture </> "html"
+ page = htmlRoot </> "input.html"
+ support =
+ htmlRoot </> "_static" </> "naproche-html.js"
+ freshPage <- ByteString.readFile page
+ freshSupport <- ByteString.readFile support
+ Directory.removePathForcibly htmlRoot
+ writeNonExecutableFile (cliFixtureVampire fixture)
+ (warmExit, _warmStdout, warmStderr) <-
+ runCliFixture fixture ["input.tex", "--html"]
+ warmExit `shouldBe` ExitSuccess
+ warmStderr `shouldContain` "Verification successful."
+ warmPage <- ByteString.readFile page
+ warmSupport <- ByteString.readFile support
+ assertEqual "fresh/cache-hit page bytes" freshPage warmPage
+ assertEqual "fresh/cache-hit support bytes"
+ freshSupport warmSupport
+
missingRendererDataIsTyped :: Assertion
missingRendererDataIsTyped =
withCliFixture cliSource \fixture -> do
+ seedPackagedPreludeCache fixture
Directory.removeFile
(cliFixtureRoot fixture </> "library" </> "lexicon.tsv")
writeExecutableScript
@@ -440,7 +498,7 @@ missingRendererDataIsTyped =
, "printf '%s\\n' '% SZS status Theorem for cli'"
]
(exitCode, stdout, stderr) <-
- runCliFixture fixture ["input.tex", "--fresh", "--html"]
+ runCliFixture fixture ["input.tex", "--html"]
exitCode `shouldBe` ExitFailure 2
stdout `shouldBe` ""
stderr `shouldContain` "HTML preparation failed:"
@@ -452,27 +510,44 @@ missingRendererDataIsTyped =
=<< Directory.doesPathExist
(cliFixtureRoot fixture </> "html")
+htmlFailureRetainsAuthorizationReport :: Assertion
+htmlFailureRetainsAuthorizationReport =
+ withCliFixture cliGapSource \fixture -> do
+ seedPackagedPreludeCache fixture
+ Directory.removeFile
+ (cliFixtureRoot fixture </> "library" </> "lexicon.tsv")
+ writeNonExecutableFile (cliFixtureVampire fixture)
+ (exitCode, stdout, stderr) <-
+ runCliFixture fixture ["input.tex", "--html"]
+ exitCode `shouldBe` ExitFailure 2
+ stdout `shouldBe` ""
+ stderr `shouldContain`
+ "Verification succeeded, but HTML preparation failed:"
+ stderr `shouldContain`
+ "Direct source authorization summary: 0 source axioms, 1 explicit proof gap."
+ stderr `shouldContain` "Explicit proof gap at input.tex 5:5"
+ assertBool "failed output publishes no HTML"
+ . not
+ =<< Directory.doesPathExist
+ (cliFixtureRoot fixture </> "html")
+
outcomeCases :: [(CommandOutcome, ExitCode)]
outcomeCases =
[ (CommandCompleted, ExitSuccess)
, (VerificationSucceeded emptyReport, ExitSuccess)
, (VerificationCompletedWithGaps emptyReport, ExitSuccess)
- , ( VerificationRejected Nowhere (CountermodelFound "")
+ , ( VerificationRejected emptyReport Nowhere (CountermodelFound "")
, ExitFailure 1
)
- , (ProverFailed Nowhere (ProverIndeterminate ""), ExitFailure 2)
+ , ( ProverFailed emptyReport Nowhere (ProverIndeterminate "")
+ , ExitFailure 2
+ )
]
emptyReport :: VerificationReport
emptyReport =
VerificationReport
- { verificationRoute = LegacyVerificationRoute
- , verificationLegacyDeclaredAssumptionCount = 0
- , verificationTypedDeclaredAssumptionCount = 0
- , verificationTrustedVampireCount = 0
- , verificationExplicitGapLocations = []
- , verificationTrustedLegacyRuleCount = 0
- , verificationKernelProofCount = 0
+ { verificationDirectEscapes = []
}
runCliWithFakeVampire
@@ -495,8 +570,9 @@ runCliWithSourceAndConfiguredVampire
-> IO (ExitCode, String, String)
runCliWithSourceAndConfiguredVampire source prepareVampire =
withCliFixture source \fixture -> do
+ seedPackagedPreludeCache fixture
prepareVampire (cliFixtureVampire fixture)
- runCliFixture fixture ["input.tex", "--fresh"]
+ runCliFixture fixture ["input.tex"]
data CliFixture = CliFixture
{ cliFixtureRoot :: !FilePath
@@ -562,6 +638,27 @@ runCliFixture fixture arguments =
})
""
+-- | Populate only the packaged final-prelude root. Process-boundary tests
+-- can then exercise the requested ordinary module outcome without making
+-- their fake prover depend on the prelude's private obligation count.
+seedPackagedPreludeCache :: CliFixture -> Assertion
+seedPackagedPreludeCache fixture = do
+ let sourcePath = cliFixtureRoot fixture </> "input.tex"
+ original <- ByteString.readFile sourcePath
+ writeExecutableScript
+ (cliFixtureVampire fixture)
+ [ "cat >/dev/null"
+ , "printf '%s\\n' '% SZS status Theorem for prelude seed'"
+ ]
+ (exitCode, stdout, stderr) <-
+ (do
+ writeFile sourcePath "% cache the packaged final prelude\n"
+ runCliFixture fixture ["input.tex"])
+ `Exception.finally` ByteString.writeFile sourcePath original
+ exitCode `shouldBe` ExitSuccess
+ stdout `shouldBe` ""
+ stderr `shouldContain` "Verification successful."
+
assertNoDefaultStore :: CliFixture -> Assertion
assertNoDefaultStore fixture =
assertBool "default store was not created"
@@ -577,6 +674,14 @@ writeExecutableScript path scriptLines = do
Directory.setPermissions path
(Directory.setOwnerExecutable True permissions)
+writeNonExecutableFile :: FilePath -> IO ()
+writeNonExecutableFile path = do
+ exists <- Directory.doesPathExist path
+ if exists
+ then Directory.removeFile path
+ else pure ()
+ writeFile path "not executable"
+
requireZfExecutable :: IO FilePath
requireZfExecutable = do
executable <- Directory.findExecutable "zf"
@@ -603,6 +708,14 @@ cliSource =
, "\\end{proposition}"
]
+cliPreludeSyntaxSource :: String
+cliPreludeSyntaxSource =
+ unlines
+ [ "\\begin{proposition}\\label{parse_prelude_syntax}"
+ , " For all $x$ we have $\\preludeSuccessor{x} = \\preludeSuccessor{x}$."
+ , "\\end{proposition}"
+ ]
+
cliGapSource :: String
cliGapSource =
unlines
diff --git a/source/Test/Unit/Core.hs b/source/Test/Unit/Core.hs
index fd817c6..e1ba10d 100644
--- a/source/Test/Unit/Core.hs
+++ b/source/Test/Unit/Core.hs
@@ -15,16 +15,20 @@ import Test.Tasty.HUnit hiding (assert)
import Test.Tasty.Hedgehog (testPropertyNamed)
-data TestGlobal = TestGlobal
+data TestGlobal
+ = TestGlobal
+ | TestPairGlobal
deriving (Show, Eq, Ord)
instance NFData TestGlobal where
- rnf TestGlobal =
+ rnf _global =
()
testGlobalType :: TestGlobal -> Maybe CoreType
testGlobalType TestGlobal =
Just TySet
+testGlobalType TestPairGlobal =
+ Just (TySet `TyArrow` (TySet `TyArrow` TySet))
unitTests :: TestTree
unitTests =
@@ -51,6 +55,9 @@ unitTests =
"specializes the checked separation characteristic"
specializesCheckedSeparationCharacteristic
, testCase
+ "specializes the checked replacement characteristic"
+ specializesCheckedReplacementCharacteristic
+ , testCase
"thaws checked closed terms without changing them"
thawsCheckedClosedTerms
, testPropertyNamed
@@ -325,7 +332,11 @@ specializesCheckedSeparationCharacteristic = do
maybe
(assertFailure "separation did not form a set definition")
pure
- (scopedSetDefinition body)
+ (scopedSetDefinition
+ (Foundation.foundationAxiomFrozen
+ foundation
+ Foundation.SeparationCharacteristic)
+ body)
let generated =
instantiateCanonical
separation
@@ -343,36 +354,90 @@ specializesCheckedSeparationCharacteristic = do
"local characteristic is the checked rule specialization"
expected
generated
+
+specializesCheckedReplacementCharacteristic :: Assertion
+specializesCheckedReplacementCharacteristic = do
+ foundation <-
+ either
+ (assertFailure . show)
+ pure
+ Foundation.checkedFoundation
+ pair <- checked [] (CGlobal TestPairGlobal)
+ domain <- checked [] (CIntrinsic Empty)
+ value <- checked [TySet] (CBound 0)
+ (graph, checkedDomain, function) <-
+ maybe
+ (assertFailure "checked values did not form a replacement graph")
+ pure
+ (scopedReplacementGraph pair domain value)
+ definition <-
+ maybe
+ (assertFailure "replacement graph did not form a definition")
+ pure
+ (scopedCharacteristicDefinition
+ (Foundation.foundationAxiomFrozen
+ foundation
+ Foundation.ReplacementCharacteristic)
+ graph
+ (checkedDomain :| [function]))
+ let generated =
+ instantiateCanonical
+ (scopedCoreTerm graph)
+ (scopedCoreTerm definition)
+ expected =
+ betaNormalize
+ (specializeForall (scopedCoreTerm function)
+ (specializeForall (scopedCoreTerm checkedDomain)
+ (mapCanonicalGlobals absurd
+ (frozenCoreTerm
+ (Foundation.foundationAxiomFrozen
+ foundation
+ Foundation.ReplacementCharacteristic)))))
+ assertEqual
+ "local graph characteristic is the checked rule specialization"
+ expected
+ generated
where
- specializeForall argument = \case
- CForall _binderType body ->
- instantiateCanonical argument body
- _ ->
- error "the checked separation characteristic lost a binder"
+ checked context term =
+ either
+ (assertFailure . show)
+ pure
+ (checkScopedCanonicalCore testGlobalType context term)
+
+specializeForall
+ :: CanonicalTerm global
+ -> CanonicalTerm global
+ -> CanonicalTerm global
+specializeForall argument = \case
+ CForall _binderType body ->
+ instantiateCanonical argument body
+ _ ->
+ error "the checked characteristic lost a binder"
- betaNormalize = \case
- CApp function argument ->
- case betaNormalize function of
- CLam _binderType body ->
- betaNormalize
- (instantiateCanonical
- (betaNormalize argument)
- body)
- normalizedFunction ->
- CApp normalizedFunction (betaNormalize argument)
- CLam binderType body ->
- CLam binderType (betaNormalize body)
- CImp premise conclusion ->
- CImp
- (betaNormalize premise)
- (betaNormalize conclusion)
- CEq operandType left right ->
- CEq operandType
- (betaNormalize left)
- (betaNormalize right)
- CForall binderType body ->
- CForall binderType (betaNormalize body)
- term -> term
+betaNormalize :: CanonicalTerm global -> CanonicalTerm global
+betaNormalize = \case
+ CApp function argument ->
+ case betaNormalize function of
+ CLam _binderType body ->
+ betaNormalize
+ (instantiateCanonical
+ (betaNormalize argument)
+ body)
+ normalizedFunction ->
+ CApp normalizedFunction (betaNormalize argument)
+ CLam binderType body ->
+ CLam binderType (betaNormalize body)
+ CImp premise conclusion ->
+ CImp
+ (betaNormalize premise)
+ (betaNormalize conclusion)
+ CEq operandType left right ->
+ CEq operandType
+ (betaNormalize left)
+ (betaNormalize right)
+ CForall binderType body ->
+ CForall binderType (betaNormalize body)
+ term -> term
thawsCheckedClosedTerms :: Assertion
thawsCheckedClosedTerms = do
diff --git a/source/Test/Unit/Declaration.hs b/source/Test/Unit/Declaration.hs
index c03c21c..78ad27e 100644
--- a/source/Test/Unit/Declaration.hs
+++ b/source/Test/Unit/Declaration.hs
@@ -50,6 +50,8 @@ unitTests =
propagatesUnsafeAuthorityThroughLocalClaims
, testCase "aggregates exact Vampire obligations"
aggregatesExactVampireObligations
+ , testCase "validates complete resolver batches before rejection"
+ validatesCompleteResolverBatchesBeforeRejection
, testCase "preserves source-axiom safety through Vampire validation"
preservesSourceAxiomSafetyThroughVampireValidation
, testCase "materializes a sealed import with fresh authority"
@@ -759,6 +761,112 @@ aggregatesExactVampireObligations =
("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"
+
preservesSourceAxiomSafetyThroughVampireValidation :: Assertion
preservesSourceAxiomSafetyThroughVampireValidation =
withTemporaryDirectory "felix-declaration-source-axiom" \root -> do
diff --git a/source/Test/Unit/Encoding.hs b/source/Test/Unit/Encoding.hs
deleted file mode 100644
index cba359f..0000000
--- a/source/Test/Unit/Encoding.hs
+++ /dev/null
@@ -1,363 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module Test.Unit.Encoding (unitTests, propertyTests) where
-
-import Base
-import Checking.Backend.Problem qualified as Backend
-import Checking.Core qualified as Core
-import Encoding
-import Provers
-import Report.Location
-import Syntax.Internal
-import Tptp.UnsortedFirstOrder qualified as Tptp
-
-import Control.Monad.Logger (runNoLoggingT)
-import Data.Map.Strict qualified as Map
-import Data.Set qualified as Set
-import Data.Text qualified as Text
-import Data.Vector qualified as Vector
-import Hedgehog hiding (Command)
-import Hedgehog.Gen qualified as Gen
-import Hedgehog.Range qualified as Range
-import Test.Tasty
-import Test.Tasty.HUnit hiding (assert)
-import Test.Tasty.Hedgehog (testPropertyNamed)
-import UnliftIO.Environment (lookupEnv)
-
-unitTests :: TestTree
-unitTests =
- testGroup "Encoding"
- [ propertyTests
- , testCase
- "real Vampire distinguishes Unicode free constants from symbols"
- realVampireDistinguishesNames
- , testCase
- "real Vampire proves a typed higher-order problem"
- realVampireProvesTypedHigherOrderProblem
- ]
-
-propertyTests :: TestTree
-propertyTests =
- testGroup "properties"
- [ testPropertyNamed
- "allocates legal dense names deterministically"
- "prop_taskLocalNames"
- prop_taskLocalNames
- ]
-
-prop_taskLocalNames :: Property
-prop_taskLocalNames = property do
- generatedSpellings <-
- forAll
- (Gen.list
- (Range.linear 0 20)
- sourceSpelling)
- let spellings =
- zipWith
- (\ordinal spelling ->
- spelling <> "#" <> Text.pack (show ordinal))
- [0 :: Int ..]
- (adversarialSpellings <> generatedSpellings)
- originalBinders =
- zipWith
- (\ordinal spelling ->
- NamedVar
- ( spelling
- <> "_bound_"
- <> Text.pack (show ordinal)
- ))
- [0 :: Int ..]
- spellings
- renamedBinders =
- [ NamedVar ("renamed_" <> Text.pack (show ordinal))
- | ordinal <- [0 .. length spellings - 1]
- ]
- baseHypotheses =
- zipWith makeHypothesis spellings originalBinders
- firstHypothesis =
- listToMaybe baseHypotheses
- ?? impossible "allocator property has no seeded hypothesis"
- duplicateHypotheses =
- baseHypotheses <> [firstHypothesis]
- alphaHypotheses =
- let renamed =
- zipWith makeHypothesis spellings renamedBinders
- firstRenamed =
- listToMaybe renamed
- ?? impossible
- "allocator property has no renamed hypothesis"
- in renamed <> [firstRenamed]
- shuffledHypotheses <- forAll (Gen.shuffle duplicateHypotheses)
- let prepared =
- prepareTptpTask (namingTask duplicateHypotheses)
- shuffled =
- prepareTptpTask (namingTask shuffledHypotheses)
- alphaRenamed =
- prepareTptpTask (namingTask alphaHypotheses)
- nameOrigins = preparedTptpNameOrigins prepared
- targetNames = Map.keysSet nameOrigins
- renderedIdentifiers =
- tptpIdentifiers (preparedTptpText prepared)
- semanticCount = length spellings
- hypothesisCount = length duplicateHypotheses
- binderCount = 2 * hypothesisCount
-
- preparedTptpText shuffled === preparedTptpText prepared
- preparedTptpText alphaRenamed === preparedTptpText prepared
- preparedTptpNameOrigins shuffled === nameOrigins
- preparedTptpNameOrigins alphaRenamed === nameOrigins
-
- categoryNames "zf_u" targetNames
- === ordinalNames "zf_u" semanticCount
- categoryNames "zf_f" targetNames
- === ordinalNames "zf_f" semanticCount
- categoryNames "zf_s" targetNames
- === ordinalNames "zf_s" semanticCount
- categoryNames "zf_h" targetNames
- === ordinalNames "zf_h" hypothesisCount
- categoryNames "zf_q" targetNames
- === Set.singleton "zf_q0"
- categoryNames "V" targetNames
- === ordinalNames "V" binderCount
- assert (targetNames `Set.isSubsetOf` renderedIdentifiers)
-
- Set.size targetNames
- === 3 * semanticCount + hypothesisCount + binderCount + 1
- for_ targetNames \target ->
- if "V" `Text.isPrefixOf` target
- then assert (Tptp.isProperVariable target)
- else assert (Tptp.isProperAtomicWord target)
-
-sourceSpelling :: Gen Text
-sourceSpelling =
- Gen.text
- (Range.linear 0 16)
- (Gen.element
- ( ['a'..'z']
- <> ['A'..'Z']
- <> ['0'..'9']
- <> "_'-.:/\\"
- <> ['λ', 'Ω', '\x0301', '💥']
- ))
-
-adversarialSpellings :: [Text]
-adversarialSpellings =
- [ ""
- , "λ"
- , "e\x0301"
- , "name'"
- , "under_score"
- , "zf_u0"
- , "zf_f0"
- , "zf_s0"
- , "V0"
- , "Case"
- , "case"
- , "a-b"
- , "💥"
- ]
-
-makeHypothesis :: Text -> VarSymbol -> Hypothesis
-makeHypothesis spelling binder =
- let freeConstant = TermVar (NamedVar spelling)
- structureTerm =
- TermSymbolStruct
- (StructSymbol spelling)
- (Just freeConstant)
- body =
- Atomic
- Nowhere
- (PredicateSymbol spelling)
- [ freeConstant
- , structureTerm
- , TermVar binder
- ]
- shadowedBody =
- makeExists
- [binder]
- (Atomic
- Nowhere
- (PredicateSymbol spelling)
- [TermVar binder])
- nativeRelations =
- Equals Nowhere freeConstant freeConstant
- `And` NotEquals Nowhere freeConstant structureTerm
- in
- Hypothesis
- (Marker ("label_" <> spelling))
- (makeForall
- [binder]
- (body `And` shadowedBody `And` nativeRelations))
-
-namingTask :: [Hypothesis] -> Task
-namingTask hypotheses =
- Task
- { taskDirectness = Direct
- , taskHypotheses = hypotheses
- , taskConjectureLabel = "ignored_conjecture_label"
- , taskLocation = Nowhere
- , taskConjecture = Top
- }
-
-categoryNames :: Text -> Set Text -> Set Text
-categoryNames prefix =
- Set.filter (prefix `Text.isPrefixOf`)
-
-ordinalNames :: Text -> Int -> Set Text
-ordinalNames prefix size =
- Set.fromList
- [ prefix <> Text.pack (show ordinal)
- | ordinal <- [0 .. size - 1]
- ]
-
-tptpIdentifiers :: Text -> Set Text
-tptpIdentifiers =
- Set.delete ""
- . Set.fromList
- . Text.split (not . Tptp.isAsciiAlphaNumOrUnderscore)
-
-realVampireDistinguishesNames :: Assertion
-realVampireDistinguishesNames = do
- executable <- fromMaybe "vampire" <$> lookupEnv "NAPROCHE_ZF_VAMPIRE"
- let collisionSymbol =
- mkMixfixItem
- [Just (Command "collision")]
- "fx"
- NonAssoc
- freeConstant = TermVar (NamedVar "x")
- userConstant =
- TermSymbol
- Nowhere
- (SymbolMixfix collisionSymbol)
- []
- unicodeVariable = NamedVar "λ"
- unicodeReflexivity =
- makeForall
- [unicodeVariable]
- (Equals
- Nowhere
- (TermVar unicodeVariable)
- (TermVar unicodeVariable))
- task =
- Task
- { taskDirectness = Direct
- , taskHypotheses = []
- , taskConjectureLabel = "unicode_collision"
- , taskLocation = Nowhere
- , taskConjecture =
- Equals Nowhere freeConstant userConstant
- `And` unicodeReflexivity
- }
- (_location, _formula, answer) <-
- runNoLoggingT
- (runProver
- (vampire
- executable
- defaultTimeLimit
- defaultMemoryLimit)
- task)
- case answer of
- Right CounterSatisfiable{} ->
- pure ()
- result ->
- assertFailure
- ("expected a countermodel, got " <> show result)
-
-data Th0Global
- = Th0Predicate
- | Th0PredicateConsumer
- deriving (Show, Eq, Ord)
-
-th0GlobalType :: Th0Global -> Maybe Core.CoreType
-th0GlobalType = \case
- Th0Predicate ->
- Just
- (Core.TySet
- `Core.TyArrow` Core.TyProp)
- Th0PredicateConsumer ->
- Just
- ((Core.TySet
- `Core.TyArrow` Core.TyProp)
- `Core.TyArrow` Core.TyProp)
-
-realVampireProvesTypedHigherOrderProblem :: Assertion
-realVampireProvesTypedHigherOrderProblem = do
- executable <-
- fromMaybe "vampire"
- <$> lookupEnv "NAPROCHE_ZF_VAMPIRE"
- let claimTerm =
- Core.CApp
- (Core.CGlobal Th0PredicateConsumer)
- (Core.CLam Core.TySet
- (Core.CApp
- (Core.CGlobal Th0Predicate)
- (Core.CBound 0)))
- checked <-
- either
- (assertFailure . show)
- pure
- (Core.checkScopedCanonicalCore
- th0GlobalType
- []
- claimTerm)
- claim <-
- either
- (assertFailure . show)
- pure
- (Backend.supportedProposition
- (Vector.empty
- :: Vector.Vector
- (Void, Core.CoreType))
- checked)
- capability <-
- either
- (assertFailure . show)
- pure
- (Backend.classifySupportedProposition
- th0GlobalType
- claim)
- problem <-
- either
- (assertFailure . show)
- pure
- (Backend.planTypedProblem
- th0GlobalType
- (Vector.singleton
- (Backend.typedBackendFact
- (0 :: Int)
- claim
- capability))
- claim
- []
- []
- Backend.ExplicitGlobalPremises
- Backend.FirstOrderLocals)
- prepared <-
- either
- (assertFailure . show)
- pure
- (prepareTypedProverTask
- DirectTask
- problem)
- assertEqual
- "higher-order request dialect"
- VerificationTh0
- (preparedVerificationDialect
- (preparedTypedProverRequest
- prepared))
- answer <-
- runNoLoggingT
- (runPreparedTypedProver
- (vampire
- executable
- defaultTimeLimit
- defaultMemoryLimit)
- prepared)
- case answer of
- Right result
- | isJust (provedVampireRun result) ->
- pure ()
- result ->
- assertFailure
- ("expected a higher-order theorem, got "
- <> show result)
diff --git a/source/Test/Unit/Html.hs b/source/Test/Unit/Html.hs
index 7dd2837..14ecdc3 100644
--- a/source/Test/Unit/Html.hs
+++ b/source/Test/Unit/Html.hs
@@ -4,6 +4,7 @@ module Test.Unit.Html (unitTests) where
import Base
import Api qualified
+import Felix.Parse qualified as Parse
import Felix.Source
import Felix.Source.Graph
import Render.Html qualified as Html
@@ -13,20 +14,55 @@ import Report.Location (Location, pattern Nowhere)
import Syntax.Abstract
import Data.Text qualified as Text
+import Data.Text.IO qualified as TextIO
+import Data.List.NonEmpty qualified as NonEmpty
import System.Directory qualified as Directory
import Test.Tasty
import Test.Tasty.HUnit
unitTests :: TestTree
unitTests = testGroup "HTML renderer"
- [ testCase "reference previews are rendered for local and imported refs" referencePreviews
+ [ testCase "one shared index resolves local and cross-page previews" referencePreviews
, testCase "missing reference preview data falls back to readable text" missingReferenceFallback
, testCase "datatype rendering omits unchecked derived facts" datatypeDerivedFactsAreOmitted
]
referencePreviews :: Assertion
referencePreviews = do
- html <- Api.exportHtml "test/html-fixtures/root-preview.tex"
+ graph <-
+ expectRight =<<
+ Api.prepareDefaultSourceGraph
+ "test/html-fixtures/root-preview.tex"
+ workspace <-
+ expectRight =<< Parse.parseResolvedSourceGraph graph
+ hints <- TextIO.readFile "library/lexicon.tsv"
+ layout <-
+ expectRight
+ (layoutHtmlSourceGraph
+ Api.defaultHtmlMountPrefixes
+ graph)
+ let nodes = Parse.parsedWorkspaceImportedBeforeImporter workspace
+ sourceBlocks =
+ (\node ->
+ ( Parse.parsedModuleResolved node
+ , Parse.parsedModuleBlocks node
+ ))
+ <$> nodes
+ (renderIndex, pages) =
+ Html.buildRenderIndex sourceBlocks
+ rootPage = NonEmpty.last pages
+ context <-
+ expectRight
+ (htmlRenderContext
+ layout
+ (Html.htmlPagePresentationSource rootPage))
+ html <-
+ expectRight
+ (Html.renderDocument
+ context
+ hints
+ renderIndex
+ rootPage)
let supportScript = Html.supportScriptAssetContents
assertContains "local references keep page anchors" "href=\"#local_prop\"" html
assertContains "local references point previews at the visible target block" "data-reference-label=\"local_prop\" data-preview-target-id=\"local_prop\"" html
@@ -111,12 +147,15 @@ renderSynthetic blocks = do
(htmlRenderContext
layout
(sourceGraphRootSource graph))
+ let (renderIndex, page :| _remainingPages) =
+ Html.buildRenderIndex
+ ((sourceGraphRootSource graph, blocks) :| [])
expectRight
(Html.renderDocument
context
""
- blocks
- [(sourceGraphRootSource graph, blocks)])
+ renderIndex
+ page)
expectRight :: (Show e, HasCallStack) => Either e a -> IO a
expectRight = \case
diff --git a/source/Test/Unit/HtmlOutput.hs b/source/Test/Unit/HtmlOutput.hs
index 1993fc9..0087f82 100644
--- a/source/Test/Unit/HtmlOutput.hs
+++ b/source/Test/Unit/HtmlOutput.hs
@@ -4,7 +4,9 @@
module Test.Unit.HtmlOutput (unitTests) where
import Base
+import Felix.Parse qualified as Parse
import Felix.Source
+import Felix.Source.Graph qualified as SourceGraph
import Render.Html qualified as Html
import Render.Html.Export
import Render.Html.Output
@@ -43,7 +45,7 @@ unitTests =
"rejects a FIFO before publication"
rejectsFifo
, testCase
- "reports and cleans an incomplete publication"
+ "reports and cleans the source-order publication prefix"
reportsIncompletePublication
]
@@ -94,36 +96,29 @@ publishesMountedExport =
expectRight =<< existingRoot rootSource
searchedExport <-
expectRight =<<
- prepareHtmlExport
+ prepareTestHtmlExport
configuration
mounts
searched
hints
exactExport <-
expectRight =<<
- prepareHtmlExport
+ prepareTestHtmlExport
configuration
mounts
exact
hints
assertEqual
"root-form-independent destinations"
- (preparedHtmlBundleDestinations
- (preparedHtmlOutputBundle searchedExport))
- (preparedHtmlBundleDestinations
- (preparedHtmlOutputBundle exactExport))
- assertEqual
- "root-form-independent root document"
- (preparedHtmlRootDocument searchedExport)
- (preparedHtmlRootDocument exactExport)
+ (preparedHtmlArtifactDestination <$> searchedExport)
+ (preparedHtmlArtifactDestination <$> exactExport)
- let bundle =
- preparedHtmlOutputBundle searchedExport
- rejectsBundleEscape temp bundle
+ let artifacts = searchedExport
+ rejectsArtifactEscape temp artifacts
plan <-
requirePlan =<<
- planHtmlOutput outputRoot bundle
+ planHtmlOutput outputRoot artifacts
outputExistsBeforePublication <-
Directory.doesPathExist outputRoot
assertBool
@@ -168,11 +163,11 @@ publishesMountedExport =
Html.supportScriptAssetContents
supportText
-rejectsBundleEscape
+rejectsArtifactEscape
:: FilePath
- -> PreparedHtmlBundle
+ -> [PreparedHtmlArtifact]
-> Assertion
-rejectsBundleEscape temp bundle = do
+rejectsArtifactEscape temp artifacts = do
let outputRoot = temp </> "escape-html"
outsideRoot = temp </> "outside"
outsideMarker = outsideRoot </> "unchanged"
@@ -182,7 +177,7 @@ rejectsBundleEscape temp bundle = do
Directory.createDirectoryLink
outsideRoot
(outputRoot </> "docs")
- result <- planHtmlOutput outputRoot bundle
+ result <- planHtmlOutput outputRoot artifacts
case result of
Left
(HtmlOutputParentEscapesRoot
@@ -223,8 +218,8 @@ writesPreparedBytes =
, 0x63, 0x61, 0x66
, 0xc3, 0xa9
]
- bundle <-
- makeBundle
+ artifacts <-
+ makeArtifacts
[ ( "nested/über.html"
, TextEncoding.encodeUtf8 pageText
)
@@ -232,7 +227,7 @@ writesPreparedBytes =
, TextEncoding.encodeUtf8 supportText
)
]
- publishBundle outputRoot bundle
+ publishArtifacts outputRoot artifacts
pageBytes <-
ByteString.readFile
(outputRoot </> "nested" </> "über.html")
@@ -259,7 +254,7 @@ attachesBytesToReservedRoutes =
["page.html", "_static/naproche-html.js"])
routes <- requireRoutePlan =<<
planHtmlRoutes outputRoot reserved
- matching <- makeBundle
+ matching <- makeArtifacts
[ ("page.html", "page")
, ("_static/naproche-html.js", "support")
]
@@ -268,7 +263,7 @@ attachesBytesToReservedRoutes =
pure ()
Left failure ->
assertFailure (show failure)
- mismatched <- makeBundle
+ mismatched <- makeArtifacts
[ ("other.html", "other")
, ("_static/naproche-html.js", "support")
]
@@ -295,12 +290,12 @@ rejectsFinalSymlink =
ByteString.writeFile page "old page"
ByteString.writeFile outsideAsset "outside asset"
Directory.createFileLink outsideAsset support
- bundle <-
- makeBundle
+ artifacts <-
+ makeArtifacts
[ ("page.html", "new page")
, ("_static/naproche-html.js", "new support")
]
- result <- planHtmlOutput outputRoot bundle
+ result <- planHtmlOutput outputRoot artifacts
case result of
Left (HtmlOutputTargetIsSymbolicLink target) ->
assertEqual "rejected target" support target
@@ -331,9 +326,9 @@ replacesHardLinkedTarget =
Directory.createDirectory outputRoot
ByteString.writeFile outsidePage "outside page"
PosixFiles.createLink outsidePage page
- bundle <-
- makeBundle [("page.html", "new page")]
- publishBundle outputRoot bundle
+ artifacts <-
+ makeArtifacts [("page.html", "new page")]
+ publishArtifacts outputRoot artifacts
outsideBytes <- ByteString.readFile outsidePage
pageBytes <- ByteString.readFile page
assertEqual
@@ -349,9 +344,9 @@ rejectsFifo =
page = outputRoot </> "page.html"
Directory.createDirectory outputRoot
PosixFiles.createNamedPipe page PosixFiles.ownerModes
- bundle <-
- makeBundle [("page.html", "page")]
- result <- planHtmlOutput outputRoot bundle
+ artifacts <-
+ makeArtifacts [("page.html", "page")]
+ result <- planHtmlOutput outputRoot artifacts
case result of
Left (HtmlOutputTargetNotRegularFile target) ->
assertEqual "rejected target" page target
@@ -369,18 +364,18 @@ reportsIncompletePublication :: Assertion
reportsIncompletePublication =
withTemporaryDirectory "felix-html-output-incomplete" \temp -> do
let outputRoot = temp </> "html"
- first = outputRoot </> "a.html"
+ first = outputRoot </> "z.html"
blocked = outputRoot </> "b.html"
- unpublished = outputRoot </> "c.html"
- bundle <-
- makeBundle
- [ ("a.html", "first")
+ unpublished = outputRoot </> "a.html"
+ artifacts <-
+ makeArtifacts
+ [ ("z.html", "first")
, ("b.html", "blocked")
- , ("c.html", "unpublished")
+ , ("a.html", "unpublished")
]
plan <-
requirePlan =<<
- planHtmlOutput outputRoot bundle
+ planHtmlOutput outputRoot artifacts
Directory.createDirectory outputRoot
Directory.createDirectory blocked
result <- writeHtmlOutput plan
@@ -392,7 +387,7 @@ reportsIncompletePublication =
} -> do
expectedFirst <-
expectRight
- (safeRelativePath "a.html")
+ (safeRelativePath "z.html")
expectedBlocked <-
expectRight
(safeRelativePath "b.html")
@@ -429,23 +424,22 @@ reportsIncompletePublication =
outputEntries))
-publishBundle
+publishArtifacts
:: FilePath
- -> PreparedHtmlBundle
+ -> [PreparedHtmlArtifact]
-> IO ()
-publishBundle outputRoot bundle = do
+publishArtifacts outputRoot artifacts = do
plan <-
- requirePlan =<< planHtmlOutput outputRoot bundle
+ requirePlan =<< planHtmlOutput outputRoot artifacts
requirePublication =<< writeHtmlOutput plan
-makeBundle
+makeArtifacts
:: [(FilePath, ByteString.ByteString)]
- -> IO PreparedHtmlBundle
-makeBundle artifacts = do
- prepared <- for artifacts \(path, bytes) -> do
+ -> IO [PreparedHtmlArtifact]
+makeArtifacts artifacts =
+ for artifacts \(path, bytes) -> do
relative <- expectRight (safeRelativePath path)
- pure (relative, bytes)
- expectRight (preparedHtmlBundle prepared)
+ pure (preparedHtmlArtifact relative (Right bytes))
requirePlan
:: Either HtmlOutputError HtmlOutputPlan
@@ -484,6 +478,24 @@ readUtf8 path = do
Right text ->
pure text
+prepareTestHtmlExport
+ :: [(SourceMountId, [Text])]
+ -> SourceMounts
+ -> RootRequest
+ -> Text
+ -> IO (Either HtmlExportError [PreparedHtmlArtifact])
+prepareTestHtmlExport configuration mounts request hints = do
+ graph <-
+ expectRight =<<
+ SourceGraph.buildResolvedSourceGraph mounts request
+ workspace <-
+ expectRight =<< Parse.parseResolvedSourceGraph graph
+ pure
+ (prepareHtmlExport
+ configuration
+ (htmlPresentationFromParsedWorkspace workspace)
+ hints)
+
writeImportedTheory :: FilePath -> IO ()
writeImportedTheory path =
writeFile path
diff --git a/source/Test/Unit/Kernel.hs b/source/Test/Unit/Kernel.hs
index 27f92b2..c24debf 100644
--- a/source/Test/Unit/Kernel.hs
+++ b/source/Test/Unit/Kernel.hs
@@ -9,7 +9,6 @@ import Checking.Foundation qualified as Foundation
import Checking.Kernel.Derivation
import Checking.Kernel.Semantics qualified as Semantics
import Checking.Kernel.SetLfp qualified as SetLfp
-import Checking.Transition (checkedGlobalType)
import Checking.Typed.Inductive qualified as Inductive
import Report.Location (pattern Nowhere)
import Syntax.Internal qualified as Internal
@@ -23,6 +22,9 @@ import Test.Tasty.HUnit
data TestGlobal = TestGlobal
deriving (Show, Eq, Ord)
+testGlobalType :: TestGlobal -> CoreType
+testGlobalType _global = TySet
+
unitTests :: TestTree
unitTests =
testGroup "Kernel replay"
@@ -438,7 +440,7 @@ replaysDirectInductiveFacts = do
prepared <-
expectRight
(Inductive.prepareTypedInductive
- checkedGlobalType
+ testGlobalType
foundation
(const Nothing)
(Internal.Marker "direct_inductive")
@@ -455,7 +457,7 @@ replaysDirectInductiveFacts = do
(replayKernelDerivation
foundation
defaultKernelReplayLimits
- (Just . checkedGlobalType)
+ (const Nothing)
imports
(Inductive.typedInductiveFactTarget
fact)
diff --git a/source/Test/Unit/Migration.hs b/source/Test/Unit/Migration.hs
deleted file mode 100644
index d9042cc..0000000
--- a/source/Test/Unit/Migration.hs
+++ /dev/null
@@ -1,161 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Test.Unit.Migration (unitTests) where
-
-import Base
-import Felix.Migration
-import Felix.Parse qualified as Parse
-import Felix.Prelude qualified as Prelude
-import Felix.Source
-import Syntax.Interface qualified as Syntax
-
-import System.Directory (getCurrentDirectory)
-import System.FilePath.Posix qualified as Posix
-import Test.Tasty
-import Test.Tasty.HUnit
-
-
-unitTests :: TestTree
-unitTests =
- testGroup "Migration manifest"
- [ testCase "resolves references from prepared mount roots"
- resolvesManifestReferences
- , testCase "selects one driver for the complete graph"
- selectsCompleteGraphDriver
- ]
-
-resolvesManifestReferences :: Assertion
-resolvesManifestReferences = do
- mounts <-
- expectRight
- =<< prepareSourceMounts
- [ (sourceMountId "project", "/tmp/felix-project")
- , (sourceMountId "library", "/tmp/felix-library")
- , (sourceMountId "debug", "/tmp/felix-debug")
- ]
- forM_
- (toList activeMigrationRoots
- <> toList protectedMigrationModules
- <> toList phase53LibraryMigrationModules)
- \reference -> do
- assertEqual
- "manifest role"
- MigrationLibrary
- (migrationModuleRefRole reference)
- candidate <-
- expectRight
- (migrationModuleCandidatePath mounts reference)
- assertEqual
- "mount-relative candidate"
- ("/tmp/felix-library"
- Posix.</> safeRelativePathFilePath
- (migrationModuleRefPath reference))
- candidate
- forM_ (toList typedMigrationModules) \reference ->
- assertEqual
- "typed module mount role"
- (if reference `elem`
- (toList protectedMigrationModules
- <> toList phase53LibraryMigrationModules)
- then MigrationLibrary
- else MigrationProject)
- (migrationModuleRefRole reference)
-
-selectsCompleteGraphDriver :: Assertion
-selectsCompleteGraphDriver = do
- root <- getCurrentDirectory
- mounts <-
- expectRight
- =<< prepareSourceMounts
- [ (sourceMountId "project", root)
- , (sourceMountId "library", root Posix.</> "library")
- , (sourceMountId "debug", root Posix.</> "debug")
- ]
- selection <-
- expectRight
- (resolveMigrationSelection mounts typedMigrationModules)
- reserved <-
- expectRight
- =<< Prelude.parseReservedPreludeSource
- Prelude.emptyBootstrapSourceInput
- let bootstrapSyntax =
- Parse.identifiedParsedModuleSyntaxInterface
- (Prelude.reservedParsedPreludeModule reserved)
- syntaxInputs source
- | migrationSelectionContains selection source =
- [bootstrapSyntax]
- | otherwise = []
- parseRoot path = do
- request <- expectRight (searchedRoot path)
- Parse.parseSourceWorkspaceMeasuredWithSyntaxInputs
- mounts request syntaxInputs
- (producer, _producerMeasurements) <-
- expectRight
- =<< parseRoot "test/phase3/typed-producer.tex"
- assertEqual "selected root uses typed driver"
- TypedMigrationGraph
- (classifyMigrationGraph selection producer)
- assertEqual "selected parse receives the bootstrap syntax input"
- [Syntax.moduleSyntaxAssertedId bootstrapSyntax]
- (Syntax.moduleSyntaxDirectInputs
- (Parse.parsedModuleSyntaxInterface
- (Parse.parsedWorkspaceRootModule producer)))
- (importer, _importerMeasurements) <-
- expectRight
- =<< parseRoot "test/phase3/legacy-importer.tex"
- assertEqual "unselected importer keeps the complete graph legacy"
- LegacyMigrationGraph
- (classifyMigrationGraph selection importer)
- forM_
- [ ( "set/bipartition.tex"
- , ["set.tex", "set/cons.tex", "set/powerset.tex"]
- )
- , ("set/product.tex", ["set.tex"])
- , ("set/filter.tex", ["set.tex", "set/powerset.tex"])
- , ( "relation.tex"
- , ["set.tex", "set/powerset.tex", "set/product.tex"]
- )
- , ( "relation/properties.tex"
- , ["set.tex", "relation.tex"]
- )
- , ( "relation/uniqueness.tex"
- , ["set.tex", "relation.tex"]
- )
- , ( "function.tex"
- , ["set.tex", "relation.tex", "relation/uniqueness.tex"]
- )
- , ( "set/cantor.tex"
- , ["set/powerset.tex", "function.tex"]
- )
- , ( "set/fixpoint.tex"
- , ["set/powerset.tex", "function.tex"]
- )
- ]
- \(path, expectedImports) -> do
- (phase53, _phase53Measurements) <-
- expectRight =<< parseRoot path
- assertEqual
- (path <> " closure uses the typed driver")
- TypedMigrationGraph
- (classifyMigrationGraph selection phase53)
- assertEqual
- (path <> " direct imports")
- expectedImports
- [ safeRelativePathFilePath
- (sourceAddressRelativePath
- (Parse.parsedImportedAddress imported))
- | imported <- Parse.parsedModuleImports
- (Parse.parsedWorkspaceRootModule phase53)
- ]
- (functionImporter, _functionMeasurements) <-
- expectRight =<< parseRoot "set/equinumerosity.tex"
- assertEqual "unselected function importer remains legacy"
- LegacyMigrationGraph
- (classifyMigrationGraph selection functionImporter)
-
-expectRight :: Show err => Either err value -> IO value
-expectRight = \case
- Left err ->
- assertFailure (show err) >> fail "unreachable"
- Right value ->
- pure value
diff --git a/source/Test/Unit/Module.hs b/source/Test/Unit/Module.hs
index 1cf62e5..fbc6c0d 100644
--- a/source/Test/Unit/Module.hs
+++ b/source/Test/Unit/Module.hs
@@ -21,7 +21,6 @@ import Checking.Typed.Inductive qualified as TypedInductive
import CommandLine qualified
import Felix.Module
import Felix.Math.Codec
-import Felix.Migration qualified as Migration
import Felix.Parse qualified as Parse
import Felix.Prelude qualified as Prelude
import Felix.Source
@@ -33,21 +32,45 @@ import Paths_felix qualified as Paths
import Syntax.Abstract qualified as Raw
import Syntax.Internal qualified as Internal
import Syntax.Interface qualified as Syntax
-
-import Bound.Scope (fromScope)
-import Bound.Var (Var(..))
+import Syntax.Pragma qualified as Pragma
+
+import Control.Concurrent (threadDelay)
+import Control.Concurrent.STM
+ ( atomically
+ , check
+ , newEmptyTMVarIO
+ , newTQueueIO
+ , newTVarIO
+ , putTMVar
+ , readTQueue
+ , readTVar
+ , takeTMVar
+ , tryReadTMVar
+ , tryReadTQueue
+ , writeTQueue
+ , writeTVar
+ )
import Control.Exception (bracket)
-import Control.Monad (foldM)
+import Control.Monad (foldM, when)
import Data.ByteString qualified as ByteString
import Data.Text qualified as StrictText
import Data.Text.Encoding qualified as Text
import Control.Monad.Logger (runNoLoggingT)
-import Data.IORef (IORef, modifyIORef', newIORef, readIORef)
+import Data.IORef
+ ( IORef
+ , atomicModifyIORef'
+ , modifyIORef'
+ , newIORef
+ , readIORef
+ )
+import Data.List (sort)
+import Data.List.NonEmpty qualified as NonEmpty
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import Data.Vector qualified as Vector
import System.Directory
( createDirectoryIfMissing
+ , doesFileExist
, getCurrentDirectory
, getPermissions
, setOwnerExecutable
@@ -55,8 +78,10 @@ import System.Directory
)
import System.FilePath.Posix qualified as Posix
import System.IO.Temp qualified as Temp
+import System.Timeout qualified as Timeout
import Test.Tasty
import Test.Tasty.HUnit
+import UnliftIO.Async (withAsync, wait)
unitTests :: TestTree
@@ -68,26 +93,28 @@ unitTests =
identifiesCommentOnlyInput
, testCase "loads and parses the packaged final prelude"
parsesPackagedFinalPrelude
+ , testCase "renders packaged final-prelude failures"
+ rendersPackagedPreludeFailures
, testCase "confines exact foundation-leaf completion"
confinesFoundationLeafCompletion
, testCase "builds the confined final prelude"
buildsConfinedFinalPrelude
, testCase "publishes the final prelude as an ordinary sealed root"
publishesFinalPreludeRoot
- , testCase "checks the protected nat closure with the final prelude"
- checksProtectedNatClosure
- , testCase "checks Phase 5.3 library closures with the final prelude"
- checksPhase53LibraryClosures
, testCase "retains exact omitted-proof locations"
retainsExactOmittedProofLocation
, testCase "coalesces syntax without collapsing semantic imports"
coalescesSharedDirectSyntax
- , testCase "resets gloss state between modules"
- resetsGlossStatePerModule
, testCase "makes selected source errors terminal"
rejectsUnsupportedTypedSource
, testCase "compiles exact declarations across an import"
compilesExactDeclarationGraph
+ , testCase "compiles and imports exact structures"
+ compilesExactStructures
+ , testCase "compiles and caches contextual abbreviations"
+ compilesContextualAbbreviations
+ , testCase "rejects an unknown exact structure parent atomically"
+ rejectsUnknownExactStructureParent
, testCase "compiles exact relation expressions"
compilesExactRelationExpressions
, testCase "resolves source-owned set application"
@@ -98,6 +125,8 @@ unitTests =
compilesExactOrdinaryProofs
, testCase "compiles and reuses proof-local set definitions"
compilesAndReusesProofLocalSetDefinitions
+ , testCase "compiles and reuses proof-local function graphs"
+ compilesAndReusesProofLocalFunctionGraphs
, testCase "confines terminal exact contradiction"
confinesTerminalExactContradiction
, testCase "compiles exact separation comprehensions"
@@ -146,9 +175,21 @@ unitTests =
keepsExactSemanticsIndependentOfFixity
, testCase "loads a cached exact producer for a fresh importer"
loadsCachedExactProducerForFreshImporter
+ , testCase "reports admitted source escapes on fresh, warm, and failure paths"
+ reportsAdmittedSourceEscapes
+ , testCase "selects concurrent module failures by source order"
+ selectsConcurrentModuleFailureDeterministically
+ , testCase "batches independent structure obligations atomically"
+ batchesStructureObligationsAtomically
+ , testCase "keeps dependent proof obligations sequential"
+ keepsDependentProofObligationsSequential
+ , testCase "starts diamond consumers after sealed acknowledgements"
+ schedulesDiamondAfterSealedImports
+ , testCase "classifies typed Vampire failures conservatively"
+ classifiesTypedVampireFailures
, testCase "retains the exact prefix before a later failure"
retainsExactPrefixBeforeFailure
- , testCase "routes production verification by complete graph"
+ , testCase "routes every production root through exact checking"
routesProductionVerification
, testCase "installs nonempty implicit prelude evidence"
installsNonemptyImplicitPreludeEvidence
@@ -285,6 +326,30 @@ parsesPackagedFinalPrelude = do
(Syntax.moduleSyntaxAssertedId
(Parse.identifiedParsedModuleSyntaxInterface secondParsed))
+rendersPackagedPreludeFailures :: Assertion
+rendersPackagedPreludeFailures = do
+ assertEqual "load failure"
+ "/missing/felix-prelude.tex: unable to read packaged final prelude: not found"
+ (Prelude.renderPreludeLoadError
+ (Prelude.PreludeSourceReadFailed
+ "/missing/felix-prelude.tex"
+ "not found"))
+ assertEqual "located syntax failure"
+ "<felix-prelude>: syntax pragma location is out of range at 7:3"
+ (Prelude.renderPreludeParseError parseFailure)
+ assertEqual "authority-free API presentation"
+ ("packaged final prelude parsing failed: "
+ <> "<felix-prelude>: syntax pragma location is out of range at 7:3")
+ (Api.renderAuthorityFreeParseError
+ (Api.AuthorityFreePreludeParseFailed parseFailure))
+ where
+ parseFailure =
+ Prelude.PreludeSyntaxPragmaFailed
+ (Pragma.SyntaxPragmaLocationOutOfRange
+ Prelude.preludeDiagnosticLabel
+ 7
+ 3)
+
confinesFoundationLeafCompletion :: Assertion
confinesFoundationLeafCompletion = do
foundation <- expectRight Foundation.checkedFoundation
@@ -387,6 +452,54 @@ buildsConfinedFinalPrelude = do
[]
(Semantic.semanticInterfaceDirectInputs
(FinalPrelude.finalPreludeSemantic candidate))
+ let baseDeltas =
+ [ delta
+ | delta <- Semantic.semanticInterfaceDeclarations
+ (FinalPrelude.finalPreludeSemantic candidate)
+ , not
+ (null
+ (Semantic.semanticEnvironmentStructures
+ (Semantic.declarationDeltaEnvironment delta)))
+ ]
+ case baseDeltas of
+ [delta] -> do
+ assertEqual "base structure has no facts"
+ []
+ (Semantic.declarationDeltaFacts delta)
+ assertEqual "base structure has no propositions"
+ []
+ (Semantic.declarationDeltaPropositions delta)
+ case Semantic.semanticEnvironmentStructures
+ (Semantic.declarationDeltaEnvironment delta) of
+ [descriptor] -> do
+ assertEqual "base structure is metadata-only"
+ Nothing
+ (Semantic.semanticStructureDescriptorPredicate
+ descriptor)
+ case Semantic.semanticStructureDescriptorOperations
+ descriptor of
+ [operation] ->
+ case Identity.lookupCheckedObjectContent
+ (Semantic.semanticStructureOperationObject
+ operation)
+ (FinalPrelude.finalPreludeObjects candidate) of
+ Just Identity.OpaqueObjectContent{} -> pure ()
+ content ->
+ assertFailure
+ ("expected opaque carrier, got "
+ <> show content)
+ operations ->
+ assertFailure
+ ("expected one base operation, got "
+ <> show operations)
+ descriptors ->
+ assertFailure
+ ("expected one base descriptor, got "
+ <> show descriptors)
+ deltas ->
+ assertFailure
+ ("expected one base structure delta, got "
+ <> show (length deltas))
let role roleName =
maybe
(assertFailure
@@ -395,13 +508,13 @@ buildsConfinedFinalPrelude = do
pure
(FinalPrelude.finalPreludePublicRole
candidate roleName)
- omega <- role Migration.PreludeOmegaObject
- naturals <- role Migration.PreludeNaturalsAlias
+ omega <- role FinalPrelude.PreludeOmegaObject
+ naturals <- role FinalPrelude.PreludeNaturalsAlias
assertEqual "naturals expands to Omega"
omega naturals
traverse_
(void . role)
- (Set.toList Migration.expectedFinalPreludePublicRoles)
+ (Set.toList FinalPrelude.expectedFinalPreludePublicRoles)
let foundationTags = Set.fromList
[ tag
| batch <-
@@ -459,518 +572,61 @@ publishesFinalPreludeRoot = do
Store.openStore path theory >>= expectRight
pure store
bracket open Store.closeStore \store -> do
+ freshMemo <- Store.newStoreMemo store
session <-
expectRight
- =<< Module.buildFinalPreludeSession
- store foundation finalPreludeResolver
- let input = Module.migrationPreludeInput session
- sealed = Module.migrationPreludeModule session
+ =<< Module.acquireFinalPreludeSession
+ freshMemo store foundation finalPreludeResolver
+ let input = Module.finalPreludeInput session
+ sealed = Module.finalPreludeModule session
syntax = Module.sealedTypedModuleSyntax sealed
semantic = Module.sealedTypedModuleSemantic sealed
+ assertEqual "empty store constructs the final-prelude root"
+ Module.ModuleRootMiss
+ (Module.finalPreludeAcquisition session)
assertEqual "final prelude owner"
preludeModuleName
(Module.identifiedModuleOwner input)
assertEqual "final prelude has no semantic parents"
[]
(Semantic.semanticInterfaceDirectInputs semantic)
- key <- expectRight
- (Semantic.moduleArtifactKey
- preludeModuleName
- (Parse.identifiedParsedModuleId
- (Module.identifiedModuleParsed input))
- []
- theory)
- memo <- Store.newStoreMemo store
- loaded <- expectRight
- =<< Store.loadCachedModuleInstallation
- memo
- store
- key
- (Syntax.moduleSyntaxAssertedId syntax)
- installation <- maybe
- (assertFailure "final prelude root was not installed"
- >> fail "unreachable")
- pure
- loaded
- cached <- expectRight
- (Module.cachedSealedTypedModule
- foundation [] installation)
+ warmMemo <- Store.newStoreMemo store
+ warmSession <- expectRight
+ =<< Module.acquireFinalPreludeSession
+ warmMemo store foundation unusedResolver
+ let cached = Module.finalPreludeModule warmSession
+ assertEqual "persisted final-prelude root is a cache hit"
+ Module.ModuleRootHit
+ (Module.finalPreludeAcquisition warmSession)
assertEqual "generic root syntax"
syntax
(Module.sealedTypedModuleSyntax cached)
assertEqual "generic root semantics"
semantic
(Module.sealedTypedModuleSemantic cached)
+ assertEqual "cached base structure descriptor"
+ (semanticStructureDescriptors semantic)
+ (semanticStructureDescriptors
+ (Module.sealedTypedModuleSemantic cached))
assertEqual "generic root final prefix"
(Declaration.pendingModulePrefixCurrent
(Module.sealedTypedModulePrefix sealed))
(Declaration.pendingModulePrefixCurrent
(Module.sealedTypedModulePrefix cached))
-
-checksProtectedNatClosure :: Assertion
-checksProtectedNatClosure = do
- foundation <- expectRight Foundation.checkedFoundation
- repository <- getCurrentDirectory
- Temp.withSystemTempDirectory "felix-protected-nat" \directory -> do
- let storePath = directory Posix.</> "store.sqlite"
- executable = directory Posix.</> "vampire"
- writeFile executable
- (unlines
- [ "#!/bin/sh"
- , "cat >/dev/null"
- , "printf '%s\\n' '% SZS status Theorem for protected-core'"
- ])
- permissions <- getPermissions executable
- setPermissions executable
- (setOwnerExecutable True permissions)
- runs <- newIORef (0 :: Int)
- let resolver = countingAcceptedResolver executable runs
- open = do
- (_startup, store) <-
- Store.openStore
- storePath
- (Identity.theoryId foundation)
- >>= expectRight
- pure store
- bracket open Store.closeStore \store -> do
- prelude <-
- expectRight
- =<< Module.buildFinalPreludeSession
- store foundation resolver
- mounts <- exactFixtureMounts repository
- workspace <- parseFinalExactWorkspace prelude mounts "nat.tex"
- sealed <- compileFinalParsedWorkspaceWithResolver
- foundation prelude resolver workspace
- let parsed = toList
- (Parse.parsedWorkspaceImportedBeforeImporter workspace)
- modules = Map.fromList
- [ ( safeRelativePathFilePath
- (resolvedSourceRelativePath
- (Parse.parsedModuleResolved source))
- , checked
- )
- | (source, checked) <- zip parsed sealed
- ]
- moduleAt path = maybe
- (assertFailure ("missing typed module " <> path)
- >> fail "unreachable")
- pure
- (Map.lookup path modules)
- assertEqual "protected module count"
- 5
- (length sealed)
- let preludeSyntaxId =
- Syntax.moduleSyntaxAssertedId
- (Module.sealedTypedModuleSyntax
- (Module.migrationPreludeModule prelude))
- preludeSemanticId =
- Semantic.semanticInterfaceAssertedId
- (Module.sealedTypedModuleSemantic
- (Module.migrationPreludeModule prelude))
- forM_
- (toList
- (Parse.parsedWorkspaceImportedBeforeImporter workspace))
- \parsedModule ->
- assertEqual "final prelude is the first syntax input"
- (Just preludeSyntaxId)
- (listToMaybe
- (Syntax.moduleSyntaxDirectInputs
- (Parse.parsedModuleSyntaxInterface
- parsedModule)))
- forM_ sealed \sealedModule ->
- assertEqual "final prelude is the first semantic input"
- (Just preludeSemanticId)
- (listToMaybe
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic sealedModule)))
- setModule <- moduleAt "set.tex"
- sucModule <- moduleAt "set/suc.tex"
- natModule <- moduleAt "nat.tex"
- assertLocalAliasesAbsent
- setModule
- [ "setext"
- , "emptyset"
- , "unions"
- , "unions_iff"
- ]
- assertLocalAliasesAbsent
- natModule
- [ "num_naturals_inductive_set"
- , "num_naturals_smallest_inductive_set"
- ]
- assertTransparentObjectAlias setModule "cons"
- assertTransparentObjectAlias setModule "union"
- pairIdentity <- localObjectKeyTarget
- setModule
- (Semantic.SemanticExpressionFunction
- (Raw.mixfixPattern Raw.PairSymbol))
- consBody <- localTransparentObjectBody setModule "cons"
- let expectedConsBody =
- Core.CLam Core.TySet
- (Core.CLam Core.TySet
- (Core.canonicalSetInsert
- (Core.CBound 1)
- (Core.CBound 0)))
- assertEqual "cons uses canonical set insertion"
- expectedConsBody consBody
- assertBool "cons does not use ordered pairing"
- ( pairIdentity
- `Set.notMember` Core.canonicalTermGlobals consBody
- )
- let preludeModule = Module.migrationPreludeModule prelude
- preludeSuccessor <-
- localObjectAliasTarget preludeModule "prelude_successor"
- sourceSuccessor <- localObjectAliasTarget sucModule "suc"
- assertEqual "source successor reuses packaged successor content"
- preludeSuccessor sourceSuccessor
- preludeSuccessorBody <-
- localTransparentObjectBody preludeModule "prelude_successor"
- assertEqual "packaged successor uses canonical set insertion"
- (Core.CLam Core.TySet
- (Core.canonicalSetInsert
- (Core.CBound 0)
- (Core.CBound 0)))
- preludeSuccessorBody
- assertBool "successor does not use ordered pairing"
- ( pairIdentity
- `Set.notMember`
- Core.canonicalTermGlobals preludeSuccessorBody
- )
- assertOpaqueObjectKey
- setModule
- "pair"
- (Semantic.SemanticExpressionFunction
- (Raw.mixfixPattern Raw.PairSymbol))
- assertCleanFactAlias setModule "cons_iff"
- assertCleanFactAlias setModule "union_iff"
- traverse_
- (assertSourceAxiomAlias setModule)
- [ "pair_eq_iff"
- , "fst_eq"
- , "snd_eq"
- ]
- assertBool "protected checking exercised Vampire"
- . (> 0)
- =<< readIORef runs
-
-checksPhase53LibraryClosures :: Assertion
-checksPhase53LibraryClosures = do
- foundation <- expectRight Foundation.checkedFoundation
- repository <- getCurrentDirectory
- Temp.withSystemTempDirectory "felix-phase53-library" \directory -> do
- let storePath = directory Posix.</> "store.sqlite"
- executable = directory Posix.</> "vampire"
- writeFile executable
- (unlines
- [ "#!/bin/sh"
- , "cat >/dev/null"
- , "printf '%s\\n' '% SZS status Theorem for phase53-library'"
- ])
- permissions <- getPermissions executable
- setPermissions executable
- (setOwnerExecutable True permissions)
- runs <- newIORef (0 :: Int)
- let resolver = countingAcceptedResolver executable runs
- bracket
- (snd <$> (Store.openStore storePath
- (Identity.theoryId foundation) >>= expectRight))
- Store.closeStore
- \store -> do
- prelude <-
- expectRight
- =<< Module.buildFinalPreludeSession
- store foundation resolver
- mounts <- exactFixtureMounts repository
- selection <- expectRight
- (Migration.resolveMigrationSelection
- mounts Migration.typedMigrationModules)
- let preludeSyntaxId = Syntax.moduleSyntaxAssertedId
- (Module.sealedTypedModuleSyntax
- (Module.migrationPreludeModule prelude))
- preludeSemanticId =
- Semantic.semanticInterfaceAssertedId
- (Module.sealedTypedModuleSemantic
- (Module.migrationPreludeModule prelude))
- checkRoot path inspect = do
- workspace <- parseFinalExactWorkspace
- prelude mounts path
- assertEqual (path <> " graph route")
- Migration.TypedMigrationGraph
- (Migration.classifyMigrationGraph
- selection workspace)
- sealed <- compileFinalParsedWorkspaceWithResolver
- foundation prelude resolver workspace
- let parsed = toList
- (Parse.parsedWorkspaceImportedBeforeImporter
- workspace)
- modules = Map.fromList
- [ ( safeRelativePathFilePath
- (resolvedSourceRelativePath
- (Parse.parsedModuleResolved source))
- , (source, checked)
- )
- | (source, checked) <- zip parsed sealed
- ]
- moduleAt modulePath = maybe
- (assertFailure
- ("missing typed module " <> modulePath)
- >> fail "unreachable")
- pure
- (Map.lookup modulePath modules)
- assertEqual (path <> " module count")
- (length parsed)
- (length sealed)
- forM_ parsed \source ->
- assertEqual
- (path <> " final-prelude syntax input")
- (Just preludeSyntaxId)
- (listToMaybe
- (Syntax.moduleSyntaxDirectInputs
- (Parse.parsedModuleSyntaxInterface
- source)))
- forM_ sealed \checked ->
- assertEqual
- (path <> " final-prelude semantic input")
- (Just preludeSemanticId)
- (listToMaybe
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- checked)))
- inspect moduleAt
- unselectedImporter <- parseFinalExactWorkspace
- prelude mounts "set/equinumerosity.tex"
- assertEqual "unselected function importer graph route"
- Migration.LegacyMigrationGraph
- (Migration.classifyMigrationGraph
- selection unselectedImporter)
- checkRoot "set/bipartition.tex"
- \moduleAt -> do
- (_setParsed, setModule) <- moduleAt "set.tex"
- (_consParsed, consModule) <-
- moduleAt "set/cons.tex"
- (_powersetParsed, powersetModule) <-
- moduleAt "set/powerset.tex"
- (_bipartitionParsed, bipartitionModule) <-
- moduleAt "set/bipartition.tex"
- assertLocalAliasesAbsent powersetModule ["pow_iff"]
- assertEqual "bipartition semantic imports"
- [ preludeSemanticId
- , semanticId setModule
- , semanticId consModule
- , semanticId powersetModule
- ]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- bipartitionModule))
- assertFactAliasEscapeKind
- bipartitionModule
- "bipartition_elim"
- Authority.SourceAxiom
- checkRoot "set/product.tex"
- \moduleAt -> do
- (_setParsed, setModule) <- moduleAt "set.tex"
- (_productParsed, productModule) <-
- moduleAt "set/product.tex"
- assertEqual "product semantic imports"
- [preludeSemanticId, semanticId setModule]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- productModule))
- assertFactAliasEscapeKind
- productModule
- "inter_times_intro"
- Authority.SourceAxiom
- checkRoot "set/filter.tex"
- \moduleAt -> do
- (_setParsed, setModule) <- moduleAt "set.tex"
- (_powersetParsed, powersetModule) <-
- moduleAt "set/powerset.tex"
- (_filterParsed, filterModule) <-
- moduleAt "set/filter.tex"
- assertEqual "filter semantic imports"
- [ preludeSemanticId
- , semanticId setModule
- , semanticId powersetModule
- ]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic filterModule))
- assertAllLocalFactsClean filterModule
- checkRoot "relation.tex"
- \moduleAt -> do
- (_setParsed, setModule) <- moduleAt "set.tex"
- (_powersetParsed, powersetModule) <-
- moduleAt "set/powerset.tex"
- (_productParsed, productModule) <-
- moduleAt "set/product.tex"
- (_relationParsed, relationModule) <-
- moduleAt "relation.tex"
- assertEqual "relation semantic imports"
- [ preludeSemanticId
- , semanticId setModule
- , semanticId powersetModule
- , semanticId productModule
- ]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- relationModule))
- assertCleanFactAlias
- relationModule
- "union_relations_is_relation"
- assertFactAliasEscapeKind
- relationModule
- "id_iff"
- Authority.SourceAxiom
- assertNoLocalFactEscapeKind
- relationModule
- Authority.Omitted
- checkRoot "relation/properties.tex"
- \moduleAt -> do
- (_setParsed, setModule) <- moduleAt "set.tex"
- (_relationParsed, relationModule) <-
- moduleAt "relation.tex"
- (_propertiesParsed, propertiesModule) <-
- moduleAt "relation/properties.tex"
- assertEqual "relation properties semantic imports"
- [ preludeSemanticId
- , semanticId setModule
- , semanticId relationModule
- ]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- propertiesModule))
- assertCleanFactAlias
- propertiesModule
- "asymmetric_implies_irreflexive"
- assertNoLocalFactEscapeKind
- propertiesModule
- Authority.Omitted
- assertNoLocalSourceAxiom propertiesModule
- checkRoot "relation/uniqueness.tex"
- \moduleAt -> do
- (_setParsed, setModule) <- moduleAt "set.tex"
- (_relationParsed, relationModule) <-
- moduleAt "relation.tex"
- (_uniquenessParsed, uniquenessModule) <-
- moduleAt "relation/uniqueness.tex"
- assertEqual "relation uniqueness semantic imports"
- [ preludeSemanticId
- , semanticId setModule
- , semanticId relationModule
- ]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- uniquenessModule))
- assertCleanFactAlias
- uniquenessModule
- "subseteq_of_injective_is_injective"
- assertFactAliasEscapeKind
- uniquenessModule
- "identity_injective"
- Authority.SourceAxiom
- assertNoLocalFactEscapeKind
- uniquenessModule
- Authority.Omitted
- assertNoLocalSourceAxiom uniquenessModule
- checkRoot "function.tex"
- \moduleAt -> do
- (_setParsed, setModule) <- moduleAt "set.tex"
- (_relationParsed, relationModule) <-
- moduleAt "relation.tex"
- (_uniquenessParsed, uniquenessModule) <-
- moduleAt "relation/uniqueness.tex"
- (_functionParsed, functionModule) <-
- moduleAt "function.tex"
- assertEqual "function semantic imports"
- [ preludeSemanticId
- , semanticId setModule
- , semanticId relationModule
- , semanticId uniquenessModule
- ]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- functionModule))
- assertCleanFactAlias
- functionModule
- "function_on_weaken_codom"
- assertFactAliasEscapeKind
- functionModule
- "function_apply_intro"
- Authority.SourceAxiom
- assertFactAliasEscapeKind
- functionModule
- "funs_circ"
- Authority.Omitted
- assertLocalDirectAuthorizationCount
- functionModule
- Authority.OmittedAuthorization
- 6
- assertNoLocalSourceAxiom functionModule
- checkRoot "set/cantor.tex"
- \moduleAt -> do
- (_powersetParsed, powersetModule) <-
- moduleAt "set/powerset.tex"
- (_functionParsed, functionModule) <-
- moduleAt "function.tex"
- (_cantorParsed, cantorModule) <-
- moduleAt "set/cantor.tex"
- assertEqual "Cantor semantic imports"
- [ preludeSemanticId
- , semanticId powersetModule
- , semanticId functionModule
- ]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- cantorModule))
- assertCleanFactAlias cantorModule "cantor"
- assertNoLocalFactEscapeKind
- cantorModule Authority.Omitted
- assertNoLocalSourceAxiom cantorModule
- checkRoot "set/fixpoint.tex"
- \moduleAt -> do
- (_powersetParsed, powersetModule) <-
- moduleAt "set/powerset.tex"
- (_functionParsed, functionModule) <-
- moduleAt "function.tex"
- (_fixpointParsed, fixpointModule) <-
- moduleAt "set/fixpoint.tex"
- assertEqual "fixpoint semantic imports"
- [ preludeSemanticId
- , semanticId powersetModule
- , semanticId functionModule
- ]
- (Semantic.semanticInterfaceDirectInputs
- (Module.sealedTypedModuleSemantic
- fixpointModule))
- assertCleanFactAlias fixpointModule "fixpoint"
- assertCleanFactAlias
- fixpointModule "subseteqpreserving"
- assertFactAliasEscapeKind
- fixpointModule
- "knastertarski"
- Authority.SourceAxiom
- assertNoLocalFactEscapeKind
- fixpointModule Authority.Omitted
- assertNoLocalSourceAxiom fixpointModule
- where
- semanticId =
- Semantic.semanticInterfaceAssertedId
- . Module.sealedTypedModuleSemantic
-
-assertLocalAliasesAbsent
- :: Module.SealedTypedModule
- -> [Text]
- -> Assertion
-assertLocalAliasesAbsent sealed names =
- forM_ names \name ->
- assertBool
- ("protected module still publishes " <> show name)
- (Semantic.semanticName name `notElem` aliases)
- where
- aliases =
- [ Semantic.semanticAliasName alias
- | delta <- localSemanticDeltas sealed
- , alias <- Semantic.declarationDeltaAliases delta
- ]
+ visits <- Store.storeMemoVisits warmMemo
+ assertEqual "cached prelude validates one artifact root"
+ 1
+ (Store.storeArtifactsValidated visits)
+
+semanticStructureDescriptors
+ :: Semantic.SemanticInterface
+ -> [Semantic.SemanticStructureDescriptor]
+semanticStructureDescriptors semantic =
+ [ descriptor
+ | delta <- Semantic.semanticInterfaceDeclarations semantic
+ , descriptor <- Semantic.semanticEnvironmentStructures
+ (Semantic.declarationDeltaEnvironment delta)
+ ]
assertTransparentObjectAlias
:: Module.SealedTypedModule
@@ -983,18 +639,6 @@ assertTransparentObjectAlias sealed name = do
Identity.TransparentObject
(Identity.objectIdFamily target)
-assertOpaqueObjectKey
- :: Module.SealedTypedModule
- -> Text
- -> Semantic.SemanticGlobalKey
- -> Assertion
-assertOpaqueObjectKey sealed name key = do
- target <- localObjectKeyTarget sealed key
- assertEqual
- ("opaque object for " <> StrictText.unpack name)
- Identity.OpaqueObject
- (Identity.objectIdFamily target)
-
localObjectKeyTarget
:: Module.SealedTypedModule
-> Semantic.SemanticGlobalKey
@@ -1026,29 +670,6 @@ localObjectAliasTarget sealed name = do
(Semantic.semanticGlobalTargetObject
(Semantic.semanticGlobalBindingTarget binding))
-localTransparentObjectBody
- :: Module.SealedTypedModule
- -> Text
- -> IO (Core.CanonicalTerm Identity.ObjectId)
-localTransparentObjectBody sealed name = do
- identity <- localObjectAliasTarget sealed name
- object <- sole
- ("asserted object for " <> StrictText.unpack name)
- [ candidate
- | batch <- Declaration.pendingModulePrefixBatches
- (Module.sealedTypedModulePrefix sealed)
- , candidate <- Declaration.committedBatchObjects batch
- , Identity.assertedObjectId candidate == identity
- ]
- case Identity.assertedObjectContent object of
- Identity.TransparentObjectContent _theory _coreType body ->
- pure body
- content ->
- assertFailure
- ("object for " <> StrictText.unpack name
- <> " is not transparent: " <> show content)
- >> fail "unreachable"
-
checkedPropositionTermByAlias
:: Module.SealedTypedModule
-> Text
@@ -1057,30 +678,31 @@ checkedPropositionTermByAlias sealed name = do
batch <- batchByAlias
(Module.sealedTypedModulePrefix sealed)
name
+ alias <- sole
+ ("semantic alias for " <> StrictText.unpack name)
+ [ candidate
+ | candidate <- Semantic.declarationDeltaAliases
+ (Declaration.committedBatchDelta batch)
+ , Semantic.semanticAliasName candidate
+ == Semantic.semanticName name
+ ]
+ occurrence <- sole
+ ("semantic fact for " <> StrictText.unpack name)
+ [ candidate
+ | candidate <- Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta batch)
+ , Semantic.semanticFactFingerprint candidate
+ == Semantic.semanticAliasTarget alias
+ ]
proposition <- sole
("checked proposition for " <> StrictText.unpack name)
- (Declaration.committedBatchPropositions batch)
+ [ candidate
+ | candidate <- Declaration.committedBatchPropositions batch
+ , Identity.checkedPropositionId candidate
+ == Semantic.semanticFactProposition occurrence
+ ]
pure (Identity.checkedPropositionTerm proposition)
-assertFactAliasEscapeKind
- :: Module.SealedTypedModule
- -> Text
- -> Authority.EscapeKind
- -> Assertion
-assertFactAliasEscapeKind sealed name expected = do
- delta <- localDeltaByAlias sealed name
- fact <- sole
- ("semantic fact for " <> StrictText.unpack name)
- (Semantic.declarationDeltaFacts delta)
- assertBool
- ("escape authority for " <> StrictText.unpack name)
- ( expected
- `elem` Authority.escapeKindsToList
- (Authority.authoritySafetyEscapeKinds
- (Authority.factAuthoritySafety
- (Semantic.semanticFactAuthority fact)))
- )
-
assertCleanFactAlias
:: Module.SealedTypedModule
-> Text
@@ -1107,114 +729,6 @@ assertCleanFactAlias sealed name = do
(Authority.factAuthoritySafety
(Semantic.semanticFactAuthority fact))
-assertAllLocalFactsClean
- :: Module.SealedTypedModule
- -> Assertion
-assertAllLocalFactsClean sealed =
- assertBool
- "all locally published facts have clean authority"
- (all hasCleanAuthority localFacts)
- where
- localFacts =
- [ fact
- | delta <- localSemanticDeltas sealed
- , fact <- Semantic.declarationDeltaFacts delta
- ]
- hasCleanAuthority fact =
- Authority.factAuthoritySafety
- (Semantic.semanticFactAuthority fact)
- == Authority.cleanAuthoritySafety
-
-assertNoLocalFactEscapeKind
- :: Module.SealedTypedModule
- -> Authority.EscapeKind
- -> Assertion
-assertNoLocalFactEscapeKind sealed unexpected =
- assertBool
- ("no local fact has " <> show unexpected <> " authority")
- (all lacksEscapeKind localFacts)
- where
- localFacts =
- [ fact
- | delta <- localSemanticDeltas sealed
- , fact <- Semantic.declarationDeltaFacts delta
- ]
- lacksEscapeKind fact =
- unexpected
- `notElem` Authority.escapeKindsToList
- (Authority.authoritySafetyEscapeKinds
- (Authority.factAuthoritySafety
- (Semantic.semanticFactAuthority fact)))
-
-assertNoLocalSourceAxiom
- :: Module.SealedTypedModule
- -> Assertion
-assertNoLocalSourceAxiom sealed =
- assertBool
- "module introduces no source axiom"
- (all (/= Authority.SourceAxiomAuthorization) directAuthorizations)
- where
- directAuthorizations =
- [ Authority.validationDirectAuthorization certificate
- | batch <- Declaration.pendingModulePrefixBatches
- (Module.sealedTypedModulePrefix sealed)
- , validation <- maybeToList
- (Declaration.committedBatchDeclarationValidation batch)
- , certificate <-
- Semantic.declarationValidationRecordCertificates validation
- ]
-
-assertLocalDirectAuthorizationCount
- :: Module.SealedTypedModule
- -> Authority.DirectAuthorization
- -> Int
- -> Assertion
-assertLocalDirectAuthorizationCount sealed expected expectedCount =
- assertEqual
- ("local " <> show expected <> " authorization count")
- expectedCount
- (length
- [ ()
- | batch <- Declaration.pendingModulePrefixBatches
- (Module.sealedTypedModulePrefix sealed)
- , validation <- Declaration.committedBatchProofValidations batch
- , Authority.validationDirectAuthorization
- (Semantic.proofValidationRecordCertificate validation)
- == expected
- ])
-
-assertSourceAxiomAlias
- :: Module.SealedTypedModule
- -> Text
- -> Assertion
-assertSourceAxiomAlias sealed name = do
- batch <- batchByAlias
- (Module.sealedTypedModulePrefix sealed)
- name
- fact <- sole
- ("source axiom fact " <> StrictText.unpack name)
- (Semantic.declarationDeltaFacts
- (Declaration.committedBatchDelta batch))
- assertEqual
- ("source axiom safety for " <> StrictText.unpack name)
- (Authority.authoritySafety
- (Authority.singletonEscapeKind Authority.SourceAxiom))
- (Authority.factAuthoritySafety
- (Semantic.semanticFactAuthority fact))
- validation <- maybe
- (assertFailure
- ("source axiom validation for " <> StrictText.unpack name)
- >> fail "unreachable")
- pure
- (Declaration.committedBatchDeclarationValidation batch)
- certificate <- sole
- ("source axiom certificate for " <> StrictText.unpack name)
- (Semantic.declarationValidationRecordCertificates validation)
- assertEqual
- ("source axiom authority for " <> StrictText.unpack name)
- Authority.SourceAxiomAuthorization
- (Authority.validationDirectAuthorization certificate)
-
batchByAlias
:: Declaration.PendingModulePrefix
-> Text
@@ -1350,18 +864,10 @@ coalescesSharedDirectSyntax = do
, (sourceMountId "library", root Posix.</> "library")
, (sourceMountId "debug", root Posix.</> "debug")
]
- selection <-
- expectRight
- (Migration.resolveMigrationSelection
- mounts
- Migration.typedMigrationModules)
let bootstrapSyntax =
Module.sealedTypedModuleSyntax
(Module.bootstrapPreludeModule session)
- syntaxInputs source
- | Migration.migrationSelectionContains selection source =
- [bootstrapSyntax]
- | otherwise = []
+ syntaxInputs _source = [bootstrapSyntax]
request <-
expectRight
(searchedRoot "test/phase3/typed-shared-root.tex")
@@ -1371,9 +877,6 @@ coalescesSharedDirectSyntax = do
mounts
request
syntaxInputs
- assertEqual "selected shared-syntax graph"
- Migration.TypedMigrationGraph
- (Migration.classifyMigrationGraph selection workspace)
case Parse.parsedWorkspaceModules workspace of
[firstParsed, secondParsed, rootParsed] -> do
first <- seal foundation session firstParsed []
@@ -1436,31 +939,6 @@ coalescesSharedDirectSyntax = do
assertFailure "empty typed module did not seal"
>> fail "unreachable"
-resetsGlossStatePerModule :: Assertion
-resetsGlossStatePerModule = do
- blocks <- Api.gloss "test/phase3/gloss-root.tex"
- binders <- traverse signatureBinder blocks
- assertEqual "fresh variables restart at each module boundary"
- [Internal.FreshVar 0, Internal.FreshVar 0, Internal.FreshVar 1]
- binders
- where
- signatureBinder = \case
- Internal.BlockSig
- _location
- _marker
- _assumptions
- (Internal.SignatureFormula
- (Internal.Quantified Internal.Universally scope)) ->
- case nubOrd [binder | B binder <- toList (fromScope scope)] of
- [binder] -> pure binder
- binders ->
- assertFailure
- ("unexpected signature binders: " <> show binders)
- >> fail "unreachable"
- block ->
- assertFailure ("unexpected glossed block: " <> show block)
- >> fail "unreachable"
-
rejectsUnsupportedTypedSource :: Assertion
rejectsUnsupportedTypedSource = do
result <-
@@ -1472,13 +950,16 @@ rejectsUnsupportedTypedSource = do
Provers.defaultMemoryLimit)
"test/phase3/typed-unsupported.tex")
case result of
- Left
- (failure@(Api.VerificationTypedModuleError
+ Right
+ ( Api.VerificationCheckingFailure _report
+ (failure@(Api.VerificationTypedModuleError
source
(Module.TypedActionFailed
(Module.TypedExactCompileFailed
(Exact.ExactUnsupportedDeclarationBody location)))
- prefix)) -> do
+ prefix))
+ , _measurements
+ ) -> do
assertEqual "failed source"
"test/phase3/typed-unsupported.tex"
(safeRelativePathFilePath
@@ -1670,6 +1151,566 @@ compilesExactDeclarationGraph = do
Identity.TransparentObjectContent{} -> "transparent"
Identity.IntrinsicObjectContent{} -> "intrinsic"
+compilesExactStructures :: Assertion
+compilesExactStructures = do
+ foundation <- expectRight Foundation.checkedFoundation
+ repository <- getCurrentDirectory
+ Temp.withSystemTempDirectory "felix-exact-structures" \directory -> do
+ let path = directory Posix.</> "store.sqlite"
+ executable = directory Posix.</> "vampire"
+ writeAcceptedFixtureVampire executable
+ runs <- newIORef (0 :: Int)
+ let resolver = countingAcceptedResolver executable runs
+ (_startup, store) <-
+ Store.openStore path (Identity.theoryId foundation)
+ >>= expectRight
+ bracket (pure store) Store.closeStore \opened -> do
+ prelude <-
+ expectRight
+ =<< acquireFinalPreludeSession
+ opened foundation resolver
+ carrierOperation <- sole "base carrier operation"
+ [ operation
+ | descriptor <- semanticStructureDescriptors
+ (Module.sealedTypedModuleSemantic
+ (Module.finalPreludeModule prelude))
+ , operation <-
+ Semantic.semanticStructureDescriptorOperations descriptor
+ ]
+ mounts <- exactFixtureMounts repository
+ workspace <- parseFinalExactWorkspace
+ prelude mounts "test/phase5/exact-structure-child.tex"
+ sealed <- compileFinalParsedWorkspaceWithResolver
+ foundation prelude resolver workspace
+ freshRuns <- readIORef runs
+ warm <- installAndLoadStructures
+ opened foundation prelude workspace sealed
+ warmRuns <- readIORef runs
+ assertEqual "warm structures preserve descriptors"
+ (structureDescriptors <$> sealed)
+ (structureDescriptors <$> warm)
+ assertEqual "warm structures make no prover calls"
+ freshRuns warmRuns
+ case sealed of
+ [parent, child] -> do
+ let parentBatches =
+ Declaration.pendingModulePrefixBatches
+ (Module.sealedTypedModulePrefix parent)
+ parentDeltas =
+ Semantic.semanticInterfaceDeclarations
+ (Module.sealedTypedModuleSemantic parent)
+ childBatches =
+ Declaration.pendingModulePrefixBatches
+ (Module.sealedTypedModulePrefix child)
+ childDeltas =
+ Semantic.semanticInterfaceDeclarations
+ (Module.sealedTypedModuleSemantic child)
+ parentBatch <- sole "parent structure batch"
+ (take 1 parentBatches)
+ parentDelta <- sole "parent structure delta"
+ (take 1 parentDeltas)
+ parentDescriptor <- sole "parent structure descriptor"
+ (Semantic.semanticEnvironmentStructures
+ (Semantic.declarationDeltaEnvironment parentDelta))
+ parentOperation <- sole "parent structure operation"
+ (Semantic.semanticStructureDescriptorOperations
+ parentDescriptor)
+ parentPredicate <-
+ maybe
+ (assertFailure "parent structure has no predicate"
+ >> fail "unreachable")
+ pure
+ (Semantic.semanticStructureDescriptorPredicate
+ parentDescriptor)
+ assertEqual "structure object family order"
+ ["opaque", "transparent"]
+ [ objectFamilyName
+ (Identity.assertedObjectContent object)
+ | object <- Declaration.committedBatchObjects parentBatch
+ ]
+ assertEqual "structure fact aliases"
+ [ Semantic.semanticName "pointed_set"
+ , Semantic.semanticName "pointed_refl"
+ ]
+ (Semantic.semanticAliasName
+ <$> Semantic.declarationDeltaAliases parentDelta)
+ definitionFact <- sole "structure definition fact"
+ (take 1 (Semantic.declarationDeltaFacts parentDelta))
+ definitionTarget <-
+ targetForOccurrence parentBatch definitionFact
+ assertEqual "pointwise structure definition"
+ (Core.CForall Core.TySet
+ (Core.CEq Core.TyProp
+ (Core.CApp
+ (Core.CGlobal parentPredicate)
+ (Core.CBound 0))
+ (Core.CEq Core.TySet
+ (Core.CBound 0)
+ (Core.CBound 0))))
+ definitionTarget
+ validations <-
+ maybe
+ (assertFailure "structure validation is absent"
+ >> fail "unreachable")
+ (pure
+ . Semantic.declarationValidationRecordCertificates)
+ (Declaration.committedBatchDeclarationValidation
+ parentBatch)
+ case validations of
+ definitionValidation : projectionValidation : [] -> do
+ assertEqual "structure definition authority"
+ (Authority.CheckedKernelConstruction
+ (Authority.CheckedDefinitionEquation
+ parentPredicate))
+ (Authority.validationDirectAuthorization
+ definitionValidation)
+ projectionFact <- sole
+ "structure projection fact"
+ (drop 1
+ (Semantic.declarationDeltaFacts
+ parentDelta))
+ assertEqual
+ "projection has independent authority"
+ (Semantic.semanticFactAuthority projectionFact)
+ (Authority.validationTarget
+ projectionValidation)
+ assertEqual "projection authority is clean"
+ Authority.cleanAuthoritySafety
+ (Authority.factAuthoritySafety
+ (Authority.validationTarget
+ projectionValidation))
+ records ->
+ assertFailure
+ ("expected two structure validations, got "
+ <> show records)
+ assertBool "all parent structure facts are clean"
+ (all
+ ((== Authority.cleanAuthoritySafety)
+ . Authority.factAuthoritySafety
+ . Semantic.semanticFactAuthority)
+ (Semantic.declarationDeltaFacts parentDelta))
+
+ let claimGlobals marker = do
+ batch <- batchWithAlias marker parentBatches
+ occurrence <- sole (marker <> " occurrence")
+ (Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta batch))
+ Core.canonicalTermGlobals
+ <$> targetForOccurrence batch occurrence
+ carrierGlobals <- claimGlobals "pointed_carrier"
+ operationGlobals <- claimGlobals "pointed_operation"
+ assertBool "membership uses inherited carrier"
+ (Semantic.semanticStructureOperationObject carrierOperation
+ `Set.member` carrierGlobals)
+ assertBool "implicit and explicit operation share one object"
+ (Semantic.semanticStructureOperationObject parentOperation
+ `Set.member` operationGlobals)
+
+ childBatch <- sole "child structure batch" childBatches
+ childDelta <- sole "child structure delta" childDeltas
+ childDescriptor <- sole "child structure descriptor"
+ (Semantic.semanticEnvironmentStructures
+ (Semantic.declarationDeltaEnvironment childDelta))
+ assertEqual "child allocates no replacement operation"
+ []
+ (Semantic.semanticStructureDescriptorOperations
+ childDescriptor)
+ assertEqual "child owns only its transparent predicate"
+ ["transparent"]
+ [ objectFamilyName
+ (Identity.assertedObjectContent object)
+ | object <- Declaration.committedBatchObjects childBatch
+ ]
+ modules ->
+ assertFailure
+ ("expected parent and child structures, got "
+ <> show (length modules))
+ where
+ installAndLoadStructures store foundation prelude workspace sealed = do
+ memo <- Store.newStoreMemo store
+ case
+ ( toList
+ (Parse.parsedWorkspaceImportedBeforeImporter workspace)
+ , sealed
+ ) of
+ ([parentParsed, childParsed], [parent, child]) -> do
+ cachedParent <- persistAndLoad memo [] parentParsed parent
+ cachedChild <- persistAndLoad
+ memo [cachedParent] childParsed child
+ pure [cachedParent, cachedChild]
+ (parsed, modules) ->
+ assertFailure
+ ("expected two structure installations, got "
+ <> show (length parsed)
+ <> " parsed and "
+ <> show (length modules)
+ <> " checked modules")
+ >> fail "unreachable"
+ where
+ preludeModule = Module.finalPreludeModule prelude
+
+ persistAndLoad memo parents parsed sealedModule = do
+ let input = Module.identifiedPhysicalModule parsed
+ syntax = Module.sealedTypedModuleSyntax sealedModule
+ semantic = Module.sealedTypedModuleSemantic sealedModule
+ key <- expectRight
+ (Semantic.moduleArtifactKey
+ (Module.identifiedModuleOwner input)
+ (Parse.identifiedParsedModuleId
+ (Module.identifiedModuleParsed input))
+ (Semantic.semanticInterfaceDirectInputs semantic)
+ (Identity.theoryId foundation))
+ let artifact = Semantic.moduleArtifactResult
+ key
+ (Syntax.moduleSyntaxAssertedId syntax)
+ (Semantic.semanticInterfaceAssertedId semantic)
+ acknowledged <- expectRight
+ =<< Store.writeSealedModule
+ store
+ (Module.sealedTypedModulePrefix sealedModule)
+ [syntax]
+ [semantic]
+ artifact
+ assertEqual "cached structure artifact acknowledgement"
+ artifact acknowledged
+ loaded <- expectRight
+ =<< Store.loadCachedModuleInstallation
+ memo
+ store
+ key
+ (Syntax.moduleSyntaxAssertedId
+ (Parse.parsedModuleSyntaxInterface parsed))
+ installation <- maybe
+ (assertFailure "cached structure installation is absent"
+ >> fail "unreachable")
+ pure
+ loaded
+ expectRight
+ (Module.cachedSealedTypedModule
+ foundation
+ (preludeModule : parents)
+ installation)
+
+ structureDescriptors =
+ semanticStructureDescriptors
+ . Module.sealedTypedModuleSemantic
+
+ objectFamilyName :: Identity.ObjectContent -> String
+ objectFamilyName = \case
+ Identity.OpaqueObjectContent{} -> "opaque"
+ Identity.TransparentObjectContent{} -> "transparent"
+ Identity.IntrinsicObjectContent{} -> "intrinsic"
+
+ targetForOccurrence batch occurrence =
+ maybe
+ (assertFailure "structure proposition is absent"
+ >> fail "unreachable")
+ (pure . Core.frozenCoreTerm . Identity.checkedPropositionTerm)
+ (find
+ ((== Semantic.semanticFactProposition occurrence)
+ . Identity.checkedPropositionId)
+ (Declaration.committedBatchPropositions batch))
+
+ batchWithAlias marker batches =
+ maybe
+ (assertFailure ("missing batch alias " <> marker)
+ >> fail "unreachable")
+ pure
+ (find
+ (elem (Semantic.semanticName (StrictText.pack marker))
+ . fmap Semantic.semanticAliasName
+ . Semantic.declarationDeltaAliases
+ . Declaration.committedBatchDelta)
+ batches)
+
+compilesContextualAbbreviations :: Assertion
+compilesContextualAbbreviations = do
+ foundation <- expectRight Foundation.checkedFoundation
+ repository <- getCurrentDirectory
+ Temp.withSystemTempDirectory "felix-contextual-abbreviation" \directory -> do
+ let storePath = directory Posix.</> "store.sqlite"
+ executable = directory Posix.</> "vampire"
+ relative = "test/phase5/exact-contextual-abbreviation.tex"
+ writeAcceptedFixtureVampire executable
+ runs <- newIORef (0 :: Int)
+ let resolver = countingAcceptedResolver executable runs
+ (_startup, store) <-
+ Store.openStore storePath (Identity.theoryId foundation)
+ >>= expectRight
+ bracket (pure store) Store.closeStore \opened -> do
+ prelude <-
+ expectRight
+ =<< acquireFinalPreludeSession
+ opened foundation resolver
+ mounts <- exactFixtureMounts repository
+ workspace <- parseFinalExactWorkspace prelude mounts relative
+ sealed <- sole "contextual abbreviation module"
+ =<< compileFinalParsedWorkspaceWithResolver
+ foundation prelude resolver workspace
+ let deltas =
+ Semantic.semanticInterfaceDeclarations
+ (Module.sealedTypedModuleSemantic sealed)
+ contextualTargets =
+ [ (identity, requirements)
+ | delta <- deltas
+ , binding <- Semantic.semanticEnvironmentBindings
+ (Semantic.declarationDeltaEnvironment delta)
+ , Semantic.ContextualTransparentExpansion
+ identity requirements <-
+ [Semantic.semanticGlobalBindingTarget binding]
+ ]
+ assertEqual "contextual target count" 2
+ (length contextualTargets)
+ requirements <-
+ sole "canonical contextual requirement set"
+ (nubOrd (snd <$> contextualTargets))
+ assertEqual "one structure operation requirement" 1
+ (Map.size requirements)
+ let batches =
+ Declaration.pendingModulePrefixBatches
+ (Module.sealedTypedModulePrefix sealed)
+ traverse_
+ (assertReflexiveFact batches)
+ [ "phase5_context_dot_explicit"
+ , "phase5_context_inherited"
+ , "phase5_context_nested"
+ , "phase5_context_explicit_unique"
+ ]
+
+ parsed <- pure (Parse.parsedWorkspaceRootModule workspace)
+ let syntax = Module.sealedTypedModuleSyntax sealed
+ semantic = Module.sealedTypedModuleSemantic sealed
+ key <- expectRight
+ (Semantic.moduleArtifactKey
+ (moduleName (Parse.parsedModuleAddress parsed))
+ (Parse.parsedModuleId parsed)
+ (Semantic.semanticInterfaceDirectInputs semantic)
+ (Identity.theoryId foundation))
+ let artifact =
+ Semantic.moduleArtifactResult
+ key
+ (Syntax.moduleSyntaxAssertedId syntax)
+ (Semantic.semanticInterfaceAssertedId semantic)
+ void
+ (expectRight
+ =<< Store.writeSealedModule
+ opened
+ (Module.sealedTypedModulePrefix sealed)
+ [syntax]
+ [semantic]
+ artifact)
+ memo <- Store.newStoreMemo opened
+ loaded <- expectRight
+ =<< Store.loadCachedModuleInstallation
+ memo opened key
+ (Syntax.moduleSyntaxAssertedId
+ (Parse.parsedModuleSyntaxInterface parsed))
+ installation <- maybe
+ (assertFailure "contextual cached installation is absent"
+ >> fail "unreachable")
+ pure
+ loaded
+ cached <- expectRight
+ (Module.cachedSealedTypedModule
+ foundation
+ [Module.finalPreludeModule prelude]
+ installation)
+ assertEqual "cached contextual semantic target"
+ semantic
+ (Module.sealedTypedModuleSemantic cached)
+
+ runsBeforeConsumer <- readIORef runs
+ consumerWorkspace <-
+ parseFinalExactWorkspace prelude mounts
+ "test/phase5/exact-contextual-abbreviation-consumer.tex"
+ let consumerParsed =
+ Parse.parsedWorkspaceRootModule consumerWorkspace
+ consumerInput <- expectRight
+ (Module.typedModuleInput
+ foundation
+ (Module.finalPreludeReadiness prelude)
+ resolver
+ Declaration.FreshValidation
+ consumerParsed
+ [cached])
+ consumer <- Module.runTypedModule consumerInput >>= \case
+ Module.TypedModuleSucceeded sealedConsumer ->
+ pure sealedConsumer
+ Module.TypedModuleOpenFailed failure ->
+ assertFailure
+ ("contextual consumer did not open: " <> show failure)
+ >> fail "unreachable"
+ Module.TypedModuleFailed failure _prefix ->
+ assertFailure
+ ("contextual consumer did not seal: " <> show failure)
+ >> fail "unreachable"
+ let consumerTargets =
+ [ Semantic.semanticGlobalTargetObject
+ (Semantic.semanticGlobalBindingTarget binding)
+ | delta <- localSemanticDeltas consumer
+ , binding <- Semantic.semanticEnvironmentBindings
+ (Semantic.declarationDeltaEnvironment delta)
+ ]
+ assertEqual "two contextual consumer declarations" 2
+ (length consumerTargets)
+ void
+ (sole
+ "quantified contextual binder matches its explicit parameter"
+ (nubOrd consumerTargets))
+ runsAfterConsumer <- readIORef runs
+ assertEqual "contextual abbreviations require no prover call"
+ runsBeforeConsumer runsAfterConsumer
+
+ verifyFailure foundation resolver prelude mounts sealed
+ "test/phase5/exact-contextual-abbreviation-missing.tex"
+ (\case
+ Exact.ExactContextualExpansionNotAvailable location _key ->
+ assertEqual "missing context line" 5 (locLine location)
+ failure ->
+ assertFailure
+ ("unexpected missing-context failure: "
+ <> show failure))
+ verifyFailure foundation resolver prelude mounts sealed
+ "test/phase5/exact-contextual-abbreviation-ambiguous.tex"
+ (\case
+ Exact.ExactStructureOperationAmbiguous
+ location _symbol objects -> do
+ assertEqual "ambiguous operation line" 16
+ (locLine location)
+ assertEqual "two distinct operation objects" 2
+ (length objects)
+ failure ->
+ assertFailure
+ ("unexpected operation ambiguity failure: "
+ <> show failure))
+ where
+ assertReflexiveFact batches marker = do
+ batch <- maybe
+ (assertFailure ("missing contextual fact " <> marker)
+ >> fail "unreachable")
+ pure
+ (find
+ (elem (Semantic.semanticName (StrictText.pack marker))
+ . fmap Semantic.semanticAliasName
+ . Semantic.declarationDeltaAliases
+ . Declaration.committedBatchDelta)
+ batches)
+ proposition <- sole (marker <> " proposition")
+ (Declaration.committedBatchPropositions batch)
+ let body = stripClaimEnvelope
+ (Core.frozenCoreTerm
+ (Identity.checkedPropositionTerm proposition))
+ case body of
+ Core.CEq _ left right ->
+ assertEqual (marker <> " canonical sides") left right
+ _ ->
+ assertFailure
+ (marker <> " did not elaborate to reflexive equality: "
+ <> show body)
+
+ stripClaimEnvelope = \case
+ Core.CForall _ body -> stripClaimEnvelope body
+ Core.CImp _ body -> stripClaimEnvelope body
+ term -> term
+
+ verifyFailure foundation resolver prelude mounts imported relative checkFailure = do
+ workspace <- parseFinalExactWorkspace prelude mounts relative
+ let parsed = Parse.parsedWorkspaceRootModule workspace
+ input <- expectRight
+ (Module.typedModuleInput
+ foundation
+ (Module.finalPreludeReadiness prelude)
+ resolver
+ Declaration.FreshValidation
+ parsed
+ [imported])
+ Module.runTypedModule input >>= \case
+ Module.TypedModuleFailed
+ (Module.TypedActionFailed
+ (Module.TypedExactCompileFailed failure))
+ _prefix ->
+ checkFailure failure
+ Module.TypedModuleFailed
+ (Module.TypedActionFailed
+ (Module.TypedExactProofFailed
+ (ExactProof.ExactProofElaborationFailed failure)))
+ _prefix ->
+ checkFailure failure
+ Module.TypedModuleSucceeded{} ->
+ assertFailure (relative <> " was unexpectedly accepted")
+ Module.TypedModuleOpenFailed failure ->
+ assertFailure
+ (relative <> " did not open: " <> show failure)
+ Module.TypedModuleFailed failure _prefix ->
+ assertFailure
+ (relative <> " failed unexpectedly: " <> show failure)
+
+rejectsUnknownExactStructureParent :: Assertion
+rejectsUnknownExactStructureParent =
+ Temp.withSystemTempDirectory "felix-exact-structure-parent" \root -> do
+ let relative = "entry.tex"
+ path = root Posix.</> relative
+ source =
+ "\\begin{struct}\\label{known_structure}\n"
+ <> " A known structure $X$ is a onesorted structure.\n"
+ <> "\\end{struct}\n\n"
+ <> "\\begin{struct}\\label{invalid_structure}\n"
+ <> " An invalid structure $X$ is a future structure.\n"
+ <> "\\end{struct}\n\n"
+ <> "\\begin{struct}\\label{future_structure}\n"
+ <> " A future structure $X$ is a onesorted structure.\n"
+ <> "\\end{struct}\n"
+ ByteString.writeFile path
+ (Text.encodeUtf8 (StrictText.pack source))
+ foundation <- expectRight Foundation.checkedFoundation
+ Temp.withSystemTempDirectory "felix-exact-structure-store" \directory -> do
+ let storePath = directory Posix.</> "store.sqlite"
+ executable = directory Posix.</> "vampire"
+ writeAcceptedFixtureVampire executable
+ runs <- newIORef (0 :: Int)
+ let resolver = countingAcceptedResolver executable runs
+ (_startup, store) <-
+ Store.openStore storePath (Identity.theoryId foundation)
+ >>= expectRight
+ bracket (pure store) Store.closeStore \opened -> do
+ prelude <-
+ expectRight
+ =<< acquireFinalPreludeSession
+ opened foundation resolver
+ mounts <- exactFixtureMounts root
+ workspace <- parseFinalExactWorkspace prelude mounts relative
+ let parsed = Parse.parsedWorkspaceRootModule workspace
+ input <- expectRight
+ (Module.typedModuleInput
+ foundation
+ (Module.finalPreludeReadiness prelude)
+ resolver
+ Declaration.FreshValidation
+ parsed
+ [])
+ Module.runTypedModule input >>= \case
+ Module.TypedModuleFailed
+ (Module.TypedActionFailed
+ (Module.TypedExactCompileFailed
+ (Exact.ExactStructureNotVisible
+ location _phrase)))
+ prefix -> do
+ assertEqual "unknown parent line" 5 (locLine location)
+ assertEqual "only the valid structure was published"
+ 1
+ (length
+ (Declaration.pendingModulePrefixBatches prefix))
+ Module.TypedModuleSucceeded{} ->
+ assertFailure "unknown structure parent was accepted"
+ Module.TypedModuleOpenFailed failure ->
+ assertFailure
+ ("invalid structure module did not open: "
+ <> show failure)
+ Module.TypedModuleFailed failure _prefix ->
+ assertFailure
+ ("unexpected invalid structure failure: "
+ <> show failure)
+
compilesExactRelationExpressions :: Assertion
compilesExactRelationExpressions = do
foundation <- expectRight Foundation.checkedFoundation
@@ -1712,14 +1753,17 @@ compilesExactRelationExpressions = do
prover
"test/phase5/exact-relation-expression-missing-pair.tex")
case missingPair of
- Left
- (Api.VerificationTypedModuleError
+ Right
+ ( Api.VerificationCheckingFailure _report
+ (Api.VerificationTypedModuleError
_source
(Module.TypedActionFailed
(Module.TypedExactProofFailed
(ExactProof.ExactProofElaborationFailed
(Exact.ExactGlobalNotVisible location key))))
- prefix) -> do
+ prefix)
+ , _measurements
+ ) -> do
assertEqual "missing ordered-pair provider line"
2
(locLine location)
@@ -1752,7 +1796,7 @@ resolvesSourceOwnedApplication = do
\store -> do
prelude <-
expectRight
- =<< Module.buildFinalPreludeSession
+ =<< acquireFinalPreludeSession
store foundation resolver
mounts <- exactFixtureMounts repository
workspace <- parseFinalExactWorkspace
@@ -1788,14 +1832,17 @@ resolvesSourceOwnedApplication = do
prover
"test/phase5/exact-application-missing.tex")
case missing of
- Left
- (Api.VerificationTypedModuleError
+ Right
+ ( Api.VerificationCheckingFailure _report
+ (Api.VerificationTypedModuleError
_source
(Module.TypedActionFailed
(Module.TypedExactProofFailed
(ExactProof.ExactProofElaborationFailed
(Exact.ExactGlobalNotVisible location key))))
- prefix) -> do
+ prefix)
+ , _measurements
+ ) -> do
assertEqual "unresolved application line" 2 (locLine location)
assertEqual "unresolved application key"
(Semantic.SemanticExpressionFunction
@@ -1826,7 +1873,7 @@ confinesExactQuantifiedTerms = do
\store -> do
prelude <-
expectRight
- =<< Module.buildFinalPreludeSession
+ =<< acquireFinalPreludeSession
store foundation resolver
mounts <- exactFixtureMounts repository
workspace <- parseFinalExactWorkspace
@@ -1856,15 +1903,18 @@ confinesExactQuantifiedTerms = do
prover
"test/phase5/exact-quantified-subject-nested.tex")
case negative of
- Left
- (Api.VerificationTypedModuleError
+ Right
+ ( Api.VerificationCheckingFailure _report
+ (Api.VerificationTypedModuleError
_source
(Module.TypedActionFailed
(Module.TypedExactProofFailed
(ExactProof.ExactProofElaborationFailed
(Exact.ExactQuantifiedTermRequiresStatementSubject
location))))
- prefix) -> do
+ prefix)
+ , _measurements
+ ) -> do
assertEqual "nested quantified term line" 8 (locLine location)
assertEqual "earlier exact definition remains committed"
1
@@ -2307,6 +2357,209 @@ compilesAndReusesProofLocalSetDefinitions =
(Core.CImp left (Core.CImp right Core.CFalsum))
Core.CFalsum
+compilesAndReusesProofLocalFunctionGraphs :: Assertion
+compilesAndReusesProofLocalFunctionGraphs =
+ Temp.withSystemTempDirectory "felix-exact-local-function" \root -> do
+ let relative = "test/phase5/exact-local-function.tex"
+ failedRelative =
+ "test/phase5/exact-local-function-failure.tex"
+ executable = root Posix.</> "vampire"
+ storePath = root Posix.</> "store.sqlite"
+ writeAcceptedFixtureVampire executable
+ foundation <- expectRight Foundation.checkedFoundation
+ bootstrap <-
+ expectRight
+ =<< Module.buildBootstrapPreludeFixture
+ foundation unusedResolver
+ mounts <- exactFixtureMounts =<< getCurrentDirectory
+ workspace <- parseExactWorkspace bootstrap mounts relative
+ observations <- newIORef []
+ let resolver = Declaration.vampireResolver \prepared -> do
+ let problem =
+ Provers.preparedTypedProverLogicalProblem prepared
+ premises =
+ [ ( Backend.typedProblemRoute problem
+ , fmap snd
+ (Vector.toList
+ (Backend.supportedPropositionSupport
+ proposition))
+ , Backend.supportedPropositionTerm proposition
+ )
+ | premise <-
+ Vector.toList
+ (Backend.typedProblemLocalPremises problem)
+ , let proposition =
+ Backend.typedLocalPremiseProposition premise
+ ]
+ modifyIORef' observations (<> premises)
+ runNoLoggingT
+ (Provers.runPreparedTypedProver
+ (Provers.vampire
+ executable
+ Provers.defaultTimeLimit
+ Provers.defaultMemoryLimit)
+ prepared)
+ freshModules <-
+ compileParsedWorkspaceWithValidation
+ foundation bootstrap resolver
+ Declaration.FreshValidation workspace
+ allObserved <- readIORef observations
+ let observed =
+ [ (route, proposition)
+ | (route, support, proposition) <- allObserved
+ , support == [Core.TySet, Core.TySet]
+ , isJust (localFunctionPair proposition)
+ ]
+ assertBool
+ ("the local graph characteristic reaches a discharge: "
+ <> show allObserved)
+ (not (null observed))
+ for_ observed \(route, proposition) -> do
+ assertEqual "local function characteristic stays on FOF"
+ Backend.RouteFof route
+ assertExactLocalFunctionCharacteristic proposition
+ freshRoot <- sole "fresh local-function root"
+ (take 1 (reverse freshModules))
+ rootBatch <- sole "local function publishes only its theorem"
+ (drop 1
+ (Declaration.pendingModulePrefixBatches
+ (Module.sealedTypedModulePrefix freshRoot)))
+ assertEqual "local function publishes no object"
+ [] (Declaration.committedBatchObjects rootBatch)
+ assertEqual "local function publishes only its theorem"
+ 1
+ (length
+ (Declaration.committedBatchPropositions rootBatch))
+ assertEqual "local function publishes no semantic binding"
+ []
+ (Semantic.semanticEnvironmentBindings
+ (Semantic.declarationDeltaEnvironment
+ (Declaration.committedBatchDelta rootBatch)))
+ rootFact <- sole "local-function theorem"
+ (Semantic.declarationDeltaFacts
+ (Declaration.committedBatchDelta rootBatch))
+ assertEqual "local-function theorem remains clean"
+ Authority.cleanAuthoritySafety
+ (Authority.factAuthoritySafety
+ (Semantic.semanticFactAuthority rootFact))
+
+ bracket
+ (snd <$> (Store.openStore storePath
+ (Identity.theoryId foundation) >>= expectRight))
+ Store.closeStore
+ \store -> do
+ traverse_
+ (expectRightIO
+ . Store.writePendingModulePrefix store
+ . Module.sealedTypedModulePrefix)
+ freshModules
+ let validation =
+ Declaration.WarmValidation
+ (Declaration.validationLookup
+ (expectRightIO
+ . Store.loadProofValidation store)
+ (expectRightIO
+ . Store.loadDeclarationValidation store))
+ warmRuns <- newIORef (0 :: Int)
+ warmModules <-
+ compileParsedWorkspaceWithValidation
+ foundation bootstrap
+ (countingAcceptedResolver executable warmRuns)
+ validation workspace
+ assertEqual "warm local-function graph skips Vampire"
+ 0 =<< readIORef warmRuns
+ warmRoot <- sole "warm local-function root"
+ (take 1 (reverse warmModules))
+ assertEqual "warm local-function semantic interface"
+ (Module.sealedTypedModuleSemantic freshRoot)
+ (Module.sealedTypedModuleSemantic warmRoot)
+ assertEqual "warm local-function prefix"
+ (Declaration.pendingModulePrefixCurrent
+ (Module.sealedTypedModulePrefix freshRoot))
+ (Declaration.pendingModulePrefixCurrent
+ (Module.sealedTypedModulePrefix warmRoot))
+
+ failedWorkspace <-
+ parseExactWorkspace bootstrap mounts failedRelative
+ failedInput <- expectRight
+ (Module.typedModuleInput
+ foundation
+ (Module.bootstrapPreludeReadiness bootstrap)
+ unusedResolver
+ Declaration.FreshValidation
+ (Parse.parsedWorkspaceRootModule failedWorkspace)
+ [])
+ Module.runTypedModule failedInput >>= \case
+ Module.TypedModuleFailed
+ (Module.TypedActionFailed
+ (Module.TypedExactProofFailed
+ (ExactProof.ExactProofElaborationFailed
+ (Exact.ExactFreeVariable location
+ (Raw.NamedVar "f")))))
+ prefix -> do
+ assertEqual "self-reference rejection line"
+ 6 (locLine location)
+ assertBool "failed local function publishes no theorem"
+ (null
+ (Declaration.pendingModulePrefixBatches prefix))
+ Module.TypedModuleSucceeded{} ->
+ assertFailure "self-referential local function was accepted"
+ Module.TypedModuleOpenFailed failure ->
+ assertFailure
+ ("local-function failure fixture did not open: "
+ <> show failure)
+ Module.TypedModuleFailed failure _prefix ->
+ assertFailure
+ ("unexpected local-function failure: "
+ <> show failure)
+ where
+ assertExactLocalFunctionCharacteristic proposition = do
+ pair <-
+ maybe
+ (assertFailure "local function characteristic has wrong shape")
+ pure
+ (localFunctionPair proposition)
+ assertEqual "local function uses the exact replacement characteristic"
+ (expectedLocalFunctionCharacteristic pair)
+ proposition
+
+ localFunctionPair proposition =
+ case Set.toList (Core.canonicalTermGlobals proposition) of
+ [pair]
+ | proposition == expectedLocalFunctionCharacteristic pair ->
+ Just pair
+ _ ->
+ Nothing
+
+ expectedLocalFunctionCharacteristic pair =
+ Core.CForall Core.TySet
+ (Core.CEq Core.TyProp
+ (member (Core.CBound 0) (Core.CBound 1))
+ (existsP
+ (andP
+ (member (Core.CBound 0) (Core.CBound 3))
+ (Core.CEq Core.TySet
+ (Core.CBound 1)
+ (Core.CApp
+ (Core.CApp
+ (Core.CGlobal pair)
+ (Core.CBound 0))
+ (Core.CBound 0))))))
+
+ member element set =
+ Core.CApp
+ (Core.CApp (Core.CIntrinsic Core.Member) element)
+ set
+
+ andP left right =
+ notP (Core.CImp left (notP right))
+
+ existsP proposition =
+ notP (Core.CForall Core.TySet (notP proposition))
+
+ notP proposition =
+ Core.CImp proposition Core.CFalsum
+
confinesTerminalExactContradiction :: Assertion
confinesTerminalExactContradiction =
Temp.withSystemTempDirectory "felix-exact-contradiction" \directory -> do
@@ -3210,7 +3463,8 @@ assertExactDatatypeModule label sealed = do
(\binding ->
case Semantic.semanticGlobalBindingTarget binding of
Semantic.GlobalReference{} -> True
- Semantic.TransparentExpansion{} -> False)
+ Semantic.TransparentExpansion{} -> False
+ Semantic.ContextualTransparentExpansion{} -> False)
bindings)
assertEqual (label <> " datatype global targets")
(Set.fromList objectIds)
@@ -4537,9 +4791,6 @@ loadsCachedExactProducerForFreshImporter = do
executable
Provers.defaultTimeLimit
Provers.defaultMemoryLimit
- resolver = Declaration.vampireResolver \prepared ->
- runNoLoggingT
- (Provers.runPreparedTypedProver prover prepared)
verify mode source =
runNoLoggingT
(Api.verifyWithObserverAndStoreMode
@@ -4553,10 +4804,12 @@ loadsCachedExactProducerForFreshImporter = do
"test/phase5/exact-importer.tex"
assertTypedSuccess "fresh producer" producer
assertTypedSuccess "warm producer/fresh importer" importer
+ memo <- Store.newStoreMemo store
prelude <-
expectRight
- =<< Module.buildFinalPreludeSession
- store foundation resolver
+ =<< Module.acquireFinalPreludeSession
+ memo store foundation unusedResolver
+ preludeVisits <- Store.storeMemoVisits memo
repository <- getCurrentDirectory
mounts <- exactFixtureMounts repository
workspace <- parseFinalExactWorkspace
@@ -4566,11 +4819,11 @@ loadsCachedExactProducerForFreshImporter = do
(Parse.parsedWorkspaceImportedBeforeImporter workspace)
preludeSemantic =
Module.sealedTypedModuleSemantic
- (Module.migrationPreludeModule prelude)
+ (Module.finalPreludeModule prelude)
preludeId =
Semantic.semanticInterfaceAssertedId preludeSemantic
theory = Identity.theoryId foundation
- loadInstallation memo parsed direct = do
+ loadInstallation parsed direct = do
key <- expectRight
(Semantic.moduleArtifactKey
(moduleName (Parse.parsedModuleAddress parsed))
@@ -4598,16 +4851,25 @@ loadsCachedExactProducerForFreshImporter = do
]
case parsedModules of
[producerParsed, importerParsed] -> do
- memo <- Store.newStoreMemo store
producerInstallation <-
- loadInstallation memo producerParsed [preludeId]
+ loadInstallation producerParsed [preludeId]
+ producerVisits <- Store.storeMemoVisits memo
+ assertEqual "ordinary root adds one artifact validation"
+ (Store.storeArtifactsValidated preludeVisits + 1)
+ (Store.storeArtifactsValidated producerVisits)
+ assertEqual "ordinary root reuses prelude syntax validation"
+ (Store.storeSyntaxRowsValidated preludeVisits + 1)
+ (Store.storeSyntaxRowsValidated producerVisits)
+ assertEqual "ordinary root reuses prelude semantic validation"
+ (Store.storeSemanticRowsValidated preludeVisits + 1)
+ (Store.storeSemanticRowsValidated producerVisits)
let producerSemanticId =
Semantic.semanticInterfaceAssertedId
(Store.cachedInstallationSemantic
producerInstallation)
importerInstallation <-
loadInstallation
- memo importerParsed [preludeId, producerSemanticId]
+ importerParsed [preludeId, producerSemanticId]
case ( environmentBindings producerInstallation
, environmentBindings importerInstallation
) of
@@ -4666,6 +4928,832 @@ loadsCachedExactProducerForFreshImporter = do
<> show (length modules))
Store.closeStore store
+selectsConcurrentModuleFailureDeterministically :: Assertion
+selectsConcurrentModuleFailureDeterministically = do
+ foundation <- expectRight Foundation.checkedFoundation
+ Temp.withSystemTempDirectory "felix-concurrent-module-failure" \root -> do
+ let executable = root Posix.</> "vampire"
+ source = "test/phase7/concurrent-failure-root.tex"
+ prover =
+ Provers.vampire
+ executable
+ Provers.defaultTimeLimit
+ Provers.defaultMemoryLimit
+ ignored =
+ Api.verificationRequestObserver
+ (\_position _request -> pure ())
+ select amount =
+ Provers.selectEffectiveJobs
+ (Provers.effectiveJobs amount)
+ (fail "explicit jobs unexpectedly detected processors")
+ reportEntry escape =
+ ( Api.reportedEscapeKind escape
+ , locFile (Api.reportedEscapeLocation escape)
+ , locLine (Api.reportedEscapeLocation escape)
+ )
+ inspect label expectedPositions
+ (result, measurements, positions) = do
+ case result of
+ Api.VerificationFailure report failed -> do
+ assertEqual (label <> " selected earlier failure")
+ "test/phase7/concurrent-earlier.tex"
+ (locFile (Api.failedVerificationLocation failed))
+ assertEqual (label <> " admitted source prefix")
+ [ ( Api.ReportedSourceAxiom
+ , "test/phase7/concurrent-earlier.tex"
+ , 1
+ )
+ ]
+ (reportEntry
+ <$> Api.verificationDirectEscapes report)
+ other ->
+ assertFailure
+ (label <> " did not reject deterministically: "
+ <> show other)
+ assertEqual (label <> " executed only sibling obligations")
+ expectedPositions
+ (sort
+ [ ( Provers.workPositionModuleOrdinal position
+ , Provers.workPositionLocalRequestOrdinal position
+ )
+ | position <- positions
+ ])
+ pure measurements
+ runCase label jobsAmount = do
+ let storePath = root Posix.</> (label <> ".sqlite")
+ processLock = root Posix.</> (label <> ".process-lock")
+ processStarted =
+ root Posix.</> (label <> ".process-started")
+ writeAcceptedFixtureVampire executable
+ (_startup, store) <-
+ Store.openStore storePath (Identity.theoryId foundation)
+ >>= expectRight
+ bracket (pure store) Store.closeStore \openStore -> do
+ -- Seed only the final prelude. The unsupported ordinary
+ -- module cannot publish a root.
+ void
+ (runNoLoggingT
+ (Api.verifyMeasuredWithObserverAndStoreMode
+ openStore
+ Api.WarmStoreValidation
+ ignored
+ prover
+ "test/phase3/typed-unsupported.tex")
+ >>= expectRight)
+ writeFile executable
+ (unlines
+ [ "#!/bin/sh"
+ , "while ! mkdir \"" <> processLock
+ <> "\" 2>/dev/null; do sleep 0.01; done"
+ , "trap 'rmdir \"" <> processLock
+ <> "\"' EXIT"
+ , ": > \"" <> processStarted <> "\""
+ , "cat >/dev/null"
+ , "printf '%s\\n' '% SZS status CounterSatisfiable for concurrent-fixture'"
+ ])
+ permissions <- getPermissions executable
+ setPermissions executable
+ (setOwnerExecutable True permissions)
+ positionsRef <- newIORef []
+ let observer =
+ Api.verificationRequestObserver
+ (\position _request -> do
+ atomicModifyIORef' positionsRef
+ (\positions ->
+ (position : positions, ()))
+ when
+ (jobsAmount > 1
+ && Provers.workPositionModuleOrdinal
+ position == 1)
+ (waitForFileSignal
+ "later module process"
+ processStarted))
+ jobs <- select jobsAmount
+ (result, measurements) <-
+ runNoLoggingT
+ (Api.verifyMeasuredWithObserverAndStoreModeAndJobs
+ openStore
+ Api.WarmStoreValidation
+ jobs
+ observer
+ prover
+ source)
+ >>= expectRight
+ positions <- readIORef positionsRef
+ pure (result, measurements, positions)
+ parallel <-
+ runCase "parallel" 2
+ >>= inspect "parallel" [(1, 1), (2, 1)]
+ sequential <-
+ runCase "sequential" 1
+ >>= inspect "sequential" [(1, 1)]
+ assertEqual "parallel module checker bound"
+ 2
+ (Api.verificationMaximumLiveModuleCheckers parallel)
+ assertEqual "parallel Vampire bound"
+ 2
+ (Api.verificationMaximumLiveVampireProcesses parallel)
+ assertEqual "sequential module checker reference"
+ 1
+ (Api.verificationMaximumLiveModuleCheckers sequential)
+ assertEqual "sequential Vampire reference"
+ 1
+ (Api.verificationMaximumLiveVampireProcesses sequential)
+
+waitForFileSignal :: String -> FilePath -> Assertion
+waitForFileSignal label path = do
+ guarded <- Timeout.timeout 10000000 loop
+ case guarded of
+ Just () ->
+ pure ()
+ Nothing ->
+ assertFailure (label <> " was not observed")
+ where
+ loop = do
+ exists <- doesFileExist path
+ if exists
+ then pure ()
+ else do
+ threadDelay 10000
+ loop
+
+batchesStructureObligationsAtomically :: Assertion
+batchesStructureObligationsAtomically = do
+ foundation <- expectRight Foundation.checkedFoundation
+ Temp.withSystemTempDirectory "felix-structure-obligation-batch" \root -> do
+ let storePath = root Posix.</> "store.sqlite"
+ executable = root Posix.</> "vampire"
+ unavailable = root Posix.</> "must-not-run-vampire"
+ source = "test/phase7/structure-obligation-batch.tex"
+ prover path =
+ Provers.vampire
+ path
+ Provers.defaultTimeLimit
+ Provers.defaultMemoryLimit
+ select amount =
+ Provers.selectEffectiveJobs
+ (Provers.effectiveJobs amount)
+ (fail "explicit jobs unexpectedly detected processors")
+ run openStore jobs observer vampireCommand =
+ runNoLoggingT
+ (Api.verifyMeasuredWithObserverAndStoreModeAndJobs
+ openStore
+ Api.WarmStoreValidation
+ jobs
+ observer
+ vampireCommand
+ source)
+ >>= expectRight
+ inspectFailure label positions (result, measurements) = do
+ case result of
+ Api.VerificationFailure report failed -> do
+ assertEqual (label <> " selects first consequence")
+ (source, 12)
+ ( locFile (Api.failedVerificationLocation failed)
+ , locLine (Api.failedVerificationLocation failed)
+ )
+ assertEqual (label <> " retains preceding prefix")
+ [(Api.ReportedSourceAxiom, source, 1)]
+ [ ( Api.reportedEscapeKind escape
+ , locFile (Api.reportedEscapeLocation escape)
+ , locLine (Api.reportedEscapeLocation escape)
+ )
+ | escape <- Api.verificationDirectEscapes report
+ ]
+ other ->
+ assertFailure
+ (label <> " did not reject its structure batch: "
+ <> show other)
+ assertEqual (label <> " assigns consecutive positions")
+ [(1, 1), (1, 2)]
+ (sort positions)
+ assertEqual (label <> " observes one two-member batch")
+ (1, 2, 2)
+ ( Api.verificationObligationBatchCount measurements
+ , Api.verificationPreparedObligationCount measurements
+ , Api.verificationMaximumObligationBatchSize measurements
+ )
+ pure measurements
+ writeAcceptedFixtureVampire executable
+ (_startup, store) <-
+ Store.openStore storePath (Identity.theoryId foundation)
+ >>= expectRight
+ bracket (pure store) Store.closeStore \openStore -> do
+ let ignored =
+ Api.verificationRequestObserver
+ (\_position _request -> pure ())
+ -- Seed only the confined prelude so this fixture observes exactly
+ -- the ordinary structure module's ready batch.
+ void
+ (runNoLoggingT
+ (Api.verifyMeasuredWithObserverAndStoreMode
+ openStore
+ Api.WarmStoreValidation
+ ignored
+ (prover executable)
+ "test/phase3/typed-unsupported.tex")
+ >>= expectRight)
+ parallelJobs <- select 2
+ parallelPositions <- newIORef []
+ firstStarted <- newEmptyTMVarIO
+ secondStarted <- newEmptyTMVarIO
+ releaseFirst <- newEmptyTMVarIO
+ let laterCompleted = root Posix.</> "later-completed"
+ writeRejectingVampire executable laterCompleted
+ let parallelObserver =
+ Api.verificationRequestObserver \position _request -> do
+ let ordinal =
+ Provers.workPositionLocalRequestOrdinal position
+ atomicModifyIORef' parallelPositions
+ (\positions ->
+ ( ( Provers.workPositionModuleOrdinal position
+ , ordinal
+ ) : positions
+ , ()
+ ))
+ case ordinal of
+ 1 -> do
+ atomically (putTMVar firstStarted ())
+ atomically (takeTMVar releaseFirst)
+ 2 ->
+ atomically (putTMVar secondStarted ())
+ _ ->
+ assertFailure
+ ("unexpected structure request ordinal: "
+ <> show ordinal)
+ withAsync
+ (run openStore parallelJobs parallelObserver
+ (prover executable))
+ \verification -> do
+ void
+ (awaitSignal "first structure request"
+ (atomically (takeTMVar firstStarted)))
+ void
+ (awaitSignal "second structure request"
+ (atomically (takeTMVar secondStarted)))
+ -- Only the later member can reach the subprocess while
+ -- the first observer is gated. Its completed signal
+ -- therefore establishes reversed wall-clock completion.
+ waitForFileSignal
+ "later structure consequence"
+ laterCompleted
+ atomically (putTMVar releaseFirst ())
+ parallelResult <- wait verification
+ positions <- readIORef parallelPositions
+ parallelMeasurements <-
+ inspectFailure "parallel"
+ positions parallelResult
+ assertEqual "parallel obligations overlap"
+ 2
+ (Api.verificationMaximumLiveVampireProcesses
+ parallelMeasurements)
+
+ sequentialJobs <- select 1
+ sequentialPositions <- newIORef []
+ let sequentialCompleted = root Posix.</> "sequential-completed"
+ writeRejectingVampire executable sequentialCompleted
+ let sequentialObserver =
+ Api.verificationRequestObserver \position _request ->
+ atomicModifyIORef' sequentialPositions
+ (\positions ->
+ ( ( Provers.workPositionModuleOrdinal position
+ , Provers.workPositionLocalRequestOrdinal
+ position
+ ) : positions
+ , ()
+ ))
+ sequentialResult <-
+ run openStore sequentialJobs sequentialObserver
+ (prover executable)
+ sequentialObserved <- readIORef sequentialPositions
+ sequentialMeasurements <-
+ inspectFailure "sequential"
+ sequentialObserved sequentialResult
+ assertEqual "sequential batch is the semantic reference"
+ 1
+ (Api.verificationMaximumLiveVampireProcesses
+ sequentialMeasurements)
+
+ -- A rejected sibling wrote neither validation nor a module root:
+ -- the complete batch executes again, while the earlier source
+ -- axiom remains the admitted prefix. A subsequent hit executes
+ -- no request at all.
+ writeAcceptedFixtureVampire executable
+ acceptedPositions <- newIORef []
+ let acceptedObserver =
+ Api.verificationRequestObserver \position _request ->
+ modifyIORef' acceptedPositions
+ (position :)
+ (accepted, acceptedMeasurements) <-
+ run openStore parallelJobs acceptedObserver
+ (prover executable)
+ case accepted of
+ Api.VerificationCompleted report _presentation ->
+ assertEqual "successful retry retains only source axiom"
+ [Api.ReportedSourceAxiom]
+ (Api.reportedEscapeKind
+ <$> Api.verificationDirectEscapes report)
+ other ->
+ assertFailure
+ ("successful structure retry failed: " <> show other)
+ acceptedObserved <- readIORef acceptedPositions
+ assertEqual "successful retry executes the complete batch"
+ 2
+ (length acceptedObserved)
+ assertEqual "failed declaration published no root"
+ (1, 1)
+ ( Api.verificationModuleRootHitCount acceptedMeasurements
+ , Api.verificationModuleRootMissCount acceptedMeasurements
+ )
+ let forbiddenObserver =
+ Api.verificationRequestObserver \position _request ->
+ assertFailure
+ ("warm structure batch invoked Vampire at "
+ <> show position)
+ (warm, warmMeasurements) <-
+ run openStore parallelJobs forbiddenObserver
+ (prover unavailable)
+ case warm of
+ Api.VerificationCompleted{} -> pure ()
+ other ->
+ assertFailure
+ ("warm structure batch did not install: " <> show other)
+ assertEqual "warm module hit executes no batch"
+ (2, 0, 0)
+ ( Api.verificationModuleRootHitCount warmMeasurements
+ , Api.verificationModuleRootMissCount warmMeasurements
+ , Api.verificationVampireRunCount warmMeasurements
+ )
+ where
+ awaitSignal label action = do
+ result <- Timeout.timeout 10000000 action
+ maybe
+ (assertFailure (label <> " was not observed")
+ >> fail "unreachable")
+ pure
+ result
+
+ writeRejectingVampire executable completed = do
+ writeFile executable
+ (unlines
+ [ "#!/bin/sh"
+ , "cat >/dev/null"
+ , ": > \"" <> completed <> "\""
+ , "printf '%s\\n' '% SZS status CounterSatisfiable for structure-batch-fixture'"
+ ])
+ permissions <- getPermissions executable
+ setPermissions executable
+ (setOwnerExecutable True permissions)
+
+keepsDependentProofObligationsSequential :: Assertion
+keepsDependentProofObligationsSequential =
+ Temp.withSystemTempDirectory "felix-dependent-proof-chain" \root -> do
+ repository <- getCurrentDirectory
+ foundation <- expectRight Foundation.checkedFoundation
+ bootstrap <-
+ expectRight
+ =<< Module.buildBootstrapPreludeFixture
+ foundation
+ unusedResolver
+ mounts <- exactFixtureMounts repository
+ workspace <- parseExactWorkspace
+ bootstrap mounts "test/phase7/dependent-proof-chain.tex"
+ let executable = root Posix.</> "vampire"
+ writeAcceptedFixtureVampire executable
+ firstSubmitted <- newEmptyTMVarIO
+ secondSubmitted <- newEmptyTMVarIO
+ releaseFirst <- newEmptyTMVarIO
+ calls <- newIORef (0 :: Int)
+ let resolver =
+ Declaration.vampireBatchResolver \tasks -> do
+ assertEqual "dependent proof resolver batch is singleton"
+ 1
+ (NonEmpty.length tasks)
+ ordinal <- atomicModifyIORef' calls
+ (\current -> (current + 1, current + 1))
+ case ordinal of
+ 1 -> do
+ atomically (putTMVar firstSubmitted ())
+ atomically (takeTMVar releaseFirst)
+ 2 ->
+ atomically (putTMVar secondSubmitted ())
+ _ ->
+ assertFailure
+ ("unexpected dependent proof request: "
+ <> show ordinal)
+ traverse
+ (\prepared ->
+ runNoLoggingT
+ (Provers.runPreparedTypedProver
+ (Provers.vampire
+ executable
+ Provers.defaultTimeLimit
+ Provers.defaultMemoryLimit)
+ prepared))
+ tasks
+ withAsync
+ (compileParsedWorkspaceWithResolver
+ foundation bootstrap resolver workspace)
+ \checking -> do
+ void
+ (awaitSignal "local subclaim request"
+ (atomically (takeTMVar firstSubmitted)))
+ atomically (tryReadTMVar secondSubmitted) >>= \case
+ Nothing -> pure ()
+ Just () ->
+ assertFailure
+ "proof continuation was submitted before its local claim"
+ atomically (putTMVar releaseFirst ())
+ void
+ (awaitSignal "dependent continuation request"
+ (atomically (takeTMVar secondSubmitted)))
+ sealed <- wait checking
+ assertEqual "dependent proof module sealed" 1 (length sealed)
+ readIORef calls
+ >>= assertEqual "dependent proof executed two ordered requests" 2
+ where
+ awaitSignal label action = do
+ result <- Timeout.timeout 10000000 action
+ maybe
+ (assertFailure (label <> " was not observed")
+ >> fail "unreachable")
+ pure
+ result
+
+schedulesDiamondAfterSealedImports :: Assertion
+schedulesDiamondAfterSealedImports = do
+ foundation <- expectRight Foundation.checkedFoundation
+ Temp.withSystemTempDirectory "felix-concurrent-diamond" \root -> do
+ let storePath = root Posix.</> "store.sqlite"
+ executable = root Posix.</> "vampire"
+ unavailable = root Posix.</> "must-not-run-vampire"
+ source = "test/phase7/diamond-root.tex"
+ prover path =
+ Provers.vampire
+ path
+ Provers.defaultTimeLimit
+ Provers.defaultMemoryLimit
+ ignored =
+ Api.verificationRequestObserver
+ (\_position _request -> pure ())
+ writeAcceptedFixtureVampire executable
+ (_startup, store) <-
+ Store.openStore storePath (Identity.theoryId foundation)
+ >>= expectRight
+ bracket (pure store) Store.closeStore \openStore -> do
+ -- Acquire the final prelude before introducing scheduler gates.
+ void
+ (runNoLoggingT
+ (Api.verifyMeasuredWithObserverAndStoreMode
+ openStore
+ Api.WarmStoreValidation
+ ignored
+ (prover executable)
+ "test/phase3/typed-unsupported.tex")
+ >>= expectRight)
+ jobs <- Provers.selectEffectiveJobs
+ (Provers.effectiveJobs 2)
+ (fail "explicit jobs unexpectedly detected processors")
+ baseStarted <- newEmptyTMVarIO
+ branchStarted <- newTQueueIO
+ rootStarted <- newEmptyTMVarIO
+ releaseBase <- newTVarIO False
+ releaseBranches <- newTVarIO False
+ let awaitRelease released =
+ atomically (readTVar released >>= check)
+ observer =
+ Api.verificationRequestObserver
+ (\position _request ->
+ case Provers.workPositionModuleOrdinal position of
+ 1 -> do
+ atomically (putTMVar baseStarted ())
+ awaitRelease releaseBase
+ ordinal@2 -> do
+ atomically
+ (writeTQueue branchStarted ordinal)
+ awaitRelease releaseBranches
+ ordinal@3 -> do
+ atomically
+ (writeTQueue branchStarted ordinal)
+ awaitRelease releaseBranches
+ 4 ->
+ atomically (putTMVar rootStarted ())
+ _ ->
+ pure ())
+ verify vampireCommand requestObserver =
+ runNoLoggingT
+ (Api.verifyMeasuredWithObserverAndStoreModeAndJobs
+ openStore
+ Api.WarmStoreValidation
+ jobs
+ requestObserver
+ vampireCommand
+ source)
+ >>= expectRight
+ await label action = do
+ result <- Timeout.timeout 10000000 action
+ maybe
+ (assertFailure (label <> " was not observed")
+ >> fail "unreachable")
+ pure
+ result
+ withAsync (verify (prover executable) observer) \verification -> do
+ void (await "base request" (atomically (takeTMVar baseStarted)))
+ threadDelay 50000
+ atomically (tryReadTQueue branchStarted) >>= \case
+ Nothing -> pure ()
+ Just ordinal ->
+ assertFailure
+ ("dependent module started before base seal: "
+ <> show ordinal)
+ atomically (writeTVar releaseBase True)
+ firstBranch <- await "first branch"
+ (atomically (readTQueue branchStarted))
+ secondBranch <- await "second branch"
+ (atomically (readTQueue branchStarted))
+ assertEqual "both diamond branches became ready together"
+ [2, 3]
+ (sort [firstBranch, secondBranch])
+ atomically (tryReadTMVar rootStarted) >>= \case
+ Nothing -> pure ()
+ Just () ->
+ assertFailure
+ "diamond root started before both branch seals"
+ atomically (writeTVar releaseBranches True)
+ void (await "diamond root" (atomically (takeTMVar rootStarted)))
+ (coldResult, coldMeasurements) <- wait verification
+ case coldResult of
+ Api.VerificationCompleted{} -> pure ()
+ other ->
+ assertFailure
+ ("cold diamond did not complete: " <> show other)
+ assertEqual "cold diamond module misses plus prelude hit"
+ (1, 4)
+ ( Api.verificationModuleRootHitCount coldMeasurements
+ , Api.verificationModuleRootMissCount coldMeasurements
+ )
+ let forbiddenObserver =
+ Api.verificationRequestObserver
+ (\position _request ->
+ assertFailure
+ ("warm diamond invoked Vampire at "
+ <> show position))
+ (warmResult, warmMeasurements) <-
+ verify (prover unavailable) forbiddenObserver
+ case warmResult of
+ Api.VerificationCompleted{} -> pure ()
+ other ->
+ assertFailure
+ ("warm diamond did not install: " <> show other)
+ assertEqual "warm diamond installs each distinct root"
+ (5, 0)
+ ( Api.verificationModuleRootHitCount warmMeasurements
+ , Api.verificationModuleRootMissCount warmMeasurements
+ )
+ assertEqual "warm diamond runs no prover"
+ 0
+ (Api.verificationVampireRunCount warmMeasurements)
+
+reportsAdmittedSourceEscapes :: Assertion
+reportsAdmittedSourceEscapes = do
+ foundation <- expectRight Foundation.checkedFoundation
+ Temp.withSystemTempDirectory "felix-admitted-source-report" \root -> do
+ let storePath = root Posix.</> "store.sqlite"
+ executable = root Posix.</> "vampire"
+ unavailable = root Posix.</> "must-not-run-vampire"
+ observer =
+ Api.verificationRequestObserver \_ordinal _request -> pure ()
+ prover path =
+ Provers.vampire
+ path
+ Provers.defaultTimeLimit
+ Provers.defaultMemoryLimit
+ writeAcceptedFixtureVampire executable
+ (_startup, store) <-
+ Store.openStore storePath (Identity.theoryId foundation)
+ >>= expectRight
+ bracket (pure store) Store.closeStore \openStore -> do
+ let verify mode vampirePath source =
+ runNoLoggingT
+ (Api.verifyMeasuredWithObserverAndStoreMode
+ openStore
+ mode
+ observer
+ (prover vampirePath)
+ source)
+ >>= expectRight
+ reportEntries =
+ fmap
+ (\escape ->
+ ( Api.reportedEscapeKind escape
+ , locFile (Api.reportedEscapeLocation escape)
+ , locLine (Api.reportedEscapeLocation escape)
+ ))
+ . Api.verificationDirectEscapes
+ expectedConsumer =
+ [ ( Api.ReportedSourceAxiom
+ , "test/phase5/exact-escape-producer.tex"
+ , 1
+ )
+ , ( Api.ReportedOmitted
+ , "test/phase5/exact-escape-producer.tex"
+ , 9
+ )
+ , ( Api.ReportedOmitted
+ , "test/phase5/exact-escape-consumer.tex"
+ , 35
+ )
+ ]
+ (freshResult, freshMeasurements) <-
+ verify
+ Api.FreshStoreValidation
+ executable
+ "test/phase5/exact-escape-consumer.tex"
+ freshReport <- case freshResult of
+ Api.CompletedWithExplicitGaps report _presentation -> pure report
+ other ->
+ assertFailure
+ ("fresh escape report did not complete with gaps: "
+ <> show other)
+ >> fail "unreachable"
+ assertEqual "fresh direct escapes"
+ expectedConsumer
+ (reportEntries freshReport)
+ assertEqual "cold acquisition includes prelude and two modules"
+ (0, 3)
+ ( Api.verificationModuleRootHitCount freshMeasurements
+ , Api.verificationModuleRootMissCount freshMeasurements
+ )
+
+ (warmResult, warmMeasurements) <-
+ verify
+ Api.WarmStoreValidation
+ unavailable
+ "test/phase5/exact-escape-consumer.tex"
+ warmReport <- case warmResult of
+ Api.CompletedWithExplicitGaps report _presentation -> pure report
+ other ->
+ assertFailure
+ ("warm escape report did not complete with gaps: "
+ <> show other)
+ >> fail "unreachable"
+ assertEqual "warm report uses rebound current locations"
+ freshReport warmReport
+ assertEqual "warm acquisition includes prelude and two modules"
+ (3, 0)
+ ( Api.verificationModuleRootHitCount warmMeasurements
+ , Api.verificationModuleRootMissCount warmMeasurements
+ )
+ assertEqual "warm root hit invokes no Vampire process"
+ 0
+ (Api.verificationVampireRunCount warmMeasurements)
+
+ void
+ (verify
+ Api.FreshStoreValidation
+ executable
+ "test/phase5/exact-source-axiom.tex")
+ (failedResult, failedMeasurements) <-
+ verify
+ Api.WarmStoreValidation
+ unavailable
+ "test/phase6/admitted-prefix-failure.tex"
+ failedReport <- case failedResult of
+ Api.VerificationCheckingFailure report _failure -> pure report
+ other ->
+ assertFailure
+ ("typed suffix failure was not report-bearing: "
+ <> show other)
+ >> fail "unreachable"
+ assertEqual "failure report retains only admitted source prefix"
+ (take 2 expectedConsumer
+ <> [ ( Api.ReportedOmitted
+ , "test/phase6/admitted-prefix-failure.tex"
+ , 7
+ )
+ ])
+ (reportEntries failedReport)
+ assertEqual "failed root is not counted as acquired"
+ (2, 0)
+ ( Api.verificationModuleRootHitCount failedMeasurements
+ , Api.verificationModuleRootMissCount failedMeasurements
+ )
+ assertEqual "cached prefix failure invokes no Vampire process"
+ 0
+ (Api.verificationVampireRunCount failedMeasurements)
+
+classifiesTypedVampireFailures :: Assertion
+classifiesTypedVampireFailures = do
+ foundation <- expectRight Foundation.checkedFoundation
+ Temp.withSystemTempDirectory "felix-typed-failure-classification" \root -> do
+ let storePath = root Posix.</> "store.sqlite"
+ executable = root Posix.</> "vampire"
+ observer =
+ Api.verificationRequestObserver \_ordinal _request -> pure ()
+ prover =
+ Provers.vampire
+ executable
+ Provers.defaultTimeLimit
+ Provers.defaultMemoryLimit
+ writeAcceptedFixtureVampire executable
+ (_startup, store) <-
+ Store.openStore storePath (Identity.theoryId foundation)
+ >>= expectRight
+ bracket (pure store) Store.closeStore \openStore -> do
+ let verify source =
+ runNoLoggingT
+ (Api.verifyMeasuredWithObserverAndStoreMode
+ openStore
+ Api.WarmStoreValidation
+ observer
+ prover
+ source)
+ >>= expectRight
+ writeProtocol lines = do
+ writeFile executable
+ (unlines (["#!/bin/sh", "cat >/dev/null"] <> lines))
+ permissions <- getPermissions executable
+ setPermissions executable
+ (setOwnerExecutable True permissions)
+ expectTypedFailure classify = do
+ (result, _measurements) <-
+ verify "test/phase5/exact-runtime-failure.tex"
+ case result of
+ Api.VerificationFailure report failed -> do
+ assertEqual "typed failure has no direct escapes"
+ []
+ (Api.verificationDirectEscapes report)
+ assertEqual "typed failure retains source location"
+ "test/phase5/exact-runtime-failure.tex"
+ (locFile
+ (Api.failedVerificationLocation failed))
+ classify
+ (Api.failedVerificationReason failed)
+ (CommandLine.verificationCommandOutcome result)
+ other ->
+ assertFailure
+ ("typed prover outcome was misclassified: "
+ <> show other)
+
+ -- Populate only the confined prelude. The selected ordinary
+ -- module then remains a miss for each classified live failure.
+ (_preludeResult, _preludeMeasurements) <-
+ verify "test/phase3/typed-unsupported.tex"
+
+ writeProtocol
+ [ "printf '%s\\n' '% SZS status CounterSatisfiable for typed-failure'"
+ , "exit 0"
+ ]
+ expectTypedFailure \reason outcome -> do
+ case reason of
+ Api.CountermodelFailure{} -> pure ()
+ other -> assertFailure ("expected countermodel: " <> show other)
+ case outcome of
+ CommandLine.VerificationRejected{} -> pure ()
+ other -> assertFailure ("expected rejection: " <> show other)
+
+ writeProtocol
+ [ "printf '%s\\n' '% SZS status Timeout for typed-failure'"
+ , "exit 0"
+ ]
+ expectTypedFailure \reason outcome -> do
+ case reason of
+ Api.IndeterminateFailure{} -> pure ()
+ other -> assertFailure ("expected indeterminate result: " <> show other)
+ case outcome of
+ CommandLine.ProverFailed
+ _report _location CommandLine.ProverIndeterminate{} ->
+ pure ()
+ other -> assertFailure ("expected prover failure: " <> show other)
+
+ writeProtocol
+ [ "printf '%s\\n' '% SZS status Theorem for typed-failure'"
+ , "exit 7"
+ ]
+ expectTypedFailure \reason outcome -> do
+ case reason of
+ Api.ProtocolFailure{} -> pure ()
+ other -> assertFailure ("expected protocol failure: " <> show other)
+ case outcome of
+ CommandLine.ProverFailed
+ _report _location CommandLine.ProverProtocolFailure{} ->
+ pure ()
+ other -> assertFailure ("expected prover failure: " <> show other)
+
+ writeFile executable "not executable"
+ permissions <- getPermissions executable
+ setPermissions executable
+ (setOwnerExecutable False permissions)
+ expectTypedFailure \reason outcome -> do
+ case reason of
+ Api.TransportFailure{} -> pure ()
+ other -> assertFailure ("expected transport failure: " <> show other)
+ case outcome of
+ CommandLine.ProverFailed
+ _report _location CommandLine.ProverTransportFailure{} ->
+ pure ()
+ other -> assertFailure ("expected prover failure: " <> show other)
+
retainsExactPrefixBeforeFailure :: Assertion
retainsExactPrefixBeforeFailure = do
result <-
@@ -4675,13 +5763,16 @@ retainsExactPrefixBeforeFailure = do
prover
"test/phase5/exact-failure.tex")
case result of
- Left
- (Api.VerificationTypedModuleError
+ Right
+ ( Api.VerificationCheckingFailure _report
+ (Api.VerificationTypedModuleError
source
(Module.TypedActionFailed
(Module.TypedExactCompileFailed
(Exact.ExactUnsupportedDeclarationBody location)))
- prefix) -> do
+ prefix)
+ , _measurements
+ ) -> do
assertEqual "failed exact source"
"test/phase5/exact-failure.tex"
(safeRelativePathFilePath
@@ -4702,14 +5793,17 @@ retainsExactPrefixBeforeFailure = do
prover
"test/phase5/exact-proof-failure.tex")
case proofFailure of
- Left
- (Api.VerificationTypedModuleError
+ Right
+ ( Api.VerificationCheckingFailure _report
+ (Api.VerificationTypedModuleError
_source
(Module.TypedActionFailed
(Module.TypedExactProofFailed
(ExactProof.ExactProofGoalStatementMismatch
location)))
- prefix) -> do
+ prefix)
+ , _measurements
+ ) -> do
assertEqual "mismatched assumption line" 10 (locLine location)
assertEqual "failed proof publishes no theorem"
1
@@ -4727,12 +5821,15 @@ retainsExactPrefixBeforeFailure = do
prover
"test/phase5/unmatched-proof.tex")
case unmatched of
- Left
- (Api.VerificationTypedModuleError
+ Right
+ ( Api.VerificationCheckingFailure _report
+ (Api.VerificationTypedModuleError
_source
(Module.TypedActionFailed
(Module.TypedUnmatchedProof location))
- prefix) -> do
+ prefix)
+ , _measurements
+ ) -> do
assertEqual "unmatched proof line" 1 (locLine location)
assertEqual "unmatched proof publishes no declaration"
0
@@ -4821,14 +5918,17 @@ rejectsNestedExactSetInduction = do
prover
"test/phase5/exact-induction-nested.tex")
case result of
- Left
- (Api.VerificationTypedModuleError
+ Right
+ ( Api.VerificationCheckingFailure _report
+ (Api.VerificationTypedModuleError
_source
(Module.TypedActionFailed
(Module.TypedExactProofFailed
(ExactProof.ExactProofSetInductionNotOutermost
location)))
- prefix) -> do
+ prefix)
+ , _measurements
+ ) -> do
assertEqual "nested induction line" 7 (locLine location)
assertBool "failed proof publishes no theorem"
(null (Declaration.pendingModulePrefixBatches prefix))
@@ -4854,35 +5954,14 @@ routesProductionVerification =
setPermissions executable
(setOwnerExecutable True permissions)
producer <- verifyFixture executable "test/phase3/typed-producer.tex"
- assertRoute "selected producer"
- Api.TypedVerificationRoute
- producer
- setRoot <- verifyFixture executable "set.tex"
- assertRoute "protected set root"
- Api.TypedVerificationRoute
- setRoot
- natRoot <- verifyFixture executable "nat.tex"
- assertRoute "protected naturals root"
- Api.TypedVerificationRoute
- natRoot
- forM_
- [ ("bipartition", "set/bipartition.tex")
- , ("function", "function.tex")
- , ("Cantor", "set/cantor.tex")
- ]
- \(label, path) ->
- assertRoute ("typed " <> label)
- Api.TypedVerificationRoute
- =<< verifyFixture executable path
+ assertTypedSuccess "exact producer" producer
selectedRuns <- runCount counter
- assertBool "selected roots constructed the final prelude"
+ assertBool "ordinary roots construct the final prelude"
(selectedRuns > 0)
- importer <- verifyFixture executable "test/phase3/legacy-importer.tex"
- assertRoute "unselected importer"
- Api.LegacyVerificationRoute
- importer
- assertEqual "legacy root did not construct the final prelude"
- selectedRuns
+ importer <- verifyFixture executable "test/phase3/typed-importer.tex"
+ assertTypedSuccess "ordinary importer" importer
+ assertBool "every root constructs the final prelude"
+ . (> selectedRuns)
=<< runCount counter
where
verifyFixture executable path =
@@ -4899,16 +5978,6 @@ routesProductionVerification =
runCount path =
length . StrictText.lines . StrictText.pack <$> readFile path
- assertRoute label expected = \case
- Api.VerifiedWithTrustedVampire report ->
- assertEqual label expected (Api.verificationRoute report)
- Api.CompletedWithExplicitGaps report ->
- assertFailure
- (label <> " completed with gaps via "
- <> show (Api.verificationRoute report))
- Api.VerificationFailure failure ->
- assertFailure (label <> " failed: " <> show failure)
-
installsNonemptyImplicitPreludeEvidence :: Assertion
installsNonemptyImplicitPreludeEvidence = do
foundation <- expectRight Foundation.checkedFoundation
@@ -5330,13 +6399,13 @@ parseExactWorkspace bootstrap mounts relative =
relative
parseFinalExactWorkspace
- :: Module.MigrationPreludeSession
+ :: Module.FinalPreludeSession
-> SourceMounts
-> FilePath
-> IO Parse.ParsedSourceWorkspace
parseFinalExactWorkspace prelude mounts relative =
parseExactWorkspaceWithPrelude
- (Module.migrationPreludeModule prelude)
+ (Module.finalPreludeModule prelude)
mounts
relative
@@ -5401,7 +6470,7 @@ compileParsedWorkspaceWithValidation
compileFinalParsedWorkspaceWithResolver
:: Foundation.CheckedFoundation
- -> Module.MigrationPreludeSession
+ -> Module.FinalPreludeSession
-> Declaration.VampireResolver
-> Parse.ParsedSourceWorkspace
-> IO [Module.SealedTypedModule]
@@ -5468,14 +6537,13 @@ compileParsedWorkspaceWithReadiness
assertTypedSuccess :: String -> Api.VerificationResult -> Assertion
assertTypedSuccess label = \case
- Api.VerifiedWithTrustedVampire report ->
- assertEqual label Api.TypedVerificationRoute
- (Api.verificationRoute report)
- Api.CompletedWithExplicitGaps report ->
- assertFailure
- (label <> " completed with gaps via "
- <> show (Api.verificationRoute report))
- Api.VerificationFailure failure ->
+ Api.VerificationCompleted _report _presentation ->
+ pure ()
+ Api.CompletedWithExplicitGaps _report _presentation ->
+ assertFailure (label <> " completed with gaps")
+ Api.VerificationFailure _report failure ->
+ assertFailure (label <> " failed: " <> show failure)
+ Api.VerificationCheckingFailure _report failure ->
assertFailure (label <> " failed: " <> show failure)
sole :: String -> [value] -> IO value
@@ -5494,3 +6562,16 @@ expectRight = \case
expectRightIO :: Show error => IO (Either error value) -> IO value
expectRightIO action =
action >>= expectRight
+
+acquireFinalPreludeSession
+ :: Store.Store
+ -> Foundation.CheckedFoundation
+ -> Declaration.VampireResolver
+ -> IO
+ (Either
+ Module.FinalPreludeReadinessError
+ Module.FinalPreludeSession)
+acquireFinalPreludeSession store foundation resolver = do
+ memo <- Store.newStoreMemo store
+ Module.acquireFinalPreludeSession
+ memo store foundation resolver
diff --git a/source/Test/Unit/Provers.hs b/source/Test/Unit/Provers.hs
index d852755..22a6b5b 100644
--- a/source/Test/Unit/Provers.hs
+++ b/source/Test/Unit/Provers.hs
@@ -2,24 +2,24 @@
module Test.Unit.Provers (unitTests) where
-import Base
+import Base hiding (Empty)
+import Checking.Backend.Problem
+import Checking.Core
import Provers
-import Report.Location (pattern Nowhere)
-import Syntax.Internal
- ( Directness(..)
- , Hypothesis(..)
- , Marker(..)
- , Task(..)
- , pattern Top
- )
import Control.Concurrent (threadDelay)
import Control.Exception (bracket)
import Control.Exception qualified as Exception
import Control.Monad.Logger (runNoLoggingT)
+import Data.IORef
+ ( newIORef
+ , readIORef
+ , writeIORef
+ )
import Data.Set qualified as Set
import Data.Text qualified as Text
import Data.Text.IO qualified as Text
+import Data.Vector qualified as Vector
import System.Directory qualified as Directory
import System.Exit (ExitCode(..))
import System.FilePath.Posix ((</>))
@@ -34,16 +34,162 @@ import Test.Tasty
import Test.Tasty.HUnit
import Text.Read (readMaybe)
import Text.Megaparsec (parseMaybe)
-import UnliftIO.Async (cancel, withAsync)
+import UnliftIO.Async (cancel, mapConcurrently, withAsync)
unitTests :: TestTree
unitTests =
testGroup "Provers"
[ vampireStatusParserTests
, vampireClassifierTests
+ , jobsSelectionTests
+ , vampireExecutorTests
, vampireProcessTests
]
+jobsSelectionTests :: TestTree
+jobsSelectionTests =
+ testGroup "effective jobs"
+ [ testCase "uses a positive override exactly" do
+ detectorCalled <- newIORef False
+ selected <- selectEffectiveJobs
+ (effectiveJobs 3)
+ (writeIORef detectorCalled True >> pure 99)
+ jobsSelectionEffectiveJobs selected
+ `shouldBe` positiveJobs 3
+ jobsSelectionDetectedProcessors selected `shouldBe` Nothing
+ jobsSelectionWasOverridden selected `shouldBe` True
+ readIORef detectorCalled >>= (`shouldBe` False)
+ , testCase "leaves one detected logical processor free" do
+ selected <- selectEffectiveJobs Nothing (pure 8)
+ jobsSelectionEffectiveJobs selected
+ `shouldBe` positiveJobs 7
+ jobsSelectionDetectedProcessors selected `shouldBe` Just 8
+ jobsSelectionWasOverridden selected `shouldBe` False
+ , testCase "falls back to one after bad detection" do
+ nonPositive <- selectEffectiveJobs Nothing (pure 0)
+ jobsSelectionEffectiveJobs nonPositive
+ `shouldBe` positiveJobs 1
+ failed <- selectEffectiveJobs Nothing
+ (Exception.throwIO (userError "processor detection failed"))
+ jobsSelectionEffectiveJobs failed
+ `shouldBe` positiveJobs 1
+ jobsSelectionDetectedProcessors failed `shouldBe` Nothing
+ ]
+
+vampireExecutorTests :: TestTree
+vampireExecutorTests =
+ testGroup "bounded Vampire executor"
+ [ testCase "bounds live one-core processes" do
+ prepared <- preparedTypedTask 0
+ withFakeVampire
+ [ "previous=''"
+ , "found=0"
+ , "for argument in \"$@\"; do"
+ , " if [ \"$previous\" = '--cores' ]; then"
+ , " [ \"$argument\" = '1' ] || exit 17"
+ , " found=1"
+ , " fi"
+ , " previous=$argument"
+ , "done"
+ , "[ \"$found\" = '1' ] || exit 18"
+ , "cat >/dev/null"
+ , "sleep 0.2"
+ , "printf '%s\n' '% SZS status Theorem for fake'"
+ ]
+ \vampireCommand ->
+ withVampireExecutor
+ (positiveJobs 2)
+ vampireCommand
+ (\_position _request -> pure ())
+ \executor -> do
+ answers <- mapConcurrently
+ (\ordinal ->
+ runNoLoggingT
+ (runPreparedTypedProverWithExecutor
+ executor
+ (workPosition 1 ordinal)
+ prepared))
+ [1..4]
+ traverse_ assertProved answers
+ observed <- vampireExecutorObservation executor
+ vampireExecutorRunCount observed `shouldBe` 4
+ vampireExecutorMaximumLiveCount observed
+ `shouldBe` 2
+ , testCase "propagates observer failure to the submitter" do
+ prepared <- preparedTypedTask 0
+ withFakeVampire
+ [ "cat >/dev/null"
+ , "printf '%s\n' '% SZS status Theorem for fake'"
+ ]
+ \vampireCommand ->
+ withVampireExecutor
+ (positiveJobs 1)
+ vampireCommand
+ (\_position _request ->
+ Exception.throwIO
+ (userError "observer failed"))
+ \executor -> do
+ result <- Exception.try
+ (runNoLoggingT
+ (runPreparedTypedProverWithExecutor
+ executor
+ (workPosition 1 1)
+ prepared))
+ case result of
+ Left (failure :: Exception.IOException) ->
+ assertBool
+ "observer exception"
+ ("observer failed"
+ `Text.isInfixOf`
+ Text.pack (show failure))
+ Right answer ->
+ assertFailure
+ ("observer failure was lost: "
+ <> show answer)
+ , testCase "cancels queued and running jobs independently" do
+ prepared <- preparedTypedTask 0
+ withProcessGroupFake
+ defaultTimeLimit
+ []
+ \pidFile vampireCommand ->
+ withVampireExecutor
+ (positiveJobs 1)
+ vampireCommand
+ (\_position _request -> pure ())
+ \executor ->
+ withAsync
+ (runNoLoggingT
+ (runPreparedTypedProverWithExecutor
+ executor
+ (workPosition 1 1)
+ prepared))
+ \running -> do
+ processIds <- waitForProcessIds pidFile
+ withAsync
+ (runNoLoggingT
+ (runPreparedTypedProverWithExecutor
+ executor
+ (workPosition 2 1)
+ prepared))
+ \queued -> do
+ waitForSubmittedCount executor 2
+ cancel queued
+ cancel running
+ observed <- vampireExecutorObservation
+ executor
+ vampireExecutorSubmittedCount observed
+ `shouldBe` 2
+ vampireExecutorRunCount observed
+ `shouldBe` 1
+ assertProcessesGone processIds
+ ]
+
+positiveJobs :: Int -> EffectiveJobs
+positiveJobs amount =
+ fromMaybe
+ (error "test requested a non-positive job count")
+ (effectiveJobs amount)
+
vampireStatusParserTests :: TestTree
vampireStatusParserTests =
testGroup "Vampire status parser"
@@ -165,12 +311,14 @@ vampireProcessTests =
assertFailure
("expected malformed stdout, got " <> show result)
, testCase "returns a broken stdin pipe" do
+ prepared <- preparedTypedTask 20000
result <- withFakeVampire
[ "exec 0<&-"
, "sleep 1"
]
\vampireCommand ->
- runVampireProcess vampireCommand largeTask
+ runNoLoggingT
+ (runPreparedTypedProver vampireCommand prepared)
case result of
Left (ProverCommunicationFailed _ ProverStdin _) ->
pure ()
@@ -179,6 +327,7 @@ vampireProcessTests =
("expected a communication failure, got "
<> show processResult)
, testCase "drains output while feeding prover input" do
+ prepared <- preparedTypedTask 20000
guardedAnswer <- Timeout.timeout
30000000
(withFakeVampire
@@ -192,21 +341,23 @@ vampireProcessTests =
, "exit 0"
]
\vampireCommand -> do
- (_location, _formula, answer) <-
- runNoLoggingT
- (runProver vampireCommand largeTask)
- pure answer)
+ runNoLoggingT
+ (runPreparedTypedProver
+ vampireCommand
+ prepared))
case guardedAnswer of
Nothing ->
assertFailure "prover communication did not finish"
Just answer ->
assertProved answer
, testCase "reports signal termination separately" do
+ prepared <- preparedTypedTask 0
result <- withFakeVampire
[ "kill -TERM $$"
]
\vampireCommand ->
- runVampireProcess vampireCommand directTask
+ runNoLoggingT
+ (runPreparedTypedProver vampireCommand prepared)
case result of
Left
(ProverTerminatedBySignal
@@ -222,27 +373,31 @@ vampireProcessTests =
("expected signal termination, got "
<> show processResult)
, testCase "deadline terminates and reaps the process group" do
+ prepared <- preparedTypedTask 0
withProcessGroupFake
(Seconds 0)
[]
\pidFile vampireCommand -> do
result <-
- runVampireProcess
- vampireCommand
- directTask
+ runNoLoggingT
+ (runPreparedTypedProver
+ vampireCommand
+ prepared)
assertTimedOut result
processIds <- readProcessIds pidFile
assertProcessesGone processIds
, testCase "output exhaustion terminates the process group" do
+ prepared <- preparedTypedTask 0
withProcessGroupFake
defaultTimeLimit
[ "head -c 33554432 /dev/zero"
]
\pidFile vampireCommand -> do
result <-
- runVampireProcess
- vampireCommand
- directTask
+ runNoLoggingT
+ (runPreparedTypedProver
+ vampireCommand
+ prepared)
case result of
Left
(ProverOutputLimitExceeded
@@ -257,14 +412,16 @@ vampireProcessTests =
processIds <- readProcessIds pidFile
assertProcessesGone processIds
, testCase "cancellation terminates and reaps the process group" do
+ prepared <- preparedTypedTask 0
withProcessGroupFake
defaultTimeLimit
[]
\pidFile vampireCommand ->
withAsync
- (runVampireProcess
- vampireCommand
- directTask)
+ (runNoLoggingT
+ (runPreparedTypedProver
+ vampireCommand
+ prepared))
\worker -> do
processIds <- waitForProcessIds pidFile
cancel worker
@@ -408,6 +565,24 @@ waitForProcessIds path = do
threadDelay 10000
loop
+waitForSubmittedCount :: VampireExecutor -> Int -> Assertion
+waitForSubmittedCount executor expected = do
+ guarded <- Timeout.timeout 10000000 loop
+ case guarded of
+ Just () ->
+ pure ()
+ Nothing ->
+ assertFailure
+ ("executor did not submit " <> show expected <> " requests")
+ where
+ loop = do
+ observed <- vampireExecutorObservation executor
+ if vampireExecutorSubmittedCount observed >= expected
+ then pure ()
+ else do
+ threadDelay 10000
+ loop
+
assertProcessesGone :: [ProcessID] -> Assertion
assertProcessesGone processIds = do
guarded <- Timeout.timeout 10000000 loop
@@ -442,9 +617,9 @@ runFakeVampire scriptLines =
withFakeVampire
(["cat >/dev/null"] <> scriptLines)
\vampireCommand -> do
- (_location, _formula, answer) <- runNoLoggingT
- (runProver vampireCommand directTask)
- pure answer
+ prepared <- preparedTypedTask 0
+ runNoLoggingT
+ (runPreparedTypedProver vampireCommand prepared)
withFakeVampire
:: [String]
@@ -496,21 +671,43 @@ shouldBe :: (Eq a, Show a, HasCallStack) => a -> a -> Assertion
shouldBe =
flip (assertEqual "")
-directTask :: Task
-directTask =
- Task
- { taskDirectness = Direct
- , taskHypotheses = []
- , taskConjectureLabel = Marker "dummy"
- , taskLocation = Nowhere
- , taskConjecture = Top
- }
+preparedTypedTask
+ :: Int
+ -> IO (PreparedTypedProverTask Int Void Void Void)
+preparedTypedTask factCount = do
+ checked <- expectRight
+ (checkScopedCanonicalCore
+ (const Nothing)
+ []
+ propositionTerm)
+ proposition <- expectRight
+ (supportedProposition Vector.empty checked)
+ capability <- expectRight
+ (classifySupportedProposition (const Nothing) proposition)
+ let facts =
+ Vector.generate
+ factCount
+ (\reference ->
+ typedBackendFact reference proposition capability)
+ problem <- expectRight
+ (planTypedProblem
+ (const Nothing)
+ facts
+ proposition
+ []
+ []
+ ExplicitGlobalPremises
+ FirstOrderLocals)
+ expectRight (prepareTypedProverTask DirectTask problem)
+ where
+ propositionTerm =
+ CEq TySet
+ (CIntrinsic Empty)
+ (CIntrinsic Empty)
-largeTask :: Task
-largeTask =
- directTask
- { taskHypotheses =
- replicate
- 20000
- (Hypothesis (Marker "large") Top)
- }
+expectRight :: Show error => Either error value -> IO value
+expectRight = \case
+ Left failure ->
+ assertFailure (show failure) >> fail "unreachable"
+ Right value ->
+ pure value
diff --git a/source/Test/Unit/Semantic.hs b/source/Test/Unit/Semantic.hs
index 4a22f08..160735c 100644
--- a/source/Test/Unit/Semantic.hs
+++ b/source/Test/Unit/Semantic.hs
@@ -19,6 +19,7 @@ import Syntax.Abstract qualified as Raw
import Data.ByteString (ByteString)
import Data.List qualified as List
+import Data.Map.Strict qualified as Map
import Test.Tasty
import Test.Tasty.HUnit
@@ -32,6 +33,8 @@ unitTests =
roundTripsSemanticState
, testCase "round-trips exact semantic global keys"
roundTripsSemanticGlobalKeys
+ , testCase "round-trips canonical structure descriptors"
+ roundTripsStructureDescriptors
, testCase "keys exact proof and module inputs"
keysExactInputs
]
@@ -102,7 +105,11 @@ roundTripsSemanticGlobalKeys = do
first : rest ->
Semantic.semanticGlobalBinding
first
- (Semantic.TransparentExpansion target)
+ (Semantic.ContextualTransparentExpansion
+ target
+ (Map.singleton
+ (Raw.StructSymbol "operation")
+ target))
: [ Semantic.semanticGlobalBinding
key
(Semantic.GlobalReference target)
@@ -129,6 +136,53 @@ roundTripsSemanticGlobalKeys = do
(Semantic.semanticEnvironmentDelta [first, first])
_ -> assertFailure "semantic key fixture is unexpectedly empty"
+roundTripsStructureDescriptors :: Assertion
+roundTripsStructureDescriptors = do
+ fixture <- makeFixture
+ let structurePhrase marker word =
+ Semantic.semanticStructurePhrase
+ (Raw.LexicalItemSgPl
+ (Raw.SgPl
+ (Raw.TokenCons (Raw.Word word) Raw.End)
+ (Raw.TokenCons (Raw.Word (word <> "s")) Raw.End))
+ marker)
+ base = structurePhrase "onesorted_structure" "base"
+ child = structurePhrase "ordered_structure" "ordered"
+ object =
+ Identity.intrinsicObjectId
+ (fixtureTheory fixture)
+ Core.Empty
+ Core.TySet
+ operation =
+ Semantic.semanticStructureOperation
+ (Raw.StructSymbol "carrier")
+ object
+ descriptor <- expectRight
+ (Semantic.semanticStructureDescriptor
+ child
+ (Just object)
+ [base]
+ [operation])
+ delta <- expectRight
+ (Semantic.semanticEnvironmentWithStructures [] [descriptor])
+ assertEqual
+ "structure environment cache round trip"
+ (Right delta)
+ (decodeCache
+ Semantic.getSemanticEnvironmentDeltaCache
+ (encodeCache
+ (Semantic.putSemanticEnvironmentDeltaCache delta)))
+ assertEqual
+ "duplicate local operation is rejected"
+ (Left
+ (Semantic.DuplicateSemanticStructureOperation
+ (Raw.StructSymbol "carrier")))
+ (Semantic.semanticStructureDescriptor
+ child
+ (Just object)
+ [base]
+ [operation, operation])
+
keysExactInputs :: Assertion
keysExactInputs = do
fixture <- makeFixture
diff --git a/source/Test/Unit/Source.hs b/source/Test/Unit/Source.hs
index 3f6703e..73eaef5 100644
--- a/source/Test/Unit/Source.hs
+++ b/source/Test/Unit/Source.hs
@@ -5,35 +5,24 @@
module Test.Unit.Source (unitTests) where
import Base
-import Checking qualified
-import Checking.Backend.Problem qualified as Backend
-import Checking.Backend.Reconstruction qualified as Reconstruction
-import Checking.Core qualified as Core
-import Checking.Facts qualified as Facts
import Checking.Foundation qualified as Foundation
import Checking.Identity qualified as Identity
-import Checking.Kernel.Derivation qualified as Derivation
-import Checking.Legacy qualified as Legacy
-import Checking.Obligation qualified as Obligation
import Checking.Semantic qualified as Semantic
-import Checking.Transition qualified as Transition
import Felix.Cache.Codec qualified as Cache
import Felix.Module qualified as Module
import Felix.Parse qualified as Parse
import Felix.Parsed.Identity qualified as ParsedIdentity
import Felix.Parsed.Payload qualified as Parsed
+import Felix.Prelude qualified as Prelude
import Felix.Source
import Felix.Source.Content qualified as Content
import Felix.Source.Graph
import Felix.Store qualified as Store
-import Meaning qualified
-import Provers qualified
import Report.Location
( FileId(..)
, FileIdAllocator(..)
, Location(..)
, LocationRegistrationError(..)
- , pattern Nowhere
, allocateFileId
, locColumn
, locFile
@@ -44,21 +33,14 @@ import Report.Location
import Syntax.Abstract qualified as Raw
import Syntax.Adapt qualified as Adapt
import Syntax.Interface qualified as Interface
-import Syntax.Internal
import Syntax.Token (runLexer)
-import Bound.Scope (toScope)
-import Control.Exception (bracket, evaluate, try)
-import Control.Monad (foldM)
-import Control.Monad.Logger (runNoLoggingT)
+import Control.Exception (bracket, evaluate)
import Data.ByteString qualified as ByteString
-import Data.HashMap.Strict qualified as HashMap
import Data.IORef
import Data.List qualified as List
import Data.List.NonEmpty qualified as NonEmpty
-import Data.Set qualified as Set
import Data.Text qualified as Text
-import Data.Vector qualified as Vector
import Data.Word (Word8, Word16)
import Database.SQLite.Simple qualified as SQLite
import System.Directory qualified as Directory
@@ -89,6 +71,8 @@ unitTests = testGroup "Source resolution"
, testCase "reserves the all-ones file identifier"
preservesReservedFileId
, testCase "builds an imported-before-importer source graph" buildsSourceGraph
+ , testCase "rejects the packaged prelude as ordinary source"
+ rejectsPackagedPreludeAsOrdinarySource
, testCase "orders sibling imports by textual occurrence"
ordersSiblingImports
, testCase "orders shared dependencies before their importers"
@@ -114,20 +98,6 @@ unitTests = testGroup "Source resolution"
, testCase "rejects a corrupted cached declaration anchor"
rejectsCorruptedCachedDeclarationAnchor
, testCase "parses source-local blocks in graph order" parsesSourceGraph
- , testCase "assigns and reserves dense legacy module positions"
- reservesLegacyModulePositions
- , testCase "admits complete legacy declaration batches"
- admitsLegacyDeclarations
- , testCase "publishes deterministic legacy import views"
- publishesLegacyImportViews
- , testCase "publishes typed signatures and facts through transition modules"
- publishesTransitionSignatures
- , testCase "rejects cached global types from another builder"
- rejectsForeignCachedGlobalType
- , testCase "authorizes exact typed Vampire requests"
- authorizesTypedVampireRequests
- , testCase "enforces and replays direct inductive guards"
- publishesTypedInductive
, testCase "does not leak syntax between sibling imports"
rejectsSiblingSyntaxLeakage
, testCase "parses source fixity levels and grouping"
@@ -154,10 +124,8 @@ unitTests = testGroup "Source resolution"
reportsMalformedLexicalDeclaration
, testCase "validates inductive function patterns during scanning"
rejectsMalformedInductivePattern
- , testCase "scans, parses, and checks adjective signatures"
+ , testCase "scans and parses adjective signatures"
acceptsAdjectiveSignature
- , testCase "rejects unresolved quantified symbolic-signature terms"
- rejectsQuantifiedSymbolicSignatureTerm
, testCase "rejects malformed math-led signature heads"
rejectsMalformedSignatureHead
, testCase "locates conflicting declarations within one environment"
@@ -166,8 +134,6 @@ unitTests = testGroup "Source resolution"
acceptsBuiltinSourceDeclaration
, testCase "keeps the built-in marker for a prefix predicate declaration"
acceptsBuiltinPrefixPredicateDeclaration
- , testCase "rejects duplicate fixed-base semantics during checking"
- rejectsDuplicateFixedBaseSemantics
, testCase "does not rescan repeated canonical imports"
avoidsAliasImportLexiconCollision
, testCase "parses loaded sources without rereading files" parsesWithoutRereading
@@ -275,6 +241,47 @@ rootFormsShareIdentity =
(resolvedSourceRelativePath (loadedSource searchedLoaded))
(resolvedSourceRelativePath (loadedSource exactLoaded))
+rejectsPackagedPreludeAsOrdinarySource :: Assertion
+rejectsPackagedPreludeAsOrdinarySource = do
+ packaged <- expectRight =<< Prelude.loadReservedPreludeSourceInput
+ canonical <- expectJust "packaged canonical path"
+ (Prelude.reservedPreludeSourceCanonicalPath packaged)
+ let path = canonicalPathFilePath canonical
+ mounts <- oneMount "packaged" (Posix.takeDirectory path)
+ request <- expectRight (searchedRoot (Posix.takeFileName path))
+ let validate = Prelude.rejectOrdinaryPreludeSourceGraph packaged
+ syntaxInputs = const []
+ Parse.parseSourceWorkspaceMeasuredWithSyntaxInputsAndGraphValidation
+ mounts request syntaxInputs validate >>= \case
+ Left
+ (Parse.SourceWorkspaceError
+ (PackagedPreludeSelectedAsOrdinarySource source)) ->
+ assertEqual "authority-free rejected path"
+ canonical
+ (resolvedSourceCanonicalPath source)
+ other ->
+ assertFailure
+ ("unexpected authority-free result: " <> show other)
+
+ withTemporaryDirectory "felix-reserved-parse-store" \temp -> do
+ foundation <- expectRight Foundation.checkedFoundation
+ store <- openTestStore
+ (temp Posix.</> "store.sqlite")
+ (Identity.theoryId foundation)
+ Parse.parseSourceWorkspaceMeasuredWithStoreAndSyntaxInputsAndGraphValidation
+ store mounts request syntaxInputs validate >>= \case
+ Left
+ (Parse.ParseExecutionWorkspaceError
+ (Parse.SourceWorkspaceError
+ (PackagedPreludeSelectedAsOrdinarySource source))) ->
+ assertEqual "typed rejected path"
+ canonical
+ (resolvedSourceCanonicalPath source)
+ other ->
+ assertFailure
+ ("unexpected typed result: " <> show other)
+ Store.closeStore store
+
attributesNestedSources :: Assertion
attributesNestedSources =
withTemporaryDirectory "felix-source-nested-mount" \temp -> do
@@ -682,46 +689,6 @@ buildsEmptyModules =
(Parse.parsedModuleSyntaxInterface
(Parse.parsedWorkspaceRootModule
workspace)))))
- assignments <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals workspace)
- assignment <-
- case toList assignments of
- [only] ->
- pure only
- actual ->
- assertFailure
- ("expected one empty module assignment, got "
- <> show (length actual))
- >> fail "unreachable"
- checkedFoundationValue <-
- expectRight Foundation.checkedFoundation
- builder <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- assignment
- [])
- checked <-
- Checking.runCheckingBlocks
- []
- (Checking.initialTransitionCheckingStateWithTaskPreparation
- Checking.WithoutDumpPremselTraining
- id
- builder
- (\_batch ->
- assertFailure
- "empty module emitted an obligation"))
- finalBuilder <-
- expectJust
- "empty transition builder"
- (Checking.checkingTransitionModuleBuilder checked)
- void
- (expectRight
- (Transition.sealTransitionModule
- (Checking.checkingStateEnvironment checked)
- finalBuilder))
identifiesOwnerIndependentParsedModules :: Assertion
identifiesOwnerIndependentParsedModules =
@@ -1235,1613 +1202,6 @@ parsesSourceGraph =
["shared.tex", "entry.tex"]
emitted
-reservesLegacyModulePositions :: Assertion
-reservesLegacyModulePositions =
- withTemporaryDirectory "felix-legacy-module-stage" \temp -> do
- writeTheory (temp Posix.</> "shared.tex") [] "shared"
- writeTheory
- (temp Posix.</> "entry.tex")
- ["shared.tex"]
- "entry"
- graph <- buildSearchedGraph temp "entry.tex"
- workspace <-
- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- assignments <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals workspace)
- assertEqual "dense imported-first module ordinals"
- [0, 1]
- ( Legacy.legacyModuleOrdinalValue
- . Legacy.assignedLegacyModuleOrdinal
- <$> toList assignments
- )
- assertEqual "assigned source order"
- ["shared.tex", "entry.tex"]
- ( safeRelativePathFilePath
- . sourceAddressRelativePath
- . Parse.parsedModuleAddress
- . Legacy.assignedParsedModule
- <$> toList assignments
- )
-
- let firstAssignment :| _remainingAssignments =
- assignments
- stage =
- Legacy.openLegacyModuleStage
- firstAssignment
- (Legacy.emptyLegacyImportedView
- Checking.initialLegacyCheckingEnvironment)
- origin = Facts.factOrigin (Location 0) "declaration"
- firstFact =
- Facts.stageFact
- ("first" :| ["first_alias"])
- origin
- (Facts.prepareSemanticFact Top)
- secondFact =
- Facts.stageFact
- ("second" :| [])
- origin
- (Facts.prepareSemanticFact Bottom)
- reservation <-
- expectRight
- (Legacy.reserveLegacyDeclaration
- (firstFact :| [secondFact])
- stage)
- assertEqual "dense local fact ordinals"
- [0, 1]
- ( Legacy.legacyLocalFactOrdinalValue
- . Legacy.legacyFactLocalOrdinal
- . Legacy.legacyReservedFactReference
- <$> toList (Legacy.legacyReservedFacts reservation)
- )
-
- let duplicateAliasFact =
- Facts.stageFact
- ("first_alias" :| [])
- origin
- (Facts.prepareSemanticFact Bottom)
- case Legacy.reserveLegacyDeclaration
- (firstFact :| [duplicateAliasFact])
- stage of
- Left Legacy.LegacyAliasAlreadyBound{} ->
- pure ()
- Left err ->
- assertFailure
- ("expected alias rejection, got " <> show err)
- Right _ ->
- assertFailure "expected duplicate legacy alias rejection"
-
-admitsLegacyDeclarations :: Assertion
-admitsLegacyDeclarations =
- withTemporaryDirectory "felix-legacy-admission" \temp -> do
- writeTheory (temp Posix.</> "entry.tex") [] "entry"
- graph <- buildSearchedGraph temp "entry.tex"
- workspace <-
- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- assignment :| _ <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals workspace)
- let stage =
- Legacy.openLegacyModuleStage
- assignment
- (Legacy.emptyLegacyImportedView
- Checking.initialLegacyCheckingEnvironment)
- blocks =
- [ BlockAxiom
- Nowhere
- "declared"
- (Axiom [] Top)
- , BlockLemma
- Nowhere
- "omitted"
- (Lemma [] Bottom)
- , BlockProof
- Nowhere
- Nowhere
- (Omitted Nowhere)
- ]
- resolveGapBatch batch = do
- resolved <-
- traverse
- (either
- (ioError . userError . show)
- pure
- . Obligation.resolveObligationAsGap)
- (Obligation.preparedBatchObligations batch)
- either
- (ioError . userError . show)
- pure
- (Obligation.resolveObligationBatch
- batch
- resolved)
- initial =
- Checking.initialLegacyCheckingStateWithTaskPreparation
- Checking.WithoutDumpPremselTraining
- id
- stage
- resolveGapBatch
- checked <-
- Checking.runCheckingBlocks blocks initial
- admittedStage <-
- maybe
- (assertFailure
- "authoritative checking lost the legacy stage"
- >> pure stage)
- pure
- (Checking.checkingLegacyModuleStage checked)
- admittedModule <-
- expectRight
- (Legacy.sealLegacyModuleStage
- (Checking.checkingStateEnvironment checked)
- admittedStage)
- assertEqual "two sealed local facts"
- 2
- (Vector.length
- (Legacy.legacyAdmittedLocalFacts admittedModule))
- assertEqual "one sealed declared assumption"
- 1
- (Vector.length
- (Legacy.legacyAdmittedDirectAxiomManifest
- admittedModule))
- let finalTrust =
- Legacy.legacyFactEntryTrustDependencies
- (Vector.last
- (Legacy.legacyAdmittedLocalFacts
- admittedModule))
- assertEqual "one explicit gap"
- 1
- (Set.size
- (Legacy.legacyExplicitGaps finalTrust))
- assertEqual "direct gap needs no legacy finalization rule"
- 0
- (Set.size
- (Legacy.trustedLegacyRuleUses finalTrust))
-
-publishesTransitionSignatures :: Assertion
-publishesTransitionSignatures =
- withTemporaryDirectory "felix-transition-signatures" \temp -> do
- writeTheory (temp Posix.</> "shared.tex") [] "shared"
- writeTheory
- (temp Posix.</> "entry.tex")
- ["shared.tex"]
- "entry"
- graph <- buildSearchedGraph temp "entry.tex"
- workspace <-
- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- assignments <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals workspace)
- checkedFoundationValue <-
- expectRight Foundation.checkedFoundation
- case toList assignments of
- [sharedAssignment, entryAssignment] -> do
- shared <-
- admit
- checkedFoundationValue
- sharedAssignment
- []
- [ BlockSig
- Nowhere
- "shared_signature"
- []
- (SignaturePredicate
- sharedPredicate
- ("x" :| []))
- , BlockAxiom
- Nowhere
- "shared_atomic_axiom"
- (Axiom [] sharedAtomicFormula)
- ]
- let sharedGlobals =
- Transition.transitionAdmittedGlobals
- shared
- assertEqual
- "one shared typed declaration"
- 1
- (Vector.length sharedGlobals)
- case Vector.toList sharedGlobals of
- [(symbol, reference, _origin)] -> do
- assertEqual
- "shared symbol"
- (SymbolPredicate sharedPredicate)
- symbol
- assertEqual
- "shared declaration ordinal"
- 0
- (Transition.localDeclarationOrdinalValue
- (Transition.opaqueDeclarationOrdinal
- (Transition.checkedGlobalReference
- reference)))
- assertEqual
- "shared predicate type"
- (Core.TySet
- `Core.TyArrow`
- Core.TyProp)
- (Transition.checkedGlobalType reference)
- _ ->
- assertFailure
- "expected one shared typed declaration"
- let sharedFacts =
- Vector.toList
- (Transition.transitionAdmittedFacts
- shared)
- sharedManifest =
- Vector.toList
- (Transition.transitionAdmittedTypedDirectAxiomManifest
- shared)
- (sharedReference, sharedStatement) <-
- case (sharedFacts, sharedManifest) of
- ([assumption], [manifestEntry]) -> do
- assertBool
- "typed axiom is not a kernel proof"
- (not
- (Transition.admittedFactIsKernelProof
- assumption))
- assertEqual
- "manifest kind"
- Legacy.DeclaredUserAxiom
- (Transition.typedDirectAssumptionKind
- manifestEntry)
- assertEqual
- "manifest fact reference"
- (Just
- (Transition.typedDirectAssumptionFact
- manifestEntry))
- (Transition.transitionTypedFactReference
- (Transition.admittedFactReference
- assumption))
- pure
- ( Transition.admittedFactReference
- assumption
- , Transition.typedDirectAssumptionStatement
- manifestEntry
- )
- _ ->
- fail
- "expected one manifest-backed typed axiom"
-
- hiddenBuilder <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- entryAssignment
- [])
- hiddenTarget <-
- expectRight
- (Core.checkCanonicalCore
- (const Nothing)
- (Core.CImp
- Core.CFalsum
- Core.CFalsum))
- hiddenImport <-
- expectRight
- (Transition.transitionDerivationImport
- sharedReference
- hiddenTarget)
- case Transition.commitTransitionKernelFactWithImports
- ("hidden_import" :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just "hidden_import"))
- (Vector.singleton hiddenImport)
- hiddenTarget
- (Derivation.importedFactDerivation
- (Derivation.importIx 0))
- hiddenBuilder of
- Left
- (Transition.TransitionKernelImportNotVisible
- actualReference) ->
- assertEqual
- "unimported fact reference"
- sharedReference
- actualReference
- Left err ->
- assertFailure
- ("expected hidden typed import failure, got "
- <> show err)
- Right _ ->
- assertFailure
- "an unimported typed row authorized replay"
-
- entryBuilder <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- entryAssignment
- [shared])
- assertBool
- "direct import exposes the typed global"
- (isJust
- (Transition.lookupTransitionGlobal
- (SymbolPredicate sharedPredicate)
- entryBuilder))
- entry <-
- admitWithBuilder
- entryBuilder
- [ BlockAxiom
- Nowhere
- "legacy_axiom"
- (Axiom [] Top)
- , BlockSig
- Nowhere
- "entry_signature"
- []
- (SignaturePredicate
- entryPredicate
- ("z" :| []))
- , BlockLemma
- Nowhere
- "typed_import_reuse"
- (Lemma [] sharedAtomicFormula)
- , BlockLemma
- Nowhere
- "typed_reflexivity"
- (Lemma
- []
- (Equals
- Nowhere
- (EmptySet Nowhere)
- (EmptySet Nowhere)))
- ]
- case Vector.toList
- (Transition.transitionAdmittedGlobals
- entry) of
- [(_symbol, reference, _origin)] ->
- assertEqual
- "legacy declaration occupies its source ordinal"
- 1
- (Transition.localDeclarationOrdinalValue
- (Transition.opaqueDeclarationOrdinal
- (Transition.checkedGlobalReference
- reference)))
- _ ->
- assertFailure
- "expected one local entry declaration"
- let facts =
- Vector.toList
- (Transition.transitionAdmittedFacts
- entry)
- assertEqual
- "imported and local rows retain declaration order"
- [False, False, True, True]
- (Transition.admittedFactIsKernelProof
- <$> facts)
- case facts of
- [_assumption, _legacy, reused, reflexivity] -> do
- case Transition.transitionTypedFactReference
- (Transition.admittedFactReference
- reused) of
- Nothing ->
- assertFailure
- "expected a typed fact reference"
- Just reference ->
- assertEqual
- "first typed fact ordinal"
- 0
- (Transition.localFactOrdinalValue
- (Transition.factReferenceOrdinal
- reference))
- case Transition.transitionTypedFactReference
- (Transition.admittedFactReference
- reflexivity) of
- Nothing ->
- assertFailure
- "expected a typed reflexivity reference"
- Just reference ->
- assertEqual
- "second typed fact ordinal"
- 1
- (Transition.localFactOrdinalValue
- (Transition.factReferenceOrdinal
- reference))
- _ ->
- assertFailure
- "expected imported assumption and three local facts"
- let inheritedAssumptions =
- Set.toList
- (Transition.typedDeclaredAssumptionUses
- (Transition.transitionAdmittedTypedTrustDependencies
- entry))
- case inheritedAssumptions of
- [assumption] -> do
- assertEqual
- "the importer retains the owner fact"
- (Transition.transitionTypedFactReference
- sharedReference)
- (Just
- (Transition.sessionTypedAssumptionFact
- assumption))
- assertEqual
- "the owner assumption ordinal"
- 0
- (Transition.localAssumptionOrdinalValue
- (Transition.sessionTypedAssumptionOrdinal
- assumption))
- assertEqual
- "the imported assumption statement"
- sharedStatement
- (Transition.sessionTypedAssumptionStatement
- assumption)
- _ ->
- assertFailure
- "expected one inherited typed declared assumption"
- assertEqual
- "two local replayed kernel proofs"
- 2
- (Transition.transitionAdmittedKernelProofCount
- entry)
- actual ->
- assertFailure
- ("expected two module assignments, got "
- <> show (length actual))
- where
- sharedPredicate =
- PredicateSymbol "typed_shared_predicate"
- entryPredicate =
- PredicateSymbol "typed_entry_predicate"
- sharedAtomicFormula =
- Atomic
- Nowhere
- sharedPredicate
- [EmptySet Nowhere]
-
- admit checkedFoundationValue assignment imports blocks = do
- builder <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- assignment
- imports)
- admitWithBuilder builder blocks
-
- admitWithBuilder builder blocks = do
- checked <-
- Checking.runCheckingBlocks
- blocks
- (Checking.initialTransitionCheckingStateWithTaskPreparation
- Checking.WithoutDumpPremselTraining
- id
- builder
- (\_batch ->
- assertFailure
- "typed transition emitted an obligation"))
- finalBuilder <-
- maybe
- (assertFailure
- "checking lost its transition builder")
- pure
- (Checking.checkingTransitionModuleBuilder
- checked)
- expectRight
- (Transition.sealTransitionModule
- (Checking.checkingStateEnvironment checked)
- finalBuilder)
-
-rejectsForeignCachedGlobalType :: Assertion
-rejectsForeignCachedGlobalType =
- withTemporaryDirectory "felix-transition-global-types" \temp -> do
- writeTheory
- (temp Posix.</> "entry.tex")
- []
- "entry"
- graph <-
- buildSearchedGraph temp "entry.tex"
- workspace <-
- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- assignments <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals workspace)
- assignment <-
- case toList assignments of
- [only] ->
- pure only
- actual ->
- assertFailure
- ("expected one module assignment, got "
- <> show (length actual))
- >> fail "unreachable"
- checkedFoundationValue <-
- expectRight Foundation.checkedFoundation
- builderA0 <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- assignment
- [])
- builderB0 <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- assignment
- [])
- let symbol =
- SymbolPredicate
- (PredicateSymbol
- "same_nominal_global")
- declarationOrigin =
- Transition.origin
- Nowhere
- Nothing
- (Just "same_nominal_global")
- builderA <-
- expectRight
- (Transition.commitTransitionOpaqueGlobal
- symbol
- Core.TySet
- declarationOrigin
- (Transition.beginTransitionDeclaration
- builderA0))
- builderB <-
- expectRight
- (Transition.commitTransitionOpaqueGlobal
- symbol
- Core.TyProp
- declarationOrigin
- (Transition.beginTransitionDeclaration
- builderB0))
- globalA <-
- maybe
- (assertFailure "builder A lost its global"
- >> fail "unreachable")
- pure
- (Transition.lookupTransitionGlobal
- symbol
- builderA)
- globalB <-
- maybe
- (assertFailure "builder B lost its global"
- >> fail "unreachable")
- pure
- (Transition.lookupTransitionGlobal
- symbol
- builderB)
- operand <-
- expectRight
- (Core.checkCanonicalCore
- (Just . Transition.checkedGlobalType)
- (Core.CGlobal globalA))
- statement <-
- expectRight
- (Core.checkCanonicalCore
- (Just . Transition.checkedGlobalType)
- (Core.CEq
- Core.TySet
- (Core.CGlobal globalA)
- (Core.CGlobal globalA)))
- case Transition.commitTransitionKernelFact
- ("foreign_global_type" :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just "foreign_global_type"))
- statement
- (Derivation.equalityReflexivityDerivation
- operand)
- (Transition.beginTransitionDeclaration
- builderB) of
- Left
- (Transition.TransitionGlobalReferenceTypeMismatch
- actual
- authoritativeType) -> do
- assertEqual
- "cached global reference"
- globalA
- actual
- assertEqual
- "builder B authoritative type"
- Core.TyProp
- authoritativeType
- Left err ->
- assertFailure
- ("expected cached global type rejection, got "
- <> show err)
- Right _ ->
- assertFailure
- "builder B admitted builder A's cached type"
- let remappedOperand =
- Core.mapFrozenGlobals
- (const globalB)
- operand
- remappedStatement =
- Core.mapFrozenGlobals
- (const globalB)
- statement
- case Transition.commitTransitionKernelFact
- ("stale_term_annotation" :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just "stale_term_annotation"))
- remappedStatement
- (Derivation.equalityReflexivityDerivation
- remappedOperand)
- (Transition.beginTransitionDeclaration
- builderB) of
- Left
- (Transition.TransitionCoreCheckError
- (Core.EqualityOperandTypeMismatch
- Core.TySet
- Core.TyProp)) ->
- pure ()
- Left err ->
- assertFailure
- ("expected fresh builder-relative core check, got "
- <> show err)
- Right _ ->
- assertFailure
- "builder B admitted a stale term annotation"
-
-authorizesTypedVampireRequests :: Assertion
-authorizesTypedVampireRequests =
- withTemporaryDirectory "felix-typed-vampire" \temp -> do
- let sourcePath =
- temp Posix.</> "entry.tex"
- executablePath =
- temp Posix.</> "vampire"
- writeTheory sourcePath [] "entry"
- graph <-
- buildSearchedGraph temp "entry.tex"
- workspace <-
- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- assignments <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals
- workspace)
- assignment <-
- case toList assignments of
- [only] ->
- pure only
- actual ->
- assertFailure
- ("expected one module assignment, got "
- <> show (length actual))
- >> fail "unreachable"
- checkedFoundationValue <-
- expectRight Foundation.checkedFoundation
- baseBuilder <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- assignment
- [])
- let legacyStage =
- Transition.transitionBuilderLegacyStage
- baseBuilder
- legacyStaged =
- Facts.stageFact
- ("legacy_input" :| [])
- (Facts.factOrigin
- (Location 0)
- "legacy_input")
- (Facts.prepareSemanticFact Top)
- legacyReservation <-
- expectRight
- (Legacy.reserveLegacyDeclaration
- (legacyStaged :| [])
- legacyStage)
- let legacyReserved =
- NonEmpty.head
- (Legacy.legacyReservedFacts
- legacyReservation)
- legacyAdmitted =
- Legacy.authorizeLegacyDeclaredAssumption
- legacyStage
- Legacy.DeclaredUserAxiom
- legacyReserved
- legacyStage' <-
- expectRight
- (Legacy.appendEstablishedLegacyDeclaration
- legacyReservation
- (legacyAdmitted :| [])
- legacyStage)
- builderWithLegacy <-
- expectRight
- (Transition.transitionBuilderWithLegacyStage
- legacyStage'
- baseBuilder)
- target <-
- expectRight
- (Core.checkCanonicalCore
- (Just . Transition.checkedGlobalType)
- (Core.CImp
- Core.CFalsum
- Core.CFalsum))
- claim <-
- expectRight
- (Backend.supportedProposition
- (Vector.empty
- :: Vector.Vector
- (Void, Core.CoreType))
- (Core.embedClosedCore [] target))
- builderWithFof <-
- expectRight
- (Transition.commitTransitionTypedDeclaredAssumption
- ("fof_input" :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just "fof_input"))
- Legacy.DeclaredUserAxiom
- target
- (Transition.beginTransitionDeclaration
- builderWithLegacy))
- let higherOrderTarget =
- Core.mapFrozenGlobals
- absurd
- (Foundation.foundationAxiomFrozen
- checkedFoundationValue
- Foundation.DoubleNegationElim)
- builderWithTh0 <-
- expectRight
- (Transition.commitTransitionTypedDeclaredAssumption
- ("th0_input" :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just "th0_input"))
- Legacy.DeclaredUserAxiom
- higherOrderTarget
- (Transition.beginTransitionDeclaration
- builderWithFof))
- builder <-
- expectRight
- (Transition.commitTransitionTypedDeclaredAssumption
- ("second_fof_input" :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just "second_fof_input"))
- Legacy.DeclaredUserAxiom
- target
- (Transition.beginTransitionDeclaration
- builderWithTh0))
- implicitProblem <-
- expectRight
- (Transition.planTransitionTypedProblem
- builder
- claim
- []
- []
- Transition.ImplicitFofFacts
- Backend.FirstOrderLocals)
- let selected =
- Vector.toList
- (Backend.typedProblemGlobalPremises
- implicitProblem)
- references <-
- traverse
- ( maybe
- (assertFailure
- "implicit planning selected a legacy row"
- >> fail "unreachable")
- pure
- . Transition.transitionTypedFactReference
- . Backend.typedBackendFactReference
- )
- selected
- assertEqual
- "implicit planning preserves FOF admission order"
- [0, 2]
- ( Transition.localFactOrdinalValue
- . Transition.factReferenceOrdinal
- <$> references
- )
- assertEqual
- "implicit admitted-fact route"
- Backend.RouteFof
- (Backend.typedProblemRoute
- implicitProblem)
- explicitHigherOrder <-
- expectRight
- (Transition.planTransitionTypedProblem
- builder
- claim
- []
- []
- (Transition.ExplicitFacts
- ("th0_input" :| ["th0_input"]))
- Backend.FirstOrderLocals)
- assertEqual
- "explicit higher-order admitted fact selects TH0"
- Backend.RouteTh0
- (Backend.typedProblemRoute
- explicitHigherOrder)
- assertEqual
- "repeated explicit aliases select one fact"
- 1
- (Vector.length
- (Backend.typedProblemGlobalPremises
- explicitHigherOrder))
- case Transition.planTransitionTypedProblem
- builder
- claim
- []
- []
- (Transition.ExplicitFacts
- ("legacy_input" :| []))
- Backend.FirstOrderLocals of
- Left
- (Transition.TransitionTypedProblemDependencyNotMigrated
- reference) ->
- assertEqual
- "legacy dependency stays legacy"
- Nothing
- (Transition.transitionTypedFactReference
- reference)
- result' ->
- assertFailure
- ("expected legacy dependency rejection, got "
- <> case result' of
- Left err ->
- "Left " <> show err
- Right _problem ->
- "Right problem")
- problem <-
- expectRight
- (Transition.planTransitionTypedProblem
- builder
- claim
- []
- [Backend.typedFoundationAuxiliaryInput
- checkedFoundationValue
- Foundation.DoubleNegationElim]
- Transition.NoGlobalFacts
- Backend.AllLocals)
- prepared <-
- expectRight
- (Provers.prepareTypedProverTask
- Provers.DirectTask
- problem)
- mismatched <-
- expectRight
- (Provers.prepareTypedProverTask
- Provers.IndirectTask
- problem)
- assertEqual
- "higher-order foundation input selects TH0"
- Provers.VerificationTh0
- (Provers.preparedVerificationDialect
- (Provers.preparedTypedProverRequest
- prepared))
- writeFile executablePath
- (unlines
- [ "#!/bin/sh"
- , "cat >/dev/null"
- , "printf '%s\\n' '% SZS status Theorem for typed'"
- ])
- permissions <-
- Directory.getPermissions executablePath
- Directory.setPermissions executablePath
- (Directory.setOwnerExecutable
- True
- permissions)
- result <-
- runNoLoggingT
- (Provers.runPreparedTypedProver
- (Provers.vampire
- executablePath
- Provers.defaultTimeLimit
- Provers.defaultMemoryLimit)
- prepared)
- accepted <-
- case result of
- Right answer
- | Just run <-
- Provers.provedVampireRun answer ->
- pure run
- _ ->
- assertFailure
- ("expected accepted typed Vampire run, got "
- <> show result)
- >> fail "unreachable"
- let factOrigin =
- Transition.origin
- Nowhere
- Nothing
- (Just "typed_vampire")
- commit task =
- Transition.commitTransitionTypedVampireFact
- Reconstruction.defaultReconstructionPolicy
- ("typed_vampire" :| [])
- factOrigin
- target
- task
- accepted
- builder
- case commit mismatched of
- Left Transition.TransitionTypedVampireRequestMismatch ->
- pure ()
- result' ->
- assertFailure
- ("expected exact-request mismatch, got "
- <> showResult result')
- committed <-
- expectRight (commit prepared)
- admitted <-
- expectRight
- (Transition.sealTransitionModule
- Checking.initialLegacyCheckingEnvironment
- committed)
- let trust =
- Transition.transitionAdmittedTypedTrustDependencies
- admitted
- assertEqual
- "one typed trusted Vampire row"
- 1
- (Transition.transitionAdmittedTypedTrustedVampireCount
- admitted)
- assertEqual
- "one typed Vampire trust occurrence"
- 1
- (Set.size
- (Transition.typedTrustedVampireUses
- trust))
- assertEqual
- "mandatory lowering assumptions"
- Legacy.mandatoryVampireLoweringAssumptions
- (Transition.typedVampireLoweringUses
- trust)
- assertEqual
- "exact foundation input"
- (Set.singleton
- Foundation.DoubleNegationElim)
- (Transition.typedFoundationUses
- trust)
- let atom argument =
- Core.CApp
- (Core.CApp
- (Core.CIntrinsic Core.Member)
- (Core.CIntrinsic Core.Empty))
- argument
- atomP =
- atom (Core.CIntrinsic Core.Empty)
- atomQ =
- atom (Core.COpaqueInteger 1)
- atomR =
- atom (Core.COpaqueInteger 2)
- declareTyped alias statement current =
- expectRight
- (Transition.commitTransitionTypedDeclaredAssumption
- (alias :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just alias))
- Legacy.DeclaredUserAxiom
- statement
- (Transition.beginTransitionDeclaration
- current))
- premiseP <-
- expectRight
- (Core.checkCanonicalCore
- (Just . Transition.checkedGlobalType)
- atomP)
- premisePtoQ <-
- expectRight
- (Core.checkCanonicalCore
- (Just . Transition.checkedGlobalType)
- (Core.CImp atomP atomQ))
- premiseQtoR <-
- expectRight
- (Core.checkCanonicalCore
- (Just . Transition.checkedGlobalType)
- (Core.CImp atomQ atomR))
- reconstructedTarget <-
- expectRight
- (Core.checkCanonicalCore
- (Just . Transition.checkedGlobalType)
- atomR)
- builderWithP <-
- declareTyped
- "horn_p"
- premiseP
- builder
- builderWithPtoQ <-
- declareTyped
- "horn_p_to_q"
- premisePtoQ
- builderWithP
- builderWithHornInputs <-
- declareTyped
- "horn_q_to_r"
- premiseQtoR
- builderWithPtoQ
- reconstructedClaim <-
- expectRight
- (Backend.supportedProposition
- (Vector.empty
- :: Vector.Vector
- (Void, Core.CoreType))
- (Core.embedClosedCore
- []
- reconstructedTarget))
- reconstructedProblem <-
- expectRight
- (Transition.planTransitionTypedProblem
- builderWithHornInputs
- reconstructedClaim
- []
- []
- (Transition.ExplicitFacts
- ("horn_p"
- :| [ "horn_p_to_q"
- , "horn_q_to_r"
- ]))
- Backend.FirstOrderLocals)
- reconstructedPrepared <-
- expectRight
- (Provers.prepareTypedProverTask
- Provers.DirectTask
- reconstructedProblem)
- reconstructedResult <-
- runNoLoggingT
- (Provers.runPreparedTypedProver
- (Provers.vampire
- executablePath
- Provers.defaultTimeLimit
- Provers.defaultMemoryLimit)
- reconstructedPrepared)
- reconstructedAccepted <-
- case reconstructedResult of
- Right answer
- | Just run <-
- Provers.provedVampireRun answer ->
- pure run
- _ ->
- assertFailure
- ("expected accepted Horn Vampire run, got "
- <> show reconstructedResult)
- >> fail "unreachable"
- reconstructedBuilder <-
- expectRight
- (Transition.commitTransitionTypedVampireFact
- Reconstruction.defaultReconstructionPolicy
- ("horn_result" :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just "horn_result"))
- reconstructedTarget
- reconstructedPrepared
- reconstructedAccepted
- builderWithHornInputs)
- reconstructedModule <-
- expectRight
- (Transition.sealTransitionModule
- Checking.initialLegacyCheckingEnvironment
- reconstructedBuilder)
- reconstructedFact <-
- case Vector.unsnoc
- (Transition.transitionAdmittedFacts
- reconstructedModule) of
- Just (_earlier, finalFact) ->
- pure finalFact
- Nothing ->
- assertFailure
- "expected a reconstructed admitted fact"
- >> fail "unreachable"
- assertBool
- "supported accepted task becomes a reconstructed kernel proof"
- (Transition.admittedFactIsReconstructedKernelProof
- reconstructedFact)
- reconstructedTrust <-
- maybe
- (assertFailure
- "expected typed reconstructed trust")
- pure
- (Transition.admittedFactTypedTrustDependencies
- reconstructedFact)
- assertEqual
- "reconstruction inherits its three exact assumptions"
- 3
- (Set.size
- (Transition.typedDeclaredAssumptionUses
- reconstructedTrust))
- assertEqual
- "reconstructed run adds no trusted Vampire leaf"
- Set.empty
- (Transition.typedTrustedVampireUses
- reconstructedTrust)
- assertEqual
- "reconstructed run adds no Vampire lowering trust"
- Set.empty
- (Transition.typedVampireLoweringUses
- reconstructedTrust)
- tinyKernelLimits <-
- expectRight
- (Derivation.kernelReplayLimits 1 10)
- let tinyKernelPolicy =
- Reconstruction.reconstructionPolicy
- (Reconstruction.reconstructionPolicyConnectionLimits
- Reconstruction.defaultReconstructionPolicy)
- tinyKernelLimits
- fallbackBuilder <-
- expectRight
- (Transition.commitTransitionTypedVampireFact
- tinyKernelPolicy
- ("horn_fallback" :| [])
- (Transition.origin
- Nowhere
- Nothing
- (Just "horn_fallback"))
- reconstructedTarget
- reconstructedPrepared
- reconstructedAccepted
- builderWithHornInputs)
- fallbackModule <-
- expectRight
- (Transition.sealTransitionModule
- Checking.initialLegacyCheckingEnvironment
- fallbackBuilder)
- fallbackFact <-
- case Vector.unsnoc
- (Transition.transitionAdmittedFacts
- fallbackModule) of
- Just (_earlier, finalFact) ->
- pure finalFact
- Nothing ->
- assertFailure
- "expected a kernel-exhaustion fallback fact"
- >> fail "unreachable"
- assertBool
- "kernel exhaustion retains accepted Vampire authority"
- (Transition.admittedFactIsTrustedVampire
- fallbackFact)
- where
- showResult = \case
- Left err ->
- "Left " <> show err
- Right _builder ->
- "Right builder"
-
-publishesTypedInductive :: Assertion
-publishesTypedInductive =
- withTemporaryDirectory "felix-transition-inductive" \temp -> do
- writeTheory
- (temp Posix.</> "entry.tex")
- []
- "entry"
- graph <- buildSearchedGraph temp "entry.tex"
- workspace <-
- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- assignments <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals
- workspace)
- assignment <-
- case toList assignments of
- [only] ->
- pure only
- actual ->
- assertFailure
- ("expected one module assignment, got "
- <> show (length actual))
- >> fail "unreachable"
- checkedFoundationValue <-
- expectRight Foundation.checkedFoundation
- builder <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- assignment
- [])
- let unprovedCarrier =
- TermOp Nowhere unprovedInductiveSymbol []
- unprovedBlocks =
- [ BlockInductive
- Nowhere
- "unproved_inductive"
- Inductive
- { inductiveSymbol =
- unprovedInductiveSymbol
- , inductiveParams = []
- , inductiveDomain =
- EmptySet Nowhere
- , inductiveIntros =
- IntroRule
- []
- ( EmptySet Nowhere
- `isElementOf`
- unprovedCarrier
- )
- :| []
- }
- ]
- unproved <-
- try
- (Checking.runCheckingBlocks
- unprovedBlocks
- (Checking.initialTransitionCheckingStateWithTaskPreparation
- Checking.WithoutDumpPremselTraining
- id
- builder
- (\_batch ->
- assertFailure
- "unproved inductive emitted a legacy obligation")))
- :: IO
- (Either
- Checking.CheckingError
- Checking.CheckingState)
- case unproved of
- Left checkingError ->
- assertBool
- "missing exact guard is reported"
- ("has no authorized typed fact"
- `Text.isInfixOf`
- Text.pack (show checkingError))
- Right _checked ->
- assertFailure
- "inductive with an unproved domain guard was admitted"
- unchanged <-
- expectRight
- (Transition.sealTransitionModule
- Checking.initialLegacyCheckingEnvironment
- builder)
- assertEqual
- "failed inductive publishes no global"
- 0
- (Vector.length
- (Transition.transitionAdmittedGlobals
- unchanged))
- assertEqual
- "failed inductive publishes no fact"
- 0
- (Vector.length
- (Transition.transitionAdmittedFacts
- unchanged))
- let parameter =
- NamedVar "domain"
- domain =
- TermOp
- Nowhere
- cumulSymbol
- [TermVar parameter]
- carrier =
- TermOp
- Nowhere
- typedInductiveSymbol
- [TermVar parameter]
- blocks =
- [ BlockInductive
- Nowhere
- "typed_inductive"
- Inductive
- { inductiveSymbol =
- typedInductiveSymbol
- , inductiveParams = [parameter]
- , inductiveDomain = domain
- , inductiveIntros =
- IntroRule
- []
- (TermVar parameter
- `isElementOf`
- carrier)
- :| []
- }
- ]
- checked <-
- Checking.runCheckingBlocks
- blocks
- (Checking.initialTransitionCheckingStateWithTaskPreparation
- Checking.WithoutDumpPremselTraining
- id
- builder
- (\_batch ->
- assertFailure
- "typed inductive emitted a legacy obligation"))
- finalBuilder <-
- maybe
- (assertFailure
- "checking lost its transition builder"
- >> fail "unreachable")
- pure
- (Checking.checkingTransitionModuleBuilder
- checked)
- admitted <-
- expectRight
- (Transition.sealTransitionModule
- (Checking.checkingStateEnvironment
- checked)
- finalBuilder)
- assertEqual
- "one transparent carrier"
- 1
- (Vector.length
- (Transition.transitionAdmittedGlobals
- admitted))
- assertEqual
- "four derived facts"
- [True, True, True, True]
- ( Transition.admittedFactIsKernelProof
- <$> Vector.toList
- (Transition.transitionAdmittedFacts
- admitted)
- )
- assertEqual
- "four replayed inductive facts"
- 4
- (Transition.transitionAdmittedKernelProofCount
- admitted)
- assertBool
- "foundation guard dependency is retained"
- (Foundation.UnivOfContains
- `Set.member`
- Transition.typedFoundationUses
- (Transition.transitionAdmittedTypedTrustDependencies
- admitted))
- where
- typedInductiveSymbol =
- mkMixfixItem
- [ Just (Command "typedfin")
- , Just InvisibleBraceL
- , Nothing
- , Just InvisibleBraceR
- ]
- "typed_inductive"
- NonAssoc
-
- cumulSymbol =
- mkMixfixItem
- [ Just (Command "cumul")
- , Just InvisibleBraceL
- , Nothing
- , Just InvisibleBraceR
- ]
- "cumul"
- NonAssoc
-
- unprovedInductiveSymbol =
- mkMixfixItem
- [Just (Command "unprovedfin")]
- "unproved_inductive"
- NonAssoc
-
-publishesLegacyImportViews :: Assertion
-publishesLegacyImportViews =
- withTemporaryDirectory "felix-legacy-import-view" \temp -> do
- writeTheory (temp Posix.</> "shared.tex") [] "shared"
- writeTheory
- (temp Posix.</> "a.tex")
- ["shared.tex"]
- "a"
- writeTheory
- (temp Posix.</> "b.tex")
- ["shared.tex"]
- "b"
- writeTheory
- (temp Posix.</> "entry.tex")
- ["a.tex", "b.tex"]
- "entry"
- graph <- buildSearchedGraph temp "entry.tex"
- workspace <-
- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- assignments <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals workspace)
- case toList assignments of
- [ sharedAssignment
- , aAssignment
- , bAssignment
- , entryAssignment
- ] -> do
- shared <-
- admitOne
- sharedAssignment
- (Legacy.emptyLegacyImportedView
- Checking.initialLegacyCheckingEnvironment)
- "shared_fact"
- Bottom
- (Location 1)
- sharedView <-
- expectRight
- (Legacy.legacyImportedView
- Checking.initialLegacyCheckingEnvironment
- [shared])
- a <-
- admitOne
- aAssignment
- sharedView
- "a_fact"
- Top
- (Location 2)
- b <-
- admitOne
- bAssignment
- sharedView
- "b_fact"
- Top
- (Location 3)
- diamondView <-
- expectRight
- (Legacy.legacyImportedView
- Checking.initialLegacyCheckingEnvironment
- [a, b])
- entry <-
- expectRight
- (Legacy.sealLegacyModuleStage
- (Legacy.legacyImportedCheckingEnvironment
- diamondView)
- (Legacy.openLegacyModuleStage
- entryAssignment
- diamondView))
- assertEqual
- "direct imports retain textual order"
- [1, 2]
- ( Legacy.legacyModuleOrdinalValue
- <$> Vector.toList
- (Legacy.legacyAdmittedDirectImports
- entry)
- )
- assertEqual
- "diamond facts retain imported source order"
- [0, 1, 2]
- ( Legacy.legacyModuleOrdinalValue
- . Legacy.legacyFactModule
- . Legacy.legacyFactEntryReference
- <$> Vector.toList
- (Legacy.legacyAdmittedVisibleFacts
- entry)
- )
- assertEqual
- "equal statements at different references remain"
- 3
- (Vector.length
- (Legacy.legacyAdmittedVisibleFacts entry))
- let environmentSymbol =
- SymbolMixfix
- (mkMixfixItem
- [Just
- (Command
- "module_environment")]
- "module_environment"
- NonAssoc)
- environmentWith body =
- Legacy.legacyCheckingEnvironment
- (HashMap.insert
- environmentSymbol
- (toScope body)
- (Legacy.legacyEnvironmentAbbreviations
- Checking.initialLegacyCheckingEnvironment))
- (Legacy.legacyEnvironmentPredicateDefinitions
- Checking.initialLegacyCheckingEnvironment)
- (Legacy.legacyEnvironmentDependencies
- Checking.initialLegacyCheckingEnvironment)
- (Legacy.legacyEnvironmentOwnedSymbols
- Checking.initialLegacyCheckingEnvironment)
- (Legacy.legacyEnvironmentOwnedSymbolMarkers
- Checking.initialLegacyCheckingEnvironment)
- (Legacy.legacyEnvironmentFrozenSymbols
- Checking.initialLegacyCheckingEnvironment)
- (Legacy.legacyEnvironmentStructs
- Checking.initialLegacyCheckingEnvironment)
- (Legacy.legacyEnvironmentDefinedMarkers
- Checking.initialLegacyCheckingEnvironment)
- environmentA <-
- admitEnvironment
- aAssignment
- (Legacy.emptyLegacyImportedView
- Checking.initialLegacyCheckingEnvironment)
- (environmentWith Top)
- environmentView <-
- expectRight
- (Legacy.legacyImportedView
- Checking.initialLegacyCheckingEnvironment
- [environmentA])
- assertEqual
- "admitted semantic environment is imported"
- (Just (toScope Top))
- (HashMap.lookup
- environmentSymbol
- (Legacy.legacyEnvironmentAbbreviations
- (Legacy.legacyImportedCheckingEnvironment
- environmentView)))
- environmentB <-
- admitEnvironment
- bAssignment
- (Legacy.emptyLegacyImportedView
- Checking.initialLegacyCheckingEnvironment)
- (environmentWith Bottom)
- case Legacy.legacyImportedView
- Checking.initialLegacyCheckingEnvironment
- [environmentA, environmentB] of
- Left Legacy.LegacyImportedEnvironmentConflict{} ->
- pure ()
- Left err ->
- assertFailure
- ("expected imported environment conflict, got "
- <> show err)
- Right _ ->
- assertFailure
- "expected imported environment conflict"
-
- conflictingA <-
- admitOne
- aAssignment
- (Legacy.emptyLegacyImportedView
- Checking.initialLegacyCheckingEnvironment)
- "conflicting"
- Top
- (Location 4)
- conflictingB <-
- admitOne
- bAssignment
- (Legacy.emptyLegacyImportedView
- Checking.initialLegacyCheckingEnvironment)
- "conflicting"
- Bottom
- (Location 5)
- case Legacy.legacyImportedView
- Checking.initialLegacyCheckingEnvironment
- [conflictingA, conflictingB] of
- Left Legacy.LegacyImportedAliasConflict{} ->
- pure ()
- Left err ->
- assertFailure
- ("expected imported alias conflict, got "
- <> show err)
- Right _ ->
- assertFailure
- "expected imported alias conflict"
- actual ->
- assertFailure
- ("expected four module assignments, got "
- <> show (length actual))
- where
- admitOne assignment imported alias statement location = do
- let stage =
- Legacy.openLegacyModuleStage
- assignment
- imported
- staged =
- Facts.stageFact
- (alias :| [])
- (Facts.factOrigin location alias)
- (Facts.prepareSemanticFact statement)
- reservation <-
- expectRight
- (Legacy.reserveLegacyDeclaration
- (staged :| [])
- stage)
- let reserved =
- NonEmpty.head
- (Legacy.legacyReservedFacts reservation)
- admitted =
- Legacy.authorizeLegacyDeclaredAssumption
- stage
- Legacy.DeclaredUserAxiom
- reserved
- stage' <-
- expectRight
- (Legacy.appendEstablishedLegacyDeclaration
- reservation
- (admitted :| [])
- stage)
- expectRight
- (Legacy.sealLegacyModuleStage
- (Legacy.legacyImportedCheckingEnvironment imported)
- stage')
-
- admitEnvironment assignment imported finalEnvironment =
- expectRight
- (Legacy.sealLegacyModuleStage
- finalEnvironment
- (Legacy.openLegacyModuleStage assignment imported))
-
rejectsSiblingSyntaxLeakage :: Assertion
rejectsSiblingSyntaxLeakage =
withTemporaryDirectory "felix-source-syntax-world" \temp -> do
@@ -3667,48 +2027,6 @@ acceptsAdjectiveSignature =
_ ->
assertFailure
("unexpected adjective-signature blocks: " <> show blocks)
- semanticBlocks <- expectRight (Meaning.meaning blocks)
- void
- (Checking.check
- Checking.WithoutDumpPremselTraining
- semanticBlocks)
-
-rejectsQuantifiedSymbolicSignatureTerm :: Assertion
-rejectsQuantifiedSymbolicSignatureTerm =
- withTemporaryDirectory "felix-source-signature-quantified-term" \temp -> do
- writeFile
- (temp Posix.</> "entry.tex")
- (unlines
- [ "\\begin{definition}\\label{bridge}"
- , " $z$ is a bridge from $A$ to $B$ iff $z = z$ and $A = A$ and $B = B$."
- , "\\end{definition}"
- , "\\begin{signature}\\label{bridge_signature}"
- , " $\\foo{A}$ is a bridge from every set $x$ to $x$."
- , "\\end{signature}"
- ])
- graph <- buildSearchedGraph temp "entry.tex"
- workspace <- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- case Meaning.meaning
- (Parse.importedBeforeImporterBlocks workspace) of
- Left (Meaning.QuantifiedTermRequiresResolvedContext location) -> do
- assertEqual "quantified term file"
- "entry.tex"
- (locFile location)
- assertEqual "quantified term line"
- 5
- (locLine location)
- assertEqual "quantified term column"
- 30
- (locColumn location)
- Left err ->
- assertFailure
- ("expected quantified-term context error, got "
- <> show err)
- Right blocks ->
- assertFailure
- ("expected quantified-term context rejection, got "
- <> show blocks)
rejectsMalformedSignatureHead :: Assertion
rejectsMalformedSignatureHead = do
@@ -3902,162 +2220,6 @@ acceptsBuiltinPrefixPredicateDeclaration =
("unexpected built-in prefix declaration parse: "
<> show blocks)
-rejectsDuplicateFixedBaseSemantics :: Assertion
-rejectsDuplicateFixedBaseSemantics =
- withTemporaryDirectory "felix-source-builtin-collision" \temp -> do
- writeBuiltinZeroDefinition
- (temp Posix.</> "a.tex")
- "source_zero_a"
- writeFile
- (temp Posix.</> "entry.tex")
- ("\\import{a.tex}\n"
- <> builtinZeroDefinition "source_zero_b")
- graph <- buildSearchedGraph temp "entry.tex"
- workspace <- expectRight
- =<< Parse.parseResolvedSourceGraph graph
- assignments <-
- expectRight
- (Legacy.assignLegacyModuleOrdinals workspace)
- case toList assignments of
- [acceptedAssignment, collidingAssignment] -> do
- let acceptedParsed =
- Legacy.assignedParsedModule acceptedAssignment
- collidingParsed =
- Legacy.assignedParsedModule collidingAssignment
- acceptedLocation <-
- onlySyntaxOccurrenceLocation acceptedParsed
- collidingLocation <-
- onlySyntaxOccurrenceLocation collidingParsed
- assertLocation
- "accepted declaration"
- "a.tex"
- 1
- acceptedLocation
- assertLocation
- "colliding declaration"
- "entry.tex"
- 2
- collidingLocation
- assertEqual
- "fixed reuses emit no syntax delta"
- [[], []]
- [ Interface.canonicalSyntaxDeltaEntries
- (Interface.moduleSyntaxLocalDelta
- (Parse.parsedModuleSyntaxInterface parsed))
- | parsed <- [acceptedParsed, collidingParsed]
- ]
-
- checkedFoundationValue <-
- expectRight Foundation.checkedFoundation
- (acceptedBlocks, glossState) <-
- glossParsedBlocks
- Meaning.initialGlossState
- acceptedParsed
- acceptedBuilder <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- acceptedAssignment
- [])
- acceptedState <-
- Checking.runCheckingBlocks
- acceptedBlocks
- (checkingState acceptedBuilder)
- finalAcceptedBuilder <-
- expectJust
- "accepted transition builder"
- (Checking.checkingTransitionModuleBuilder
- acceptedState)
- acceptedModule <-
- expectRight
- (Transition.sealTransitionModule
- (Checking.checkingStateEnvironment
- acceptedState)
- finalAcceptedBuilder)
-
- (collidingBlocks, _finalGlossState) <-
- glossParsedBlocks glossState collidingParsed
- collidingBuilder <-
- expectRight
- (Transition.openTransitionModuleBuilder
- checkedFoundationValue
- Checking.initialLegacyCheckingEnvironment
- collidingAssignment
- [acceptedModule])
- result <-
- try
- (Checking.runCheckingBlocks
- collidingBlocks
- (checkingState collidingBuilder))
- :: IO
- (Either
- Checking.CheckingError
- Checking.CheckingState)
- case result of
- Left
- (Checking.CheckingError
- message
- location
- marker) -> do
- assertEqual
- "semantic collision location"
- collidingLocation
- location
- assertEqual
- "semantic collision marker"
- "source_zero_b"
- marker
- assertBool
- "accepted owner is identified"
- ("already owned by abbreviation source_zero_a"
- `Text.isInfixOf` message)
- Left err ->
- assertFailure
- ("expected located ownership collision, got "
- <> show err)
- Right _checked ->
- assertFailure
- "duplicate fixed-base semantics were accepted"
- actual ->
- assertFailure
- ("expected two module assignments, got "
- <> show (length actual))
- where
- checkingState builder =
- Checking.initialTransitionCheckingStateWithTaskPreparation
- Checking.WithoutDumpPremselTraining
- id
- builder
- (\_batch ->
- assertFailure
- "fixed-base abbreviation emitted an obligation")
-
- glossParsedBlocks initialState parsed =
- fmap
- (\(reversed, finalState) ->
- (reverse reversed, finalState))
- (foldM
- glossOne
- ([], initialState)
- (Parse.parsedModuleBlocks parsed))
-
- glossOne (reversed, state) raw = do
- (block, nextState) <-
- expectRight (Meaning.glossStep state raw)
- pure (block : reversed, nextState)
-
- onlySyntaxOccurrenceLocation parsed =
- case Parse.parsedModuleSyntaxOccurrences parsed of
- [occurrence] ->
- pure
- (Parse.parsedSyntaxOccurrenceLocation
- occurrence)
- occurrences ->
- assertFailure
- ("expected one fixed-base occurrence, got "
- <> show occurrences)
-
avoidsAliasImportLexiconCollision :: Assertion
avoidsAliasImportLexiconCollision =
withTemporaryDirectory "felix-source-alias-lexicon" \temp -> do
diff --git a/source/Test/Unit/Store.hs b/source/Test/Unit/Store.hs
index 9f25a3b..e2896c3 100644
--- a/source/Test/Unit/Store.hs
+++ b/source/Test/Unit/Store.hs
@@ -21,6 +21,7 @@ import Felix.Store qualified as Store
import Provers qualified
import Syntax.Interface qualified as Syntax
+import Control.Concurrent (threadDelay)
import Control.Exception qualified as Exception
import Data.ByteString qualified as ByteString
import Data.ByteString.Char8 qualified as ByteString.Char8
@@ -33,6 +34,7 @@ import System.FilePath.Posix qualified as Posix
import System.IO.Temp qualified as Temp
import Test.Tasty
import Test.Tasty.HUnit
+import UnliftIO.Async (concurrently)
unitTests :: TestTree
@@ -40,6 +42,8 @@ unitTests =
testGroup "SQLite store"
[ testCase "initializes and reopens the current schema"
initializesAndReopensCurrentSchema
+ , testCase "serializes invocation-local coordinator access"
+ serializesCoordinatorAccess
, testCase "rejects incompatibility without configuring the store"
rejectsIncompatibilityWithoutConfiguration
, testCase "rejects malformed compatibility metadata"
@@ -80,6 +84,28 @@ unitTests =
doesNotFallBackAfterFatalStartup
]
+serializesCoordinatorAccess :: Assertion
+serializesCoordinatorAccess = do
+ coordinator <- Store.newStoreCoordinator
+ active <- IORef.newIORef (0 :: Int)
+ maximumActive <- IORef.newIORef (0 :: Int)
+ let operation =
+ Store.withStoreCoordinator coordinator
+ (Exception.bracket_
+ (IORef.atomicModifyIORef' active
+ (\current ->
+ let next = current + 1
+ in (next, ())))
+ (IORef.atomicModifyIORef' active
+ (\current -> (current - 1, ())))
+ (do
+ current <- IORef.readIORef active
+ IORef.atomicModifyIORef' maximumActive
+ (\observed -> (max current observed, ()))
+ threadDelay 50000))
+ void (concurrently operation operation)
+ IORef.readIORef maximumActive >>= assertEqual "maximum owner count" 1
+
roundTripsExactParsedArtifacts :: Assertion
roundTripsExactParsedArtifacts =
withStoreFixture "felix-store-parsed" \path theory _fixture -> do
diff --git a/source/Test/Unit/Symdiff.hs b/source/Test/Unit/Symdiff.hs
deleted file mode 100644
index ec62fda..0000000
--- a/source/Test/Unit/Symdiff.hs
+++ /dev/null
@@ -1,132 +0,0 @@
-module Test.Unit.Symdiff where
-
-import Base
-import Bound.Scope
-import Bound.Var
-import Syntax.Internal
-import Filter
-import Report.Location
-
-import Data.Map qualified as Map
-import Data.Set qualified as Set
-import Data.Text qualified as Text
-
-mixfix :: [Maybe Token] -> FunctionSymbol
-mixfix pat = mkMixfixItem pat (markerFromPattern pat) NonAssoc
- where
- markerFromPattern = \case
- Just tok : _ -> markerFromToken tok
- Nothing : rest -> markerFromPattern rest
- [] -> Marker "mixfix"
-
-subsetSymbol :: RelationSymbol
-subsetSymbol =
- RelationSymbol (Command "subset") zeroParameterArity "subset"
-
-adjInhabited :: LexicalItem
-adjInhabited = mkLexicalItem [Just (Word "inhabited")] "inhabited"
-
-adjDisjointFrom :: LexicalItem
-adjDisjointFrom = mkLexicalItem [Just (Word "disjoint"), Just (Word "from"), Nothing] "disjoint"
-
-filtersWell :: Bool
-filtersWell = badFact `notElem` (hypothesisFormula <$> taskHypotheses (filterTask symdiff))
-
-
-handlesStructAndApply :: Bool
-handlesStructAndApply =
- let
- structOp = StructSymbol "foo_op"
- structTerm = TermSymbolStruct structOp (Just (TermVar (NamedVar "A")))
- formula = Apply (TermVar (NamedVar "f")) (structTerm :| [])
- hypo = Hypothesis
- { hypothesisMarker = Marker "struct_apply"
- , hypothesisFormula = formula
- }
- in Map.member hypo (relevantFacts passmark formula (Set.singleton hypo))
-
-
-badFact :: ExprOf a
-badFact = Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "FreshReplacementVar")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]]) (Quantified Existentially (Scope (Connected Conjunction (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (F (TermVar (B (NamedVar "A"))))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "b")), TermVar (F (TermVar (B (NamedVar "B"))))])) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (F (TermVar (B (NamedVar "FreshReplacementVar")))), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "b"))]]))))))
-
-
-symdiff :: Task
-symdiff =
- Task
- { taskDirectness = Direct
- , taskLocation = Nowhere
- , taskConjectureLabel = Marker "symdiff_test"
- , taskHypotheses = zipWith
- Hypothesis
- (Marker . Text.pack . show <$> ([1..] :: [Int]))
- [ Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "A"))], TermVar (B (NamedVar "A"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "B")), TermVar (B (NamedVar "A"))]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "A")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) []], TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) []]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "z"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "z"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))], TermVar (B (NamedVar "C"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "A")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "B")), TermVar (B (NamedVar "C"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "x"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) []]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "z"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "z"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) []], TermVar (B (NamedVar "x"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "symdiff"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "x"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "Y")), TermVar (B (NamedVar "Z"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "Y")), TermVar (B (NamedVar "Z"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Y"))], TermVar (B (NamedVar "Z"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Z"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "Y")), TermVar (B (NamedVar "Z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Y"))], TermVar (B (NamedVar "Z"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Z"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "Y")), TermVar (B (NamedVar "Z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "A"))], TermVar (B (NamedVar "A"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "B")), TermVar (B (NamedVar "A"))]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) []], TermVar (B (NamedVar "A"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "z"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "z"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))], TermVar (B (NamedVar "C"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "B")), TermVar (B (NamedVar "C"))]]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "inters"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "Pow"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "A"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) []]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "unions"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "Pow"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "A"))]], TermVar (B (NamedVar "A"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "fst"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "b"))]], TermVar (B (NamedVar "a"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "snd"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "b"))]], TermVar (B (NamedVar "b"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "A")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "Pow"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "A"))]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "Cons"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR, Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "X"))]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) [], TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "Pow"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "A"))]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation NeqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "b"))], TermVar (B (NamedVar "a"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation NeqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "b"))], TermVar (B (NamedVar "b"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "A"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))], TermVar (B (NamedVar "A"))]))
- , Quantified Universally (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) [], TermVar (B (NamedVar "a"))]))
- , Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjDisjointFrom)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjDisjointFrom)) [TermVar (B (NamedVar "B")), TermVar (B (NamedVar "A"))])))
- , Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))], TermVar (B (NamedVar "B"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))])))
- , Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "A"))])))
- , Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]]) (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "B"))]))))
- , Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Y"))]]) (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "X"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "Y"))]))))
- , Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation NeqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (Quantified Existentially (Scope (Connected ExclusiveOr (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "c")), TermVar (F (TermVar (B (NamedVar "A"))))]) (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "c")), TermVar (F (TermVar (B (NamedVar "B"))))]))) (Connected Conjunction (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "c")), TermVar (F (TermVar (B (NamedVar "A"))))])) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "c")), TermVar (F (TermVar (B (NamedVar "B"))))])))))))
- , Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))], TermVar (B (NamedVar "B"))])))
- , Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Y"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Z"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "Y")), TermVar (B (NamedVar "Z"))]])))
- , Quantified Universally (Scope (Connected Implication (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "A"))]) (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "B"))]))) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]])))
- , Quantified Universally (Scope (Connected Implication (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "X"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "Y"))])) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Y"))]])))
- , Quantified Universally (Scope (Connected Implication (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "B")), TermVar (B (NamedVar "A"))])) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))])))
- , Quantified Universally (Scope (Connected Implication (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "B")), TermVar (B (NamedVar "C"))])) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "C"))])))
- , Quantified Universally (Scope (Connected Implication (Connected Conjunction (PropositionalConstant IsTop) (PropositionalConstant IsTop)) (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]]) (Connected Disjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "A"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "B"))])))))
- , Quantified Universally (Scope (Connected Implication (Connected Conjunction (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermVar (B (NamedVar "x"))])) (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermVar (B (NamedVar "y"))]))) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))])))
- , Quantified Universally (Scope (Connected Implication (Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (F (TermVar (B (NamedVar "A"))))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (F (TermVar (B (NamedVar "B"))))])))) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))])))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjDisjointFrom)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (Quantified Universally (Scope (Not Nowhere (Quantified Existentially (Scope (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (F (TermVar (F (TermVar (B (NamedVar "A"))))))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (F (TermVar (F (TermVar (B (NamedVar "B"))))))])))))))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermVar (B (NamedVar "A"))]) (Quantified Universally (Scope (Quantified Existentially (Scope (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (F (TermVar (F (TermVar (B (NamedVar "A"))))))])))))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermVar (B (NamedVar "A"))]) (Not Nowhere (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermVar (B (NamedVar "A"))])))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "b"))], TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "aprime")), TermVar (B (NamedVar "bprime"))]]) (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "aprime"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "b")), TermVar (B (NamedVar "bprime"))]))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "a")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "b")), TermVar (B (NamedVar "c"))]], TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "aprime")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Word "pair")])) [TermVar (B (NamedVar "bprime")), TermVar (B (NamedVar "cprime"))]]]) (Connected Conjunction (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "aprime"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "b")), TermVar (B (NamedVar "bprime"))])) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "c")), TermVar (B (NamedVar "cprime"))]))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "B")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "Pow"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "A"))]]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "B")), TermVar (B (NamedVar "A"))])))
- , badFact
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]]) (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "A"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "B"))]))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]]) (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "A"))]) (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (B (NamedVar "B"))])))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "x")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "Cons"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR, Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "y")), TermVar (B (NamedVar "X"))]]) (Connected Disjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "y"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "X"))]))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "z")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "inters"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "X"))]]) (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermVar (B (NamedVar "X"))]) (Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "Y")), TermVar (F (TermVar (B (NamedVar "X"))))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (F (TermVar (B (NamedVar "z")))), TermVar (B (NamedVar "Y"))])))))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "z")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "unions"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "X"))]]) (Quantified Existentially (Scope (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "Y")), TermVar (F (TermVar (B (NamedVar "X"))))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (F (TermVar (B (NamedVar "z")))), TermVar (B (NamedVar "Y"))]))))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation subsetSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (Quantified Universally (Scope (Connected Conjunction (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (F (TermVar (B (NamedVar "A")))), TermVar (F (TermVar (B (NamedVar "B"))))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation NeqSymbol)) [TermVar (F (TermVar (B (NamedVar "A")))), TermVar (F (TermVar (B (NamedVar "B"))))]))))))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation EqSymbol)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))], TermVar (B (NamedVar "A"))])))
- , Quantified Universally (Scope (Connected Equivalence (TermSymbol Nowhere (SymbolPredicate (PredicateRelation SubseteqSymbol)) [TermVar (B (NamedVar "A")), TermVar (B (NamedVar "B"))]) (Quantified Universally (Scope (Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (F (TermVar (F (TermVar (B (NamedVar "A"))))))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermVar (F (TermVar (F (TermVar (B (NamedVar "B"))))))]))))))))
- , Quantified Universally (Scope (Connected Equivalence (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "times"), Nothing])) [TermVar (B (NamedVar "X")), TermVar (B (NamedVar "Y"))]])) (Connected Disjunction (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermVar (B (NamedVar "X"))])) (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateAdj adjInhabited)) [TermVar (B (NamedVar "Y"))])))))
- , Quantified Universally (Scope (Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (F (TermVar (B (NamedVar "y")))), TermVar (B (NamedVar "X"))]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (F (TermVar (B (NamedVar "y")))), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "Cons"), Just InvisibleBraceL, Nothing, Just InvisibleBraceR, Just InvisibleBraceL, Nothing, Just InvisibleBraceR])) [TermVar (B (NamedVar "x")), TermVar (B (NamedVar "X"))]])))))
- , Quantified Universally (Scope (Not Nowhere (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (NamedVar "a")), TermSymbol Nowhere (SymbolMixfix (mixfix [Just (Command "emptyset")])) []])))
- ]
- , taskConjecture =
- Quantified Universally (Scope (Connected Implication (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (FreshVar 0)), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "setminus"), Nothing])) [TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "union"), Nothing])) [TermVar (F (TermVar (NamedVar "x"))), TermVar (F (TermVar (NamedVar "y")))], TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "inter"), Nothing])) [TermVar (F (TermVar (NamedVar "y"))), TermVar (F (TermVar (NamedVar "x")))]]]) (TermSymbol Nowhere (SymbolPredicate (PredicateRelation ElementSymbol)) [TermVar (B (FreshVar 0)), TermSymbol Nowhere (SymbolMixfix (mixfix [Nothing, Just (Command "symdiff"), Nothing])) [TermVar (F (TermVar (NamedVar "x"))), TermVar (F (TermVar (NamedVar "y")))]])))
- }
diff --git a/source/Test/Unit/Token.hs b/source/Test/Unit/Token.hs
index b676f55..d399e2a 100644
--- a/source/Test/Unit/Token.hs
+++ b/source/Test/Unit/Token.hs
@@ -22,6 +22,8 @@ unitTests = testGroup "Lexer"
, testCase "braces inside text do not close the text frame" textBraceNesting
, testCase "cases is tokenized as an environment only inside math" casesOnlyInsideMath
, testCase "imports retain source locations and POSIX spellings" locatedImports
+ , testCase "commented environment starts are ignored"
+ ignoresCommentedEnvironmentStart
, testCase "empty inputs construct empty lexical syntax"
constructsEmptyLexicalSyntax
, testCase "extracts exact source fixity pragmas"
@@ -130,6 +132,24 @@ locatedImports = do
Right imports ->
assertFailure ("expected two imports, got " <> show imports)
+ignoresCommentedEnvironmentStart :: Assertion
+ignoresCommentedEnvironmentStart = do
+ let raw = Text.unlines
+ [ "% \\begin{signature}"
+ , "ordinary text"
+ , "\\begin{struct}"
+ , " an ordered set $X$ is a onesorted structure."
+ , "\\end{struct}"
+ ]
+ (_, chunks) <-
+ either
+ (assertFailure . errorBundlePretty)
+ pure
+ (runLexer (FileId maxBound) "commented-environment" raw)
+ case chunks of
+ [Located{unLocated = BeginEnv "struct"} : _] -> pure ()
+ _ -> assertFailure ("expected the real structure environment, got " <> show chunks)
+
constructsEmptyLexicalSyntax :: Assertion
constructsEmptyLexicalSyntax =
forM_