summaryrefslogtreecommitdiff
path: root/source/Felix/Checking/Backend
diff options
context:
space:
mode:
Diffstat (limited to 'source/Felix/Checking/Backend')
-rw-r--r--source/Felix/Checking/Backend/Problem.hs1301
-rw-r--r--source/Felix/Checking/Backend/Tptp.hs1281
2 files changed, 2582 insertions, 0 deletions
diff --git a/source/Felix/Checking/Backend/Problem.hs b/source/Felix/Checking/Backend/Problem.hs
new file mode 100644
index 0000000..0390020
--- /dev/null
+++ b/source/Felix/Checking/Backend/Problem.hs
@@ -0,0 +1,1301 @@
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+-- | Complete-problem FOF/TH0 classification and construction.
+module Felix.Checking.Backend.Problem
+ ( SupportedProposition
+ , supportedProposition
+ , projectSupportedProposition
+ , supportedPropositionSupport
+ , supportedPropositionTerm
+ , weakenClosedSupportedProposition
+ , SupportedPropositionError(..)
+ , SupportedPropositionProjectionError(..)
+ , CheckedFofProjection
+ , checkedFofProjectionProposition
+ , FofCapability(..)
+ , BackendFofExclusion(..)
+ , BackendClassificationError(..)
+ , classifySupportedProposition
+ , TypedBackendFact
+ , typedBackendFact
+ , typedBackendFactReference
+ , typedBackendFactProposition
+ , typedBackendFactCapability
+ , LocalPremiseOrdinal
+ , localPremiseOrdinal
+ , localPremiseOrdinalValue
+ , TypedLocalPremise
+ , typedLocalPremise
+ , typedLocalPremiseOrdinal
+ , typedLocalPremiseOrigin
+ , typedLocalPremiseProposition
+ , typedLocalPremiseCapability
+ , TypedFoundationAuxiliaryInput
+ , typedFoundationAuxiliaryInput
+ , TypedProblemAuxiliary
+ , typedProblemAuxiliaryOrdinal
+ , typedProblemAuxiliaryTag
+ , typedProblemAuxiliaryProposition
+ , typedProblemAuxiliaryCapability
+ , LocalPremisePolicy(..)
+ , HigherOrderJustificationPolicy(..)
+ , selectTypedLocalPremises
+ , TypedProblemRoute(..)
+ , TypedProblem
+ , planTypedProblem
+ , typedProblemRoute
+ , typedProblemClaim
+ , typedProblemGlobalPremises
+ , typedProblemLocalPremises
+ , typedProblemAuxiliaries
+ , typedProblemGlobalTypes
+ , typedProblemLocalTypes
+ , TypedProblemError(..)
+ ) where
+
+import Base
+import Felix.Checking.Core
+import Felix.Checking.Foundation
+
+import Control.Monad (foldM, unless)
+import Data.Bifunctor (first)
+import Data.List qualified as List
+import Data.Map.Strict qualified as Map
+import Data.Set qualified as Set
+import Data.Vector (Vector)
+import Data.Vector qualified as Vector
+import Numeric.Natural (Natural)
+
+
+-- | A proposition under its exact nearest-first ambient-local support.
+data SupportedProposition local global =
+ SupportedProposition
+ !(Vector (local, CoreType))
+ !(ScopedCheckedCore global)
+ deriving stock (Eq)
+
+data SupportedPropositionError local
+ = SupportedPropositionIsNotProposition !CoreType
+ | SupportedPropositionContextMismatch
+ ![CoreType]
+ ![CoreType]
+ | DuplicateSupportedLocal !local
+ | UnusedSupportedLocal !local
+ deriving stock (Show, Eq)
+
+data SupportedPropositionProjectionError local
+ = SupportedProjectionContextMismatch
+ ![CoreType]
+ ![CoreType]
+ | SupportedProjectionDuplicateLocal !local
+ | SupportedProjectionIndexMissing !Natural
+ | SupportedProjectionCoreCheckFailed !CoreCheckError
+ | SupportedProjectionValidationFailed
+ !(SupportedPropositionError local)
+ deriving stock (Show, Eq)
+
+supportedProposition
+ :: Ord local
+ => Vector (local, CoreType)
+ -> ScopedCheckedCore global
+ -> Either
+ (SupportedPropositionError local)
+ (SupportedProposition local global)
+supportedProposition support statement = do
+ unless
+ (scopedCoreType statement == TyProp)
+ (Left
+ (SupportedPropositionIsNotProposition
+ (scopedCoreType statement)))
+ let expectedContext =
+ snd <$> Vector.toList support
+ actualContext =
+ scopedCoreContext statement
+ unless
+ (actualContext == expectedContext)
+ (Left
+ (SupportedPropositionContextMismatch
+ expectedContext
+ actualContext))
+ void
+ (foldM
+ (\seen (local, _coreType) ->
+ if local `Set.member` seen
+ then
+ Left
+ (DuplicateSupportedLocal local)
+ else
+ Right (Set.insert local seen))
+ Set.empty
+ support)
+ case
+ List.find
+ (\(ordinal, _entry) ->
+ fromIntegral ordinal
+ `Set.notMember`
+ ambientIndices
+ (scopedCoreTerm statement))
+ (Vector.toList
+ (Vector.indexed support)) of
+ Just (_ordinal, (local, _coreType)) ->
+ Left (UnusedSupportedLocal local)
+ Nothing ->
+ pure ()
+ pure
+ (SupportedProposition
+ support
+ statement)
+
+-- | Retain exactly the ambient locals used by a checked proposition and
+-- remap its indices to that dense nearest-first support.
+projectSupportedProposition
+ :: Ord local
+ => (global -> Maybe CoreType)
+ -> Vector (local, CoreType)
+ -> ScopedCheckedCore global
+ -> Either
+ (SupportedPropositionProjectionError local)
+ (SupportedProposition local global)
+projectSupportedProposition globalType available statement = do
+ let expectedContext = snd <$> Vector.toList available
+ actualContext = scopedCoreContext statement
+ unless (expectedContext == actualContext)
+ (Left
+ (SupportedProjectionContextMismatch
+ expectedContext
+ actualContext))
+ void
+ (foldM
+ (\seen (local, _coreType) ->
+ if local `Set.member` seen
+ then Left (SupportedProjectionDuplicateLocal local)
+ else Right (Set.insert local seen))
+ Set.empty
+ available)
+ let used =
+ Set.toAscList
+ (ambientIndices
+ (scopedCoreTerm statement))
+ selected <- traverse (lookupNatural available) used
+ let remapping =
+ Map.fromAscList
+ (zip used [0 ..])
+ remapped <- remapAmbientIndices remapping 0
+ (scopedCoreTerm statement)
+ checked <-
+ first SupportedProjectionCoreCheckFailed
+ (checkScopedCanonicalCore
+ globalType
+ (snd <$> selected)
+ remapped)
+ first SupportedProjectionValidationFailed
+ (supportedProposition
+ (Vector.fromList selected)
+ checked)
+ where
+ lookupNatural values index =
+ maybe
+ (Left (SupportedProjectionIndexMissing index))
+ Right
+ (go index (Vector.toList values))
+
+ go _index [] =
+ Nothing
+ go 0 (value : _rest) =
+ Just value
+ go index (_value : rest) =
+ go (index - 1) rest
+
+ remapAmbientIndices remapping depth = \case
+ CBound index
+ | index < depth ->
+ Right (CBound index)
+ | otherwise ->
+ maybe
+ (Left
+ (SupportedProjectionIndexMissing
+ (index - depth)))
+ (Right . CBound . (+ depth))
+ (Map.lookup (index - depth) remapping)
+ CGlobal global ->
+ Right (CGlobal global)
+ CIntrinsic intrinsic ->
+ Right (CIntrinsic intrinsic)
+ COpaqueInteger integer ->
+ Right (COpaqueInteger integer)
+ CApp function argument ->
+ CApp
+ <$> remapAmbientIndices remapping depth function
+ <*> remapAmbientIndices remapping depth argument
+ CLam binderType body ->
+ CLam binderType
+ <$> remapAmbientIndices remapping (depth + 1) body
+ CFalsum ->
+ Right CFalsum
+ CImp premise conclusion ->
+ CImp
+ <$> remapAmbientIndices remapping depth premise
+ <*> remapAmbientIndices remapping depth conclusion
+ CEq operandType left right ->
+ CEq operandType
+ <$> remapAmbientIndices remapping depth left
+ <*> remapAmbientIndices remapping depth right
+ CForall binderType body ->
+ CForall binderType
+ <$> remapAmbientIndices remapping (depth + 1) body
+
+ambientIndices
+ :: CanonicalTerm global
+ -> Set Natural
+ambientIndices =
+ go 0
+ where
+ go depth = \case
+ CBound index
+ | index < depth ->
+ mempty
+ | otherwise ->
+ Set.singleton (index - depth)
+ CGlobal{} ->
+ mempty
+ CIntrinsic{} ->
+ mempty
+ COpaqueInteger{} ->
+ mempty
+ CApp function argument ->
+ go depth function <> go depth argument
+ CLam _binderType body ->
+ go (depth + 1) body
+ CFalsum ->
+ mempty
+ CImp premise conclusion ->
+ go depth premise <> go depth conclusion
+ CEq _operandType left right ->
+ go depth left <> go depth right
+ CForall _binderType body ->
+ go (depth + 1) body
+
+supportedPropositionSupport
+ :: SupportedProposition local global
+ -> Vector (local, CoreType)
+supportedPropositionSupport
+ (SupportedProposition support _statement) =
+ support
+
+supportedPropositionTerm
+ :: SupportedProposition local global
+ -> CanonicalTerm global
+supportedPropositionTerm
+ (SupportedProposition _support statement) =
+ scopedCoreTerm statement
+
+weakenClosedSupportedProposition
+ :: SupportedProposition Void global
+ -> SupportedProposition local global
+weakenClosedSupportedProposition
+ (SupportedProposition support statement) =
+ SupportedProposition
+ (fmap
+ (\(local, coreType) ->
+ (absurd local, coreType))
+ support)
+ statement
+
+
+newtype CheckedFofProjection local global =
+ CheckedFofProjection
+ (SupportedProposition local global)
+ deriving stock (Eq)
+
+checkedFofProjectionProposition
+ :: CheckedFofProjection local global
+ -> SupportedProposition local global
+checkedFofProjectionProposition
+ (CheckedFofProjection proposition) =
+ proposition
+
+data FofCapability projection
+ = FofProjectable !projection
+ | RequiresTh0 !(NonEmpty BackendFofExclusion)
+ deriving stock (Eq)
+
+data BackendFofExclusion
+ = StructuralFofExclusion !FofExclusion
+ | HigherOrderGlobalType !CoreType
+ | HigherOrderAmbientLocal !CoreType
+ deriving stock (Show, Eq, Ord)
+
+data BackendClassificationError global
+ = UnknownBackendGlobal !global
+ | BackendFofProjectionInvariantFailed
+ deriving stock (Show, Eq)
+
+classifySupportedProposition
+ :: Ord global
+ => (global -> Maybe CoreType)
+ -> SupportedProposition local global
+ -> Either
+ (BackendClassificationError global)
+ (FofCapability
+ (CheckedFofProjection local global))
+classifySupportedProposition globalType proposition = do
+ globalExclusions <-
+ foldM
+ collectGlobal
+ Set.empty
+ (Set.toAscList
+ (canonicalGlobals
+ (supportedPropositionTerm proposition)))
+ let structuralExclusions =
+ case classifyScopedStructure proposition of
+ FoundationFofProjectable ->
+ Set.empty
+ FoundationRequiresTh0 structural ->
+ Set.fromList
+ (StructuralFofExclusion
+ <$> toList structural)
+ localExclusions =
+ Set.fromList
+ [ HigherOrderAmbientLocal coreType
+ | (_local, coreType) <-
+ Vector.toList
+ (supportedPropositionSupport
+ proposition)
+ , coreType /= TySet
+ ]
+ exclusions =
+ structuralExclusions
+ <> globalExclusions
+ <> localExclusions
+ case Set.toAscList exclusions of
+ [] ->
+ if isFirstOrderProposition
+ globalType
+ proposition
+ then
+ Right
+ (FofProjectable
+ (CheckedFofProjection
+ proposition))
+ else
+ Left BackendFofProjectionInvariantFailed
+ firstExclusion : remainingExclusions ->
+ Right
+ (RequiresTh0
+ (firstExclusion
+ :| remainingExclusions))
+ where
+ collectGlobal exclusions global =
+ case globalType global of
+ Nothing ->
+ Left (UnknownBackendGlobal global)
+ Just coreType ->
+ Right
+ (if isFirstOrderGlobalType coreType
+ then exclusions
+ else
+ Set.insert
+ (HigherOrderGlobalType
+ coreType)
+ exclusions)
+
+classifyScopedStructure
+ :: SupportedProposition local global
+ -> FoundationBackendClass
+classifyScopedStructure =
+ classifyCanonicalFofStructure
+ . supportedPropositionTerm
+
+isFirstOrderGlobalType :: CoreType -> Bool
+isFirstOrderGlobalType =
+ go
+ where
+ go = \case
+ TySet ->
+ True
+ TyProp ->
+ True
+ TyArrow TySet result ->
+ go result
+ TyArrow _argument _result ->
+ False
+
+-- The structural and type exclusions make this projection total. This final
+-- walk catches an accidentally unsaturated first-order head.
+isFirstOrderProposition
+ :: (global -> Maybe CoreType)
+ -> SupportedProposition local global
+ -> Bool
+isFirstOrderProposition globalType proposition =
+ isFormula initialContext
+ (supportedPropositionTerm proposition)
+ where
+ initialContext =
+ snd
+ <$> Vector.toList
+ (supportedPropositionSupport
+ proposition)
+
+ isFormula context = \case
+ CFalsum ->
+ True
+ CImp premise conclusion ->
+ isFormula context premise
+ && isFormula context conclusion
+ CEq TySet left right ->
+ isTerm context left
+ && isTerm context right
+ CEq TyProp left right ->
+ isFormula context left
+ && isFormula context right
+ CForall TySet body ->
+ isFormula (TySet : context) body
+ application ->
+ case applicationHead application of
+ (CGlobal global, arguments) ->
+ maybe
+ False
+ (\coreType ->
+ applicationResult
+ coreType
+ arguments
+ == Just TyProp
+ && all
+ (isTerm context)
+ arguments)
+ (globalType global)
+ (CIntrinsic intrinsic, arguments) ->
+ applicationResult
+ (coreIntrinsicType intrinsic)
+ arguments
+ == Just TyProp
+ && all
+ (isTerm context)
+ arguments
+ _ ->
+ False
+
+ isTerm context = \case
+ CBound index ->
+ contextAt index context
+ == Just TySet
+ CGlobal global ->
+ globalType global == Just TySet
+ CIntrinsic intrinsic ->
+ coreIntrinsicType intrinsic == TySet
+ COpaqueInteger{} ->
+ True
+ application ->
+ case applicationHead application of
+ (CGlobal global, arguments) ->
+ maybe
+ False
+ (\coreType ->
+ applicationResult
+ coreType
+ arguments
+ == Just TySet
+ && all
+ (isTerm context)
+ arguments)
+ (globalType global)
+ (CIntrinsic intrinsic, arguments) ->
+ applicationResult
+ (coreIntrinsicType intrinsic)
+ arguments
+ == Just TySet
+ && all
+ (isTerm context)
+ arguments
+ _ ->
+ False
+
+applicationHead
+ :: CanonicalTerm global
+ -> (CanonicalTerm global, [CanonicalTerm global])
+applicationHead =
+ go []
+ where
+ go arguments = \case
+ CApp function argument ->
+ go (argument : arguments) function
+ headTerm ->
+ (headTerm, arguments)
+
+applicationResult
+ :: CoreType
+ -> [CanonicalTerm global]
+ -> Maybe CoreType
+applicationResult =
+ foldM
+ (\coreType _argument ->
+ case coreType of
+ TyArrow TySet result ->
+ Just result
+ _ ->
+ Nothing)
+
+contextAt :: Natural -> [value] -> Maybe value
+contextAt _index [] =
+ Nothing
+contextAt 0 (value : _remaining) =
+ Just value
+contextAt index (_value : remaining) =
+ contextAt (index - 1) remaining
+
+canonicalGlobals
+ :: Ord global
+ => CanonicalTerm global
+ -> Set global
+canonicalGlobals = \case
+ CBound{} ->
+ mempty
+ CGlobal global ->
+ Set.singleton global
+ CIntrinsic{} ->
+ mempty
+ COpaqueInteger{} ->
+ mempty
+ CApp function argument ->
+ canonicalGlobals function
+ <> canonicalGlobals argument
+ CLam _binderType body ->
+ canonicalGlobals body
+ CFalsum ->
+ mempty
+ CImp premise conclusion ->
+ canonicalGlobals premise
+ <> canonicalGlobals conclusion
+ CEq _operandType left right ->
+ canonicalGlobals left
+ <> canonicalGlobals right
+ CForall _binderType body ->
+ canonicalGlobals body
+
+
+data TypedBackendFact ref global =
+ TypedBackendFact
+ !ref
+ !(SupportedProposition Void global)
+ !(FofCapability
+ (CheckedFofProjection Void global))
+ deriving stock (Eq)
+
+typedBackendFact
+ :: ref
+ -> SupportedProposition Void global
+ -> FofCapability
+ (CheckedFofProjection Void global)
+ -> TypedBackendFact ref global
+typedBackendFact =
+ TypedBackendFact
+
+typedBackendFactReference
+ :: TypedBackendFact ref global
+ -> ref
+typedBackendFactReference
+ (TypedBackendFact
+ reference
+ _proposition
+ _capability) =
+ reference
+
+typedBackendFactProposition
+ :: TypedBackendFact ref global
+ -> SupportedProposition Void global
+typedBackendFactProposition
+ (TypedBackendFact
+ _reference
+ proposition
+ _capability) =
+ proposition
+
+typedBackendFactCapability
+ :: TypedBackendFact ref global
+ -> FofCapability
+ (CheckedFofProjection Void global)
+typedBackendFactCapability
+ (TypedBackendFact
+ _reference
+ _proposition
+ capability) =
+ capability
+
+
+newtype LocalPremiseOrdinal =
+ LocalPremiseOrdinal Natural
+ deriving stock (Show, Eq, Ord)
+
+localPremiseOrdinal :: Natural -> LocalPremiseOrdinal
+localPremiseOrdinal =
+ LocalPremiseOrdinal
+
+localPremiseOrdinalValue
+ :: LocalPremiseOrdinal
+ -> Natural
+localPremiseOrdinalValue
+ (LocalPremiseOrdinal ordinal) =
+ ordinal
+
+data TypedLocalPremise local origin global =
+ TypedLocalPremise
+ !LocalPremiseOrdinal
+ !origin
+ !(SupportedProposition local global)
+ !(FofCapability
+ (CheckedFofProjection local global))
+ deriving stock (Eq)
+
+typedLocalPremise
+ :: Ord global
+ => (global -> Maybe CoreType)
+ -> LocalPremiseOrdinal
+ -> origin
+ -> SupportedProposition local global
+ -> Either
+ (BackendClassificationError global)
+ (TypedLocalPremise local origin global)
+typedLocalPremise globalType ordinal premiseOrigin proposition =
+ TypedLocalPremise
+ ordinal
+ premiseOrigin
+ proposition
+ <$> classifySupportedProposition
+ globalType
+ proposition
+
+typedLocalPremiseOrdinal
+ :: TypedLocalPremise local origin global
+ -> LocalPremiseOrdinal
+typedLocalPremiseOrdinal
+ (TypedLocalPremise
+ ordinal
+ _origin
+ _proposition
+ _capability) =
+ ordinal
+
+typedLocalPremiseOrigin
+ :: TypedLocalPremise local origin global
+ -> origin
+typedLocalPremiseOrigin
+ (TypedLocalPremise
+ _ordinal
+ premiseOrigin
+ _proposition
+ _capability) =
+ premiseOrigin
+
+typedLocalPremiseProposition
+ :: TypedLocalPremise local origin global
+ -> SupportedProposition local global
+typedLocalPremiseProposition
+ (TypedLocalPremise
+ _ordinal
+ _origin
+ proposition
+ _capability) =
+ proposition
+
+typedLocalPremiseCapability
+ :: TypedLocalPremise local origin global
+ -> FofCapability
+ (CheckedFofProjection local global)
+typedLocalPremiseCapability
+ (TypedLocalPremise
+ _ordinal
+ _origin
+ _proposition
+ capability) =
+ capability
+
+
+data TypedFoundationAuxiliaryInput global =
+ TypedFoundationAuxiliaryInput
+ !FoundationAxiomTag
+ !(SupportedProposition Void global)
+ !(FofCapability
+ (CheckedFofProjection Void global))
+
+typedFoundationAuxiliaryInput
+ :: CheckedFoundation
+ -> FoundationAxiomTag
+ -> TypedFoundationAuxiliaryInput global
+typedFoundationAuxiliaryInput foundation tag =
+ TypedFoundationAuxiliaryInput
+ tag
+ proposition
+ capability
+ where
+ proposition =
+ SupportedProposition
+ Vector.empty
+ (embedClosedCore
+ []
+ (mapFrozenGlobals
+ absurd
+ (foundationAxiomFrozen
+ foundation
+ tag)))
+ capability =
+ case foundationAxiomBackendClass
+ foundation
+ tag of
+ FoundationFofProjectable ->
+ FofProjectable
+ (CheckedFofProjection
+ proposition)
+ FoundationRequiresTh0 exclusions ->
+ RequiresTh0
+ (StructuralFofExclusion
+ <$> exclusions)
+
+data TypedProblemAuxiliary global =
+ TypedProblemAuxiliary
+ !Natural
+ !FoundationAxiomTag
+ !(SupportedProposition Void global)
+ !(FofCapability
+ (CheckedFofProjection Void global))
+ deriving stock (Eq)
+
+typedProblemAuxiliaryOrdinal
+ :: TypedProblemAuxiliary global
+ -> Natural
+typedProblemAuxiliaryOrdinal
+ (TypedProblemAuxiliary
+ ordinal
+ _tag
+ _proposition
+ _capability) =
+ ordinal
+
+typedProblemAuxiliaryTag
+ :: TypedProblemAuxiliary global
+ -> FoundationAxiomTag
+typedProblemAuxiliaryTag
+ (TypedProblemAuxiliary
+ _ordinal
+ tag
+ _proposition
+ _capability) =
+ tag
+
+typedProblemAuxiliaryProposition
+ :: TypedProblemAuxiliary global
+ -> SupportedProposition Void global
+typedProblemAuxiliaryProposition
+ (TypedProblemAuxiliary
+ _ordinal
+ _tag
+ proposition
+ _capability) =
+ proposition
+
+typedProblemAuxiliaryCapability
+ :: TypedProblemAuxiliary global
+ -> FofCapability
+ (CheckedFofProjection Void global)
+typedProblemAuxiliaryCapability
+ (TypedProblemAuxiliary
+ _ordinal
+ _tag
+ _proposition
+ capability) =
+ capability
+
+
+-- | Source justification policy for premise selection. Higher-order routing
+-- is validated separately after the complete selected problem is known.
+data LocalPremisePolicy
+ = FirstOrderLocals
+ | CompleteLocals
+ deriving stock (Show, Eq)
+
+-- | Whether selected higher-order components must be justified by one of the
+-- two approved inline construction forms. Premise selection has already
+-- happened when this policy is applied.
+data HigherOrderJustificationPolicy
+ = ImplicitConstructionJustification
+ | ExplicitHigherOrderJustification
+ deriving stock (Show, Eq)
+
+selectTypedLocalPremises
+ :: LocalPremisePolicy
+ -> [TypedLocalPremise local origin global]
+ -> Vector (TypedLocalPremise local origin global)
+selectTypedLocalPremises selection availableLocals =
+ Vector.fromList
+ (List.sortOn
+ typedLocalPremiseOrdinal
+ (case selection of
+ FirstOrderLocals ->
+ List.filter
+ (isFofCapability
+ . typedLocalPremiseCapability)
+ availableLocals
+ CompleteLocals ->
+ availableLocals))
+
+data ImplicitHigherOrderConstruction
+ = ImplicitSeparation
+ | ImplicitFunctionalReplacement
+ deriving stock (Show, Eq, Ord)
+
+data TypedProblemRoute
+ = RouteFof
+ | RouteTh0
+ deriving stock (Show, Eq)
+
+data TypedProblem ref local origin global =
+ TypedProblem
+ !TypedProblemRoute
+ !(SupportedProposition local global)
+ !(Vector (TypedBackendFact ref global))
+ !(Vector (TypedLocalPremise local origin global))
+ !(Vector (TypedProblemAuxiliary global))
+ !(Map global CoreType)
+ !(Map local CoreType)
+ deriving stock (Eq)
+
+data TypedProblemError local global
+ = TypedProblemClaimClassificationFailed
+ !(BackendClassificationError global)
+ | TypedProblemExplicitHigherOrderJustificationRequired
+ !(NonEmpty BackendFofExclusion)
+ | TypedProblemDuplicateLocalPremiseOrdinal
+ !LocalPremiseOrdinal
+ | TypedProblemLocalTypeMismatch
+ !local
+ !CoreType
+ !CoreType
+ deriving stock (Show, Eq)
+
+planTypedProblem
+ :: (Ord local, Ord global)
+ => (global -> Maybe CoreType)
+ -> Vector (TypedBackendFact ref global)
+ -> SupportedProposition local global
+ -> [TypedLocalPremise local origin global]
+ -> [TypedFoundationAuxiliaryInput global]
+ -> LocalPremisePolicy
+ -> HigherOrderJustificationPolicy
+ -> Either
+ (TypedProblemError local global)
+ (TypedProblem ref local origin global)
+planTypedProblem
+ globalType
+ selectedFacts
+ claim
+ availableLocals
+ auxiliaries
+ localPolicy
+ higherOrderPolicy = do
+ validateLocalPremiseOrdinals
+ availableLocals
+ claimCapability <-
+ first
+ TypedProblemClaimClassificationFailed
+ (classifySupportedProposition
+ globalType
+ claim)
+ let selectedLocals =
+ selectTypedLocalPremises
+ localPolicy
+ availableLocals
+ let preparedAuxiliaries =
+ zipWith
+ prepareAuxiliary
+ [0..]
+ auxiliaries
+ case higherOrderPolicy of
+ ImplicitConstructionJustification ->
+ validateImplicitHigherOrderAdmission
+ claim
+ claimCapability
+ selectedFacts
+ selectedLocals
+ preparedAuxiliaries
+ ExplicitHigherOrderJustification ->
+ pure ()
+ let selectedFofCapabilities =
+ isFofCapability claimCapability
+ : (isFofCapability
+ . typedBackendFactCapability
+ <$> Vector.toList selectedFacts)
+ <> (isFofCapability
+ . typedLocalPremiseCapability
+ <$> Vector.toList selectedLocals)
+ <> (isFofCapability
+ . typedProblemAuxiliaryCapability
+ <$> preparedAuxiliaries)
+ route =
+ if and selectedFofCapabilities
+ then RouteFof
+ else RouteTh0
+ globalTypes <-
+ collectProblemGlobals
+ globalType
+ claim
+ selectedFacts
+ selectedLocals
+ preparedAuxiliaries
+ localTypes <-
+ collectProblemLocals
+ claim
+ selectedLocals
+ pure
+ (TypedProblem
+ route
+ claim
+ selectedFacts
+ selectedLocals
+ (Vector.fromList preparedAuxiliaries)
+ globalTypes
+ localTypes)
+ where
+ prepareAuxiliary
+ ordinal
+ (TypedFoundationAuxiliaryInput
+ tag
+ proposition
+ capability) =
+ TypedProblemAuxiliary
+ ordinal
+ tag
+ proposition
+ capability
+
+-- | Implicit automation admits higher-order routing only for a checked
+-- proposition that itself contains one of the two approved set constructions.
+-- This classification selects no premise and grants no authority.
+implicitConstructionAdmission
+ :: SupportedProposition local global
+ -> FofCapability projection
+ -> Maybe (Set ImplicitHigherOrderConstruction)
+implicitConstructionAdmission proposition capability =
+ case capability of
+ FofProjectable{} ->
+ Nothing
+ RequiresTh0 exclusions
+ | Set.null constructions ->
+ Nothing
+ | all (admittedExclusion constructions) exclusions ->
+ Just constructions
+ | otherwise ->
+ Nothing
+ where
+ dependencies =
+ foundationAxiomDependencies
+ (supportedPropositionTerm proposition)
+ constructions =
+ Set.fromList
+ ( [ ImplicitSeparation
+ | SeparationCharacteristic `Set.member` dependencies
+ ]
+ <> [ ImplicitFunctionalReplacement
+ | ReplacementCharacteristic `Set.member` dependencies
+ ]
+ )
+
+ admittedExclusion allowed = \case
+ StructuralFofExclusion HigherOrderLambda ->
+ True
+ StructuralFofExclusion (HigherOrderIntrinsic Sep) ->
+ ImplicitSeparation `Set.member` allowed
+ StructuralFofExclusion (HigherOrderIntrinsic Repl) ->
+ ImplicitFunctionalReplacement `Set.member` allowed
+ -- The checked proposition is the deliberate granularity: its typed
+ -- global occurrences neither select another fact nor grant authority.
+ HigherOrderGlobalType{} ->
+ True
+ StructuralFofExclusion{} ->
+ False
+ HigherOrderAmbientLocal{} ->
+ False
+
+validateImplicitHigherOrderAdmission
+ :: SupportedProposition local global
+ -> FofCapability claimProjection
+ -> Vector (TypedBackendFact ref global)
+ -> Vector (TypedLocalPremise local origin global)
+ -> [TypedProblemAuxiliary global]
+ -> Either (TypedProblemError local global) ()
+validateImplicitHigherOrderAdmission
+ claim claimCapability selectedFacts selectedLocals auxiliaries = do
+ claimConstructions <-
+ admittedPropositionConstructions claim claimCapability
+ traverse_ requireFirstOrderGlobal selectedFacts
+ localConstructions <-
+ foldM
+ (\admitted premise ->
+ (admitted <>)
+ <$> admittedPropositionConstructions
+ (typedLocalPremiseProposition premise)
+ (typedLocalPremiseCapability premise))
+ Set.empty
+ (Vector.toList selectedLocals)
+ let admitted = claimConstructions <> localConstructions
+ traverse_ (requireAdmittedAuxiliary admitted) auxiliaries
+ where
+ admittedPropositionConstructions proposition = \case
+ FofProjectable{} ->
+ Right Set.empty
+ RequiresTh0 exclusions ->
+ maybe
+ (Left
+ (TypedProblemExplicitHigherOrderJustificationRequired
+ exclusions))
+ Right
+ (implicitConstructionAdmission
+ proposition
+ (RequiresTh0 exclusions))
+
+ requireFirstOrderGlobal fact =
+ case typedBackendFactCapability fact of
+ FofProjectable{} ->
+ Right ()
+ RequiresTh0 exclusions ->
+ Left
+ (TypedProblemExplicitHigherOrderJustificationRequired
+ exclusions)
+
+ requireAdmittedAuxiliary admitted auxiliary =
+ case typedProblemAuxiliaryCapability auxiliary of
+ FofProjectable{} ->
+ Right ()
+ RequiresTh0 exclusions
+ | auxiliaryAdmitted admitted
+ (typedProblemAuxiliaryTag auxiliary) ->
+ Right ()
+ | otherwise ->
+ Left
+ (TypedProblemExplicitHigherOrderJustificationRequired
+ exclusions)
+
+ auxiliaryAdmitted admitted = \case
+ SeparationCharacteristic ->
+ ImplicitSeparation `Set.member` admitted
+ ReplacementCharacteristic ->
+ ImplicitFunctionalReplacement `Set.member` admitted
+ _ ->
+ False
+
+validateLocalPremiseOrdinals
+ :: [TypedLocalPremise local origin global]
+ -> Either
+ (TypedProblemError local global)
+ ()
+validateLocalPremiseOrdinals =
+ void
+ . foldM
+ (\seen premise ->
+ let ordinal =
+ typedLocalPremiseOrdinal premise
+ in
+ if ordinal `Set.member` seen
+ then
+ Left
+ (TypedProblemDuplicateLocalPremiseOrdinal
+ ordinal)
+ else
+ Right
+ (Set.insert
+ ordinal
+ seen))
+ Set.empty
+
+isFofCapability :: FofCapability projection -> Bool
+isFofCapability = \case
+ FofProjectable{} ->
+ True
+ RequiresTh0{} ->
+ False
+
+collectProblemGlobals
+ :: Ord global
+ => (global -> Maybe CoreType)
+ -> SupportedProposition local global
+ -> Vector (TypedBackendFact ref global)
+ -> Vector (TypedLocalPremise local origin global)
+ -> [TypedProblemAuxiliary global]
+ -> Either
+ (TypedProblemError local global)
+ (Map global CoreType)
+collectProblemGlobals
+ globalType
+ claim
+ facts
+ locals
+ auxiliaries =
+ Map.fromAscList
+ <$> traverse
+ resolveGlobal
+ (Set.toAscList globals)
+ where
+ globals =
+ canonicalGlobals
+ (supportedPropositionTerm claim)
+ <> foldMap
+ (canonicalGlobals
+ . supportedPropositionTerm
+ . typedBackendFactProposition)
+ facts
+ <> foldMap
+ (canonicalGlobals
+ . supportedPropositionTerm
+ . typedLocalPremiseProposition)
+ locals
+ <> foldMap
+ (canonicalGlobals
+ . supportedPropositionTerm
+ . typedProblemAuxiliaryProposition)
+ auxiliaries
+
+ resolveGlobal global =
+ case globalType global of
+ Nothing ->
+ Left
+ (TypedProblemClaimClassificationFailed
+ (UnknownBackendGlobal global))
+ Just coreType ->
+ Right (global, coreType)
+
+collectProblemLocals
+ :: Ord local
+ => SupportedProposition local global
+ -> Vector (TypedLocalPremise local origin global)
+ -> Either
+ (TypedProblemError local global)
+ (Map local CoreType)
+collectProblemLocals claim locals =
+ foldM
+ insertSupport
+ Map.empty
+ supports
+ where
+ supports =
+ Vector.toList
+ (supportedPropositionSupport claim)
+ <> concatMap
+ (Vector.toList
+ . supportedPropositionSupport
+ . typedLocalPremiseProposition)
+ (Vector.toList locals)
+
+ insertSupport current (local, coreType) =
+ case Map.lookup local current of
+ Nothing ->
+ Right
+ (Map.insert
+ local
+ coreType
+ current)
+ Just previousType
+ | previousType == coreType ->
+ Right current
+ | otherwise ->
+ Left
+ (TypedProblemLocalTypeMismatch
+ local
+ previousType
+ coreType)
+
+typedProblemRoute
+ :: TypedProblem ref local origin global
+ -> TypedProblemRoute
+typedProblemRoute
+ (TypedProblem
+ route
+ _claim
+ _facts
+ _locals
+ _auxiliaries
+ _globals
+ _localTypes) =
+ route
+
+typedProblemClaim
+ :: TypedProblem ref local origin global
+ -> SupportedProposition local global
+typedProblemClaim
+ (TypedProblem
+ _route
+ claim
+ _facts
+ _locals
+ _auxiliaries
+ _globals
+ _localTypes) =
+ claim
+
+typedProblemGlobalPremises
+ :: TypedProblem ref local origin global
+ -> Vector (TypedBackendFact ref global)
+typedProblemGlobalPremises
+ (TypedProblem
+ _route
+ _claim
+ facts
+ _locals
+ _auxiliaries
+ _globals
+ _localTypes) =
+ facts
+
+typedProblemLocalPremises
+ :: TypedProblem ref local origin global
+ -> Vector (TypedLocalPremise local origin global)
+typedProblemLocalPremises
+ (TypedProblem
+ _route
+ _claim
+ _facts
+ locals
+ _auxiliaries
+ _globals
+ _localTypes) =
+ locals
+
+typedProblemAuxiliaries
+ :: TypedProblem ref local origin global
+ -> Vector (TypedProblemAuxiliary global)
+typedProblemAuxiliaries
+ (TypedProblem
+ _route
+ _claim
+ _facts
+ _locals
+ auxiliaries
+ _globals
+ _localTypes) =
+ auxiliaries
+
+typedProblemGlobalTypes
+ :: TypedProblem ref local origin global
+ -> Map global CoreType
+typedProblemGlobalTypes
+ (TypedProblem
+ _route
+ _claim
+ _facts
+ _locals
+ _auxiliaries
+ globals
+ _localTypes) =
+ globals
+
+typedProblemLocalTypes
+ :: TypedProblem ref local origin global
+ -> Map local CoreType
+typedProblemLocalTypes
+ (TypedProblem
+ _route
+ _claim
+ _facts
+ _locals
+ _auxiliaries
+ _globals
+ localTypes) =
+ localTypes
diff --git a/source/Felix/Checking/Backend/Tptp.hs b/source/Felix/Checking/Backend/Tptp.hs
new file mode 100644
index 0000000..a5c0546
--- /dev/null
+++ b/source/Felix/Checking/Backend/Tptp.hs
@@ -0,0 +1,1281 @@
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+-- | Deterministic task-wide TPTP preparation for checked typed problems.
+module Felix.Checking.Backend.Tptp
+ ( TypedFormulaOccurrence(..)
+ , TypedTptpNameOrigin(..)
+ , PreparedTypedTptpProblem
+ , prepareTypedTptpProblem
+ , preparedTypedTptpRoute
+ , preparedTypedTptpText
+ , preparedTypedTptpTextNewline
+ , preparedTypedTptpConjectureText
+ , preparedTypedTptpNameOrigins
+ , TypedTptpPreparationError(..)
+ ) where
+
+import Base hiding (Empty)
+import Felix.Checking.Backend.Problem
+import Felix.Checking.Core
+import Tptp.UnsortedFirstOrder qualified as Tptp
+
+import Control.Monad (foldM)
+import Control.Monad.State.Strict (StateT)
+import Control.Monad.State.Strict qualified as State
+import Control.Monad.Trans.Class (lift)
+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 Numeric.Natural (Natural)
+import TextBuilder
+
+
+data TypedFormulaOccurrence ref
+ = TypedGlobalPremiseOccurrence !ref
+ | TypedLocalPremiseOccurrence !LocalPremiseOrdinal
+ | TypedAuxiliaryOccurrence !Natural
+ | TypedConjectureOccurrence
+ deriving stock (Show, Eq, Ord)
+
+data TypedTptpNameOrigin ref local global
+ = TypedGlobalNameOrigin !global
+ | TypedLocalNameOrigin !local
+ | TypedIntrinsicNameOrigin !CoreIntrinsicTag
+ | TypedIntegerNameOrigin !Integer
+ | TypedBinderNameOrigin !Natural
+ | TypedFormulaNameOrigin !(TypedFormulaOccurrence ref)
+ deriving stock (Show, Eq, Ord)
+
+data PreparedTypedTptpProblem ref local global =
+ PreparedTypedTptpProblem
+ !TypedProblemRoute
+ !Text
+ !Text
+ !(Map
+ Text
+ (TypedTptpNameOrigin ref local global))
+ deriving stock (Eq)
+
+preparedTypedTptpRoute
+ :: PreparedTypedTptpProblem ref local global
+ -> TypedProblemRoute
+preparedTypedTptpRoute
+ (PreparedTypedTptpProblem
+ route
+ _text
+ _conjecture
+ _origins) =
+ route
+
+preparedTypedTptpText
+ :: PreparedTypedTptpProblem ref local global
+ -> Text
+preparedTypedTptpText
+ (PreparedTypedTptpProblem
+ _route
+ problemText
+ _conjecture
+ _origins) =
+ problemText
+
+preparedTypedTptpTextNewline
+ :: PreparedTypedTptpProblem ref local global
+ -> Text
+preparedTypedTptpTextNewline =
+ (`Text.snoc` '\n')
+ . preparedTypedTptpText
+
+preparedTypedTptpConjectureText
+ :: PreparedTypedTptpProblem ref local global
+ -> Text
+preparedTypedTptpConjectureText
+ (PreparedTypedTptpProblem
+ _route
+ _text
+ conjecture
+ _origins) =
+ conjecture
+
+preparedTypedTptpNameOrigins
+ :: PreparedTypedTptpProblem ref local global
+ -> Map
+ Text
+ (TypedTptpNameOrigin ref local global)
+preparedTypedTptpNameOrigins
+ (PreparedTypedTptpProblem
+ _route
+ _text
+ _conjecture
+ origins) =
+ origins
+
+data TypedTptpPreparationError local global
+ = InvalidGeneratedTypedTptpName !Text
+ | DuplicateGeneratedTypedTptpName !Text
+ | TypedTptpUnknownGlobal !global
+ | TypedTptpUnknownLocal !local
+ | TypedTptpUnboundIndex !Natural
+ | TypedTptpFofProjectionMismatch
+ deriving stock (Show, Eq)
+
+
+data NameEnvironment ref local global =
+ NameEnvironment
+ !(Map global Tptp.AtomicWord)
+ !(Map global CoreType)
+ !(Map local Tptp.AtomicWord)
+ !(Map CoreIntrinsicTag Tptp.AtomicWord)
+ !(Map Integer Tptp.AtomicWord)
+ !(Map
+ Text
+ (TypedTptpNameOrigin ref local global))
+
+data RenderState ref local global =
+ RenderState
+ !Natural
+ !Natural
+ !(Map
+ Text
+ (TypedTptpNameOrigin ref local global))
+
+type Render ref local global =
+ StateT
+ (RenderState ref local global)
+ (Either
+ (TypedTptpPreparationError local global))
+
+data RenderedFormula ref = RenderedFormula
+ !Tptp.AtomicWord
+ !(TypedFormulaOccurrence ref)
+ !TextBuilder
+
+data BoundTarget
+ = BoundFofVariable !Tptp.Variable
+ | BoundTh0Variable !Tptp.Variable
+ | AmbientConstant !Tptp.AtomicWord
+
+prepareTypedTptpProblem
+ :: (Ord local, Ord global)
+ => TypedProblem ref local origin global
+ -> Either
+ (TypedTptpPreparationError local global)
+ (PreparedTypedTptpProblem ref local global)
+prepareTypedTptpProblem problem = do
+ names <-
+ allocateNames problem
+ let initialState =
+ RenderState
+ 0
+ 0
+ (nameEnvironmentOrigins names)
+ (rendered, finalState) <-
+ State.runStateT
+ (renderProblem names problem)
+ initialState
+ let (problemBuilder, conjectureBuilder) =
+ rendered
+ RenderState _nextBinder _nextHypothesis origins =
+ finalState
+ pure
+ (PreparedTypedTptpProblem
+ (typedProblemRoute problem)
+ (TextBuilder.toText problemBuilder)
+ (TextBuilder.toText conjectureBuilder)
+ origins)
+
+allocateNames
+ :: (Ord local, Ord global)
+ => TypedProblem ref local origin global
+ -> Either
+ (TypedTptpPreparationError local global)
+ (NameEnvironment ref local global)
+allocateNames problem = do
+ globalAllocations <-
+ allocateCategory
+ "tg_g"
+ TypedGlobalNameOrigin
+ (Map.keys
+ (typedProblemGlobalTypes
+ problem))
+ localAllocations <-
+ allocateCategory
+ "tg_l"
+ TypedLocalNameOrigin
+ (Map.keys
+ (typedProblemLocalTypes
+ problem))
+ intrinsicAllocations <-
+ allocateCategory
+ "tg_i"
+ TypedIntrinsicNameOrigin
+ (Set.toAscList
+ (problemIntrinsics problem))
+ integerAllocations <-
+ allocateCategory
+ "tg_n"
+ TypedIntegerNameOrigin
+ (Set.toAscList
+ (problemIntegers problem))
+ origins <-
+ foldM
+ (\current (target, nameOrigin) ->
+ insertOrigin
+ (Tptp.atomicWordText target)
+ nameOrigin
+ current)
+ Map.empty
+ ( [ (target, nameOrigin)
+ | (_global, target, nameOrigin) <-
+ globalAllocations
+ ]
+ <> [ (target, nameOrigin)
+ | (_local, target, nameOrigin) <-
+ localAllocations
+ ]
+ <> [ (target, nameOrigin)
+ | (_intrinsic, target, nameOrigin) <-
+ intrinsicAllocations
+ ]
+ <> [ (target, nameOrigin)
+ | (_integer, target, nameOrigin) <-
+ integerAllocations
+ ]
+ )
+ pure
+ (NameEnvironment
+ (Map.fromList
+ [ (global, target)
+ | (global, target, _nameOrigin) <-
+ globalAllocations
+ ])
+ (typedProblemGlobalTypes problem)
+ (Map.fromList
+ [ (local, target)
+ | (local, target, _nameOrigin) <-
+ localAllocations
+ ])
+ (Map.fromList
+ [ (intrinsic, target)
+ | (intrinsic, target, _nameOrigin) <-
+ intrinsicAllocations
+ ])
+ (Map.fromList
+ [ (integer, target)
+ | (integer, target, _nameOrigin) <-
+ integerAllocations
+ ])
+ origins)
+ where
+ allocateCategory prefix makeOrigin semantics =
+ traverse
+ (\(ordinal, semantic) -> do
+ target <-
+ generatedAtomicWord
+ (prefix
+ <> Text.pack
+ (show ordinal))
+ pure
+ ( semantic
+ , target
+ , makeOrigin semantic
+ ))
+ (zip [0 :: Int ..] semantics)
+
+nameEnvironmentOrigins
+ :: NameEnvironment ref local global
+ -> Map
+ Text
+ (TypedTptpNameOrigin ref local global)
+nameEnvironmentOrigins
+ (NameEnvironment
+ _globals
+ _globalTypes
+ _locals
+ _intrinsics
+ _integers
+ origins) =
+ origins
+
+generatedAtomicWord
+ :: Text
+ -> Either
+ (TypedTptpPreparationError local global)
+ Tptp.AtomicWord
+generatedAtomicWord target =
+ maybe
+ (Left
+ (InvalidGeneratedTypedTptpName
+ target))
+ Right
+ (Tptp.atomicWord target)
+
+generatedVariable
+ :: Text
+ -> Either
+ (TypedTptpPreparationError local global)
+ Tptp.Variable
+generatedVariable target =
+ maybe
+ (Left
+ (InvalidGeneratedTypedTptpName
+ target))
+ Right
+ (Tptp.variable target)
+
+insertOrigin
+ :: Text
+ -> TypedTptpNameOrigin ref local global
+ -> Map
+ Text
+ (TypedTptpNameOrigin ref local global)
+ -> Either
+ (TypedTptpPreparationError local global)
+ (Map
+ Text
+ (TypedTptpNameOrigin ref local global))
+insertOrigin target nameOrigin origins =
+ if Map.member target origins
+ then
+ Left
+ (DuplicateGeneratedTypedTptpName
+ target)
+ else
+ Right
+ (Map.insert
+ target
+ nameOrigin
+ origins)
+
+renderProblem
+ :: (Ord local, Ord global)
+ => NameEnvironment ref local global
+ -> TypedProblem ref local origin global
+ -> Render
+ ref
+ local
+ global
+ (TextBuilder, TextBuilder)
+renderProblem names problem = do
+ hypotheses <-
+ renderHypotheses names problem
+ conjecture <-
+ renderConjecture names problem
+ declarations <-
+ case typedProblemRoute problem of
+ RouteFof ->
+ pure []
+ RouteTh0 ->
+ renderTh0Declarations
+ names
+ problem
+ let formulaBuilders =
+ renderFormulaLine
+ (typedProblemRoute problem)
+ "axiom"
+ <$> hypotheses
+ conjectureBuilder =
+ renderFormulaLine
+ (typedProblemRoute problem)
+ "conjecture"
+ conjecture
+ complete =
+ intercalate
+ (char '\n')
+ (declarations
+ <> formulaBuilders
+ <> [conjectureBuilder])
+ pure
+ ( complete
+ , conjectureBuilder
+ )
+
+renderHypotheses
+ :: (Ord local, Ord global)
+ => NameEnvironment ref local global
+ -> TypedProblem ref local origin global
+ -> Render
+ ref
+ local
+ global
+ [RenderedFormula ref]
+renderHypotheses names problem = do
+ globalFormulas <-
+ traverse
+ (\fact ->
+ renderOccurrence
+ names
+ problem
+ (TypedGlobalPremiseOccurrence
+ (typedBackendFactReference
+ fact))
+ (weakenClosedSupportedProposition
+ (typedBackendFactProposition
+ fact)))
+ (Vector.toList
+ (typedProblemGlobalPremises
+ problem))
+ localFormulas <-
+ traverse
+ (\premise ->
+ renderOccurrence
+ names
+ problem
+ (TypedLocalPremiseOccurrence
+ (typedLocalPremiseOrdinal
+ premise))
+ (typedLocalPremiseProposition
+ premise))
+ (Vector.toList
+ (typedProblemLocalPremises
+ problem))
+ auxiliaryFormulas <-
+ traverse
+ (\auxiliary ->
+ renderOccurrence
+ names
+ problem
+ (TypedAuxiliaryOccurrence
+ (typedProblemAuxiliaryOrdinal
+ auxiliary))
+ (weakenClosedSupportedProposition
+ (typedProblemAuxiliaryProposition
+ auxiliary)))
+ (Vector.toList
+ (typedProblemAuxiliaries
+ problem))
+ pure
+ (globalFormulas
+ <> localFormulas
+ <> auxiliaryFormulas)
+
+renderConjecture
+ :: (Ord local, Ord global)
+ => NameEnvironment ref local global
+ -> TypedProblem ref local origin global
+ -> Render
+ ref
+ local
+ global
+ (RenderedFormula ref)
+renderConjecture names problem =
+ renderOccurrence
+ names
+ problem
+ TypedConjectureOccurrence
+ (typedProblemClaim problem)
+
+renderOccurrence
+ :: (Ord local, Ord global)
+ => NameEnvironment ref local global
+ -> TypedProblem ref local origin global
+ -> TypedFormulaOccurrence ref
+ -> SupportedProposition local global
+ -> Render
+ ref
+ local
+ global
+ (RenderedFormula ref)
+renderOccurrence names problem occurrence proposition = do
+ target <-
+ case occurrence of
+ TypedConjectureOccurrence ->
+ liftEither
+ (generatedAtomicWord "tg_q0")
+ _ -> do
+ ordinal <-
+ nextHypothesisOrdinal
+ liftEither
+ (generatedAtomicWord
+ ("tg_h"
+ <> Text.pack
+ (show ordinal)))
+ registerOrigin
+ (Tptp.atomicWordText target)
+ (TypedFormulaNameOrigin occurrence)
+ bounds <-
+ initialBounds
+ names
+ proposition
+ formula <-
+ case typedProblemRoute problem of
+ RouteFof ->
+ renderFofFormula
+ names
+ bounds
+ (supportedPropositionTerm
+ proposition)
+ RouteTh0 ->
+ renderTh0Term
+ names
+ bounds
+ (supportedPropositionTerm
+ proposition)
+ pure
+ (RenderedFormula
+ target
+ occurrence
+ formula)
+
+-- Formula and binder ordinals use separate dense namespaces.
+nextHypothesisOrdinal
+ :: Render ref local global Natural
+nextHypothesisOrdinal = do
+ RenderState nextBinder nextHypothesis origins <-
+ State.get
+ State.put
+ (RenderState
+ nextBinder
+ (nextHypothesis + 1)
+ origins)
+ pure nextHypothesis
+
+registerOrigin
+ :: Text
+ -> TypedTptpNameOrigin ref local global
+ -> Render ref local global ()
+registerOrigin target nameOrigin = do
+ RenderState nextBinder nextHypothesis origins <-
+ State.get
+ origins' <-
+ liftEither
+ (insertOrigin
+ target
+ nameOrigin
+ origins)
+ State.put
+ (RenderState
+ nextBinder
+ nextHypothesis
+ origins')
+
+freshBinder
+ :: Render ref local global Tptp.Variable
+freshBinder = do
+ RenderState nextBinder nextHypothesis origins <-
+ State.get
+ let target =
+ "V" <> Text.pack (show nextBinder)
+ variable <-
+ liftEither
+ (generatedVariable target)
+ origins' <-
+ liftEither
+ (insertOrigin
+ target
+ (TypedBinderNameOrigin
+ nextBinder)
+ origins)
+ State.put
+ (RenderState
+ (nextBinder + 1)
+ nextHypothesis
+ origins')
+ pure variable
+
+liftEither
+ :: Either
+ (TypedTptpPreparationError local global)
+ value
+ -> Render ref local global value
+liftEither =
+ lift
+
+initialBounds
+ :: Ord local
+ => NameEnvironment ref local global
+ -> SupportedProposition local global
+ -> Render ref local global [BoundTarget]
+initialBounds
+ (NameEnvironment
+ _globals
+ _globalTypes
+ localNames
+ _intrinsics
+ _integers
+ _origins)
+ proposition =
+ traverse
+ (\(local, _coreType) ->
+ maybe
+ (lift
+ (Left
+ (TypedTptpUnknownLocal
+ local)))
+ (pure . AmbientConstant)
+ (Map.lookup
+ local
+ localNames))
+ (Vector.toList
+ (supportedPropositionSupport
+ proposition))
+
+renderFormulaLine
+ :: TypedProblemRoute
+ -> TextBuilder
+ -> RenderedFormula ref
+ -> TextBuilder
+renderFormulaLine route role
+ (RenderedFormula target _occurrence formula) =
+ dialect
+ <> char '('
+ <> Tptp.buildAtomicWord target
+ <> char ','
+ <> role
+ <> char ','
+ <> formula
+ <> text ")."
+ where
+ dialect =
+ case route of
+ RouteFof ->
+ text "fof"
+ RouteTh0 ->
+ text "thf"
+
+
+renderFofFormula
+ :: (Ord global)
+ => NameEnvironment ref local global
+ -> [BoundTarget]
+ -> CanonicalTerm global
+ -> Render ref local global TextBuilder
+renderFofFormula names bounds = \case
+ CFalsum ->
+ pure (text "$false")
+ CImp premise conclusion -> do
+ premise' <-
+ renderFofFormula names bounds premise
+ conclusion' <-
+ renderFofFormula names bounds conclusion
+ pure
+ (parenthesize
+ (premise'
+ <> text "=>"
+ <> conclusion'))
+ CEq TySet left right -> do
+ left' <-
+ renderFofTerm names bounds left
+ right' <-
+ renderFofTerm names bounds right
+ pure
+ (parenthesize
+ (left'
+ <> char '='
+ <> right'))
+ CEq TyProp left right -> do
+ left' <-
+ renderFofFormula names bounds left
+ right' <-
+ renderFofFormula names bounds right
+ pure
+ (parenthesize
+ (left'
+ <> text "<=>"
+ <> right'))
+ CForall TySet body -> do
+ variable <-
+ freshBinder
+ body' <-
+ renderFofFormula
+ names
+ (BoundFofVariable variable
+ : bounds)
+ body
+ pure
+ (parenthesize
+ (text "!["
+ <> Tptp.buildVariable variable
+ <> text "]:"
+ <> body'))
+ application ->
+ renderFofApplication
+ names
+ bounds
+ TyProp
+ application
+
+renderFofTerm
+ :: Ord global
+ => NameEnvironment ref local global
+ -> [BoundTarget]
+ -> CanonicalTerm global
+ -> Render ref local global TextBuilder
+renderFofTerm names bounds = \case
+ CBound index ->
+ renderBound index bounds
+ CGlobal global ->
+ Tptp.buildAtomicWord
+ <$> lookupGlobal names global
+ CIntrinsic intrinsic ->
+ Tptp.buildAtomicWord
+ <$> lookupIntrinsic names intrinsic
+ COpaqueInteger integer ->
+ Tptp.buildAtomicWord
+ <$> lookupInteger names integer
+ application ->
+ renderFofApplication
+ names
+ bounds
+ TySet
+ application
+
+renderFofApplication
+ :: Ord global
+ => NameEnvironment ref local global
+ -> [BoundTarget]
+ -> CoreType
+ -> CanonicalTerm global
+ -> Render ref local global TextBuilder
+renderFofApplication names bounds expected application =
+ case applicationHead application of
+ (CGlobal global, arguments) -> do
+ coreType <-
+ maybe
+ (lift
+ (Left
+ (TypedTptpUnknownGlobal
+ global)))
+ pure
+ (Map.lookup
+ global
+ (nameEnvironmentGlobalTypes
+ names))
+ renderHead
+ coreType
+ (lookupGlobal names global)
+ arguments
+ (CIntrinsic intrinsic, arguments) ->
+ renderHead
+ (coreIntrinsicType intrinsic)
+ (lookupIntrinsic names intrinsic)
+ arguments
+ _ ->
+ lift
+ (Left
+ TypedTptpFofProjectionMismatch)
+ where
+ renderHead coreType targetAction arguments = do
+ unlessFofApplication
+ expected
+ coreType
+ arguments
+ target <-
+ targetAction
+ arguments' <-
+ traverse
+ (renderFofTerm names bounds)
+ arguments
+ pure
+ (applyAtomicWord
+ target
+ arguments')
+
+-- Global types are retained in the problem, but names need only the allocated
+-- symbols. FOF saturation was already checked by the projection witness.
+nameEnvironmentGlobalTypes
+ :: NameEnvironment ref local global
+ -> Map global CoreType
+nameEnvironmentGlobalTypes
+ (NameEnvironment
+ _globals
+ globalTypes
+ _locals
+ _intrinsics
+ _integers
+ _origins) =
+ globalTypes
+
+unlessFofApplication
+ :: CoreType
+ -> CoreType
+ -> [CanonicalTerm global]
+ -> Render ref local global ()
+unlessFofApplication expected coreType arguments =
+ case consume coreType arguments of
+ Just result
+ | result == expected ->
+ pure ()
+ _ ->
+ lift
+ (Left
+ TypedTptpFofProjectionMismatch)
+ where
+ consume current = \case
+ [] ->
+ Just current
+ _argument : remaining ->
+ case current of
+ TyArrow TySet result ->
+ consume result remaining
+ _ ->
+ Nothing
+
+applyAtomicWord
+ :: Tptp.AtomicWord
+ -> [TextBuilder]
+ -> TextBuilder
+applyAtomicWord target = \case
+ [] ->
+ Tptp.buildAtomicWord target
+ arguments ->
+ Tptp.buildAtomicWord target
+ <> Tptp.buildTuple arguments
+
+renderBound
+ :: Natural
+ -> [BoundTarget]
+ -> Render ref local global TextBuilder
+renderBound index bounds =
+ case contextAt index bounds of
+ Nothing ->
+ lift
+ (Left
+ (TypedTptpUnboundIndex
+ index))
+ Just (BoundFofVariable variable) ->
+ pure
+ (Tptp.buildVariable
+ variable)
+ Just (BoundTh0Variable variable) ->
+ pure
+ (Tptp.buildVariable
+ variable)
+ Just (AmbientConstant target) ->
+ pure
+ (Tptp.buildAtomicWord
+ target)
+
+
+renderTh0Term
+ :: Ord global
+ => NameEnvironment ref local global
+ -> [BoundTarget]
+ -> CanonicalTerm global
+ -> Render ref local global TextBuilder
+renderTh0Term names bounds = \case
+ CBound index ->
+ renderBound index bounds
+ CGlobal global ->
+ Tptp.buildAtomicWord
+ <$> lookupGlobal names global
+ CIntrinsic intrinsic ->
+ Tptp.buildAtomicWord
+ <$> lookupIntrinsic names intrinsic
+ COpaqueInteger integer ->
+ Tptp.buildAtomicWord
+ <$> lookupInteger names integer
+ CApp function argument -> do
+ function' <-
+ renderTh0Term names bounds function
+ argument' <-
+ renderTh0Term names bounds argument
+ pure
+ (parenthesize
+ (function'
+ <> char '@'
+ <> argument'))
+ CLam binderType body -> do
+ variable <-
+ freshBinder
+ body' <-
+ renderTh0Term
+ names
+ (BoundTh0Variable variable
+ : bounds)
+ body
+ pure
+ (parenthesize
+ (text "^ ["
+ <> Tptp.buildVariable variable
+ <> char ':'
+ <> renderCoreType binderType
+ <> text "] : "
+ <> body'))
+ CFalsum ->
+ pure (text "$false")
+ CImp premise conclusion -> do
+ premise' <-
+ renderTh0Term names bounds premise
+ conclusion' <-
+ renderTh0Term names bounds conclusion
+ pure
+ (parenthesize
+ (premise'
+ <> text "=>"
+ <> conclusion'))
+ CEq operandType left right -> do
+ left' <-
+ renderTh0Term names bounds left
+ right' <-
+ renderTh0Term names bounds right
+ pure
+ (parenthesize
+ (left'
+ <> (case operandType of
+ TyProp -> text "<=>"
+ _ -> char '=')
+ <> right'))
+ CForall binderType body -> do
+ variable <-
+ freshBinder
+ body' <-
+ renderTh0Term
+ names
+ (BoundTh0Variable variable
+ : bounds)
+ body
+ pure
+ (parenthesize
+ (text "! ["
+ <> Tptp.buildVariable variable
+ <> char ':'
+ <> renderCoreType binderType
+ <> text "] : "
+ <> body'))
+
+renderTh0Declarations
+ :: (Ord local, Ord global)
+ => NameEnvironment ref local global
+ -> TypedProblem ref local origin global
+ -> Render ref local global [TextBuilder]
+renderTh0Declarations names problem = do
+ globalDeclarations <-
+ traverse
+ (\(ordinal, (global, coreType)) -> do
+ target <-
+ lookupGlobal names global
+ label <-
+ liftEither
+ (generatedAtomicWord
+ ("tg_g_type_"
+ <> Text.pack
+ (show ordinal)))
+ pure
+ (typeDeclaration
+ label
+ target
+ (renderCoreType coreType)))
+ (zip [0 :: Int ..]
+ (Map.toAscList
+ (typedProblemGlobalTypes
+ problem)))
+ localDeclarations <-
+ traverse
+ (\(ordinal, (local, coreType)) -> do
+ target <-
+ lookupLocal names local
+ label <-
+ liftEither
+ (generatedAtomicWord
+ ("tg_l_type_"
+ <> Text.pack
+ (show ordinal)))
+ pure
+ (typeDeclaration
+ label
+ target
+ (renderCoreType coreType)))
+ (zip [0 :: Int ..]
+ (Map.toAscList
+ (typedProblemLocalTypes
+ problem)))
+ intrinsicDeclarations <-
+ traverse
+ (\(ordinal, intrinsic) -> do
+ target <-
+ lookupIntrinsic names intrinsic
+ label <-
+ liftEither
+ (generatedAtomicWord
+ ("tg_i_type_"
+ <> Text.pack
+ (show ordinal)))
+ pure
+ (typeDeclaration
+ label
+ target
+ (renderCoreType
+ (coreIntrinsicType
+ intrinsic))))
+ (zip [0 :: Int ..]
+ (Set.toAscList
+ (problemIntrinsics problem)))
+ integerDeclarations <-
+ traverse
+ (\(ordinal, integer) -> do
+ target <-
+ lookupInteger names integer
+ label <-
+ liftEither
+ (generatedAtomicWord
+ ("tg_n_type_"
+ <> Text.pack
+ (show ordinal)))
+ pure
+ (typeDeclaration
+ label
+ target
+ (renderCoreType TySet)))
+ (zip [0 :: Int ..]
+ (Set.toAscList
+ (problemIntegers problem)))
+ pure
+ (globalDeclarations
+ <> localDeclarations
+ <> intrinsicDeclarations
+ <> integerDeclarations)
+
+typeDeclaration
+ :: Tptp.AtomicWord
+ -> Tptp.AtomicWord
+ -> TextBuilder
+ -> TextBuilder
+typeDeclaration label target coreType =
+ text "thf("
+ <> Tptp.buildAtomicWord label
+ <> text ",type,("
+ <> Tptp.buildAtomicWord target
+ <> char ':'
+ <> coreType
+ <> text "))."
+
+renderCoreType :: CoreType -> TextBuilder
+renderCoreType = \case
+ TyProp ->
+ text "$o"
+ TySet ->
+ text "$i"
+ TyArrow argument result ->
+ parenthesize
+ (renderCoreType argument
+ <> char '>'
+ <> renderCoreType result)
+
+parenthesize :: TextBuilder -> TextBuilder
+parenthesize builder =
+ char '(' <> builder <> char ')'
+
+
+lookupGlobal
+ :: Ord global
+ => NameEnvironment ref local global
+ -> global
+ -> Render ref local global Tptp.AtomicWord
+lookupGlobal names global =
+ maybe
+ (lift
+ (Left
+ (TypedTptpUnknownGlobal
+ global)))
+ pure
+ (lookupGlobalPure names global)
+
+lookupGlobalPure
+ :: Ord global
+ => NameEnvironment ref local global
+ -> global
+ -> Maybe Tptp.AtomicWord
+lookupGlobalPure
+ (NameEnvironment
+ globals
+ _globalTypes
+ _locals
+ _intrinsics
+ _integers
+ _origins) =
+ (`Map.lookup` globals)
+
+lookupLocalPure
+ :: Ord local
+ => NameEnvironment ref local global
+ -> local
+ -> Maybe Tptp.AtomicWord
+lookupLocalPure
+ (NameEnvironment
+ _globals
+ _globalTypes
+ locals
+ _intrinsics
+ _integers
+ _origins) =
+ (`Map.lookup` locals)
+
+lookupLocal
+ :: Ord local
+ => NameEnvironment ref local global
+ -> local
+ -> Render ref local global Tptp.AtomicWord
+lookupLocal names local =
+ maybe
+ (lift
+ (Left
+ (TypedTptpUnknownLocal
+ local)))
+ pure
+ (lookupLocalPure names local)
+
+lookupIntrinsic
+ :: NameEnvironment ref local global
+ -> CoreIntrinsicTag
+ -> Render ref local global Tptp.AtomicWord
+lookupIntrinsic names intrinsic =
+ maybe
+ (lift
+ (Left
+ TypedTptpFofProjectionMismatch))
+ pure
+ (lookupIntrinsicPure names intrinsic)
+
+lookupIntrinsicPure
+ :: NameEnvironment ref local global
+ -> CoreIntrinsicTag
+ -> Maybe Tptp.AtomicWord
+lookupIntrinsicPure
+ (NameEnvironment
+ _globals
+ _globalTypes
+ _locals
+ intrinsics
+ _integers
+ _origins) =
+ (`Map.lookup` intrinsics)
+
+lookupInteger
+ :: NameEnvironment ref local global
+ -> Integer
+ -> Render ref local global Tptp.AtomicWord
+lookupInteger names integer =
+ maybe
+ (lift
+ (Left
+ TypedTptpFofProjectionMismatch))
+ pure
+ (lookupIntegerPure names integer)
+
+lookupIntegerPure
+ :: NameEnvironment ref local global
+ -> Integer
+ -> Maybe Tptp.AtomicWord
+lookupIntegerPure
+ (NameEnvironment
+ _globals
+ _globalTypes
+ _locals
+ _intrinsics
+ integers
+ _origins) =
+ (`Map.lookup` integers)
+
+problemIntrinsics
+ :: TypedProblem ref local origin global
+ -> Set CoreIntrinsicTag
+problemIntrinsics =
+ foldMap canonicalIntrinsics
+ . problemTerms
+
+problemIntegers
+ :: TypedProblem ref local origin global
+ -> Set Integer
+problemIntegers =
+ foldMap canonicalIntegers
+ . problemTerms
+
+problemTerms
+ :: TypedProblem ref local origin global
+ -> [CanonicalTerm global]
+problemTerms problem =
+ supportedPropositionTerm
+ (typedProblemClaim problem)
+ : (supportedPropositionTerm
+ . typedBackendFactProposition
+ <$> Vector.toList
+ (typedProblemGlobalPremises
+ problem))
+ <> (supportedPropositionTerm
+ . typedLocalPremiseProposition
+ <$> Vector.toList
+ (typedProblemLocalPremises
+ problem))
+ <> (supportedPropositionTerm
+ . typedProblemAuxiliaryProposition
+ <$> Vector.toList
+ (typedProblemAuxiliaries
+ problem))
+
+canonicalIntrinsics
+ :: CanonicalTerm global
+ -> Set CoreIntrinsicTag
+canonicalIntrinsics = \case
+ CBound{} ->
+ mempty
+ CGlobal{} ->
+ mempty
+ CIntrinsic intrinsic ->
+ Set.singleton intrinsic
+ COpaqueInteger{} ->
+ mempty
+ CApp function argument ->
+ canonicalIntrinsics function
+ <> canonicalIntrinsics argument
+ CLam _binderType body ->
+ canonicalIntrinsics body
+ CFalsum ->
+ mempty
+ CImp premise conclusion ->
+ canonicalIntrinsics premise
+ <> canonicalIntrinsics conclusion
+ CEq _operandType left right ->
+ canonicalIntrinsics left
+ <> canonicalIntrinsics right
+ CForall _binderType body ->
+ canonicalIntrinsics body
+
+canonicalIntegers
+ :: CanonicalTerm global
+ -> Set Integer
+canonicalIntegers = \case
+ CBound{} ->
+ mempty
+ CGlobal{} ->
+ mempty
+ CIntrinsic{} ->
+ mempty
+ COpaqueInteger integer ->
+ Set.singleton integer
+ CApp function argument ->
+ canonicalIntegers function
+ <> canonicalIntegers argument
+ CLam _binderType body ->
+ canonicalIntegers body
+ CFalsum ->
+ mempty
+ CImp premise conclusion ->
+ canonicalIntegers premise
+ <> canonicalIntegers conclusion
+ CEq _operandType left right ->
+ canonicalIntegers left
+ <> canonicalIntegers right
+ CForall _binderType body ->
+ canonicalIntegers body
+
+applicationHead
+ :: CanonicalTerm global
+ -> (CanonicalTerm global, [CanonicalTerm global])
+applicationHead =
+ go []
+ where
+ go arguments = \case
+ CApp function argument ->
+ go (argument : arguments) function
+ headTerm ->
+ (headTerm, arguments)
+
+contextAt :: Natural -> [value] -> Maybe value
+contextAt _index [] =
+ Nothing
+contextAt 0 (value : _remaining) =
+ Just value
+contextAt index (_value : remaining) =
+ contextAt (index - 1) remaining