summaryrefslogtreecommitdiff
path: root/source/Meaning.hs
diff options
context:
space:
mode:
Diffstat (limited to 'source/Meaning.hs')
-rw-r--r--source/Meaning.hs1772
1 files changed, 0 insertions, 1772 deletions
diff --git a/source/Meaning.hs b/source/Meaning.hs
deleted file mode 100644
index 04979ce..0000000
--- a/source/Meaning.hs
+++ /dev/null
@@ -1,1772 +0,0 @@
-{-# LANGUAGE ApplicativeDo #-}
-{-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE MultiWayIf #-}
-{-# LANGUAGE TupleSections #-}
-
-
-module Meaning where
-
-
-import Base
-import Syntax.Abstract (Sign(..))
-import Syntax.Abstract qualified as Raw
-import Syntax.Internal (VarSymbol(..), pattern FreshVar)
-import Syntax.Internal qualified as Sem
-import Syntax.LexicalPhrase (unsafeReadPhrase)
-import Report.Location
-
-import Bound
-import Control.Monad.Except
-import Control.Monad.State
-import Data.List qualified as List
-import Data.List.NonEmpty qualified as NonEmpty
-import Data.Map qualified as Map
-import Data.Set qualified as Set
-import Control.Exception (Exception)
-
-
--- | The 'Gloss' monad. Basic elaboration, desugaring, and validation
--- computations take place in this monad, using 'ExceptT' to log
--- validation errors and 'State' to keep track of the surrounding context.
-type Gloss = ExceptT GlossError (State GlossState)
--- This monad previously used 'ValidationT' for validation so that multiple
--- validation errors could be reported. Using only 'ExceptT' we fail immediately
--- on the first error. If we ever swich back to 'ValidateT' for error reporting,
--- then we should re-enable {-# OPTIONS_GHC -foptimal-applicative-do #-},
--- as 'ValidateT' can report more errors when used with applicative combinators.
-
--- These types are a private bridge to the current VarSymbol-based core.
-newtype LocalId = LocalId Int
- deriving (Show, Eq, Ord)
-
-data BinderTrivia = BinderTrivia
- { binderDisplayHint :: Maybe Text
- , binderDeclarationLocation :: Location
- } deriving (Show, Eq, Ord)
-
-data ResolvedLocalRef
- = AmbientRef VarSymbol
- | LocalRef LocalId
- deriving (Show, Eq, Ord)
-
-data H0ResolvedBinder = H0ResolvedBinder
- { h0BinderId :: LocalId
- , h0BinderTrivia :: BinderTrivia
- } deriving (Show, Eq, Ord)
-
-data ResolvedBinderAdapterError
- = UnknownResolvedLocal LocalId
- | DuplicateResolvedLocalAssignment LocalId
- | ResolvedLocalTokenCollision LocalId VarSymbol
- deriving (Show, Eq, Ord)
-
--- | Errors that can be detected during glossing.
-data GlossError
- = GlossDefnError Location DefnError Sem.Marker
- | GlossInductionError Location
- | GlossRelationExprWithParams Location
- | GlossRelationApplicationError Sem.RelationApplicationError
- | GlossDatatypeHeadError Location
- | GlossDatatypeClauseTargetError Location
- | GlossDatatypeConstructorError Location
- | DependentReplacementDomainNotSupported Location
- | QuantifiedTermRequiresResolvedContext Location
- | IotaTermNotSupported Location
- | DefiniteFunctionAssumptionNotSupported Location
- | GlossProofFunctionArgumentMismatch
- Location
- VarSymbol
- VarSymbol
- | GlossProofFunctionNameMismatch
- Location
- VarSymbol
- VarSymbol
- | GlossAbbreviationError
- Location
- Sem.Marker
- AbbreviationParameterError
- | DuplicateQuantifiedNounBinder
- Location
- Location
- Text
- | GlossResolvedBinderAdapterError
- Location
- ResolvedBinderAdapterError
- deriving (Eq, Ord)
-
-data AbbreviationParameterError
- = DuplicateAbbreviationParameters (NonEmpty VarSymbol)
- | FreeAbbreviationBodyVariables (NonEmpty VarSymbol)
- deriving (Show, Eq, Ord)
-
-instance Exception GlossError
-instance Show GlossError where show = explainGlossError
-
-explainGlossError :: GlossError -> String
-explainGlossError = \case
- GlossDefnError loc defnError marker ->
- "Definition error at " <> prettyLocation loc <> " (in " <> show marker <> "): " <> case defnError of
- DefnWarnLhsFree xs ->
- "The variables " <> show xs <> " in the pattern being defined (definiendum) do not occur in the body of the definition (definiens). Remove them or use them in the body."
- DefnErrorLhsNotLinear ->
- "The left-hand side of the definition is not linear (a variable occurs multiple times)."
- DefnErrorLhsTypeFree ->
- "The defintion contains variables with no typing constraints or assumptions placed on them."
- DefnErrorRhsFree xs ->
- "The variables " <> show xs <> " on the right-hand side of the definition do not occurring on the left-hand side."
- DefnErrorQuantifiedRhsTerm ->
- "A quantified term cannot be the right-hand side of a functional definition."
- GlossInductionError loc ->
- "Error at " <> prettyLocation loc <> ": Induction over a non-variable is not supported."
- GlossRelationExprWithParams loc ->
- "Error at " <> prettyLocation loc <> ": A relation defined by an expression cannot have parameters."
- GlossRelationApplicationError
- (Sem.RelationParameterArityMismatch loc relation expected actual) ->
- "Relation "
- <> show (Sem.relationSymbolToken relation)
- <> " at "
- <> prettyLocation loc
- <> " expects "
- <> show (Sem.parameterArityValue expected)
- <> " parameter(s), but received "
- <> show (Sem.parameterArityValue actual)
- <> "."
- GlossDatatypeHeadError loc ->
- "Error at " <> prettyLocation loc <> ": A datatype head must be a constant symbolic term."
- GlossDatatypeClauseTargetError loc ->
- "Error at " <> prettyLocation loc <> ": Every datatype clause must target the datatype being defined."
- GlossDatatypeConstructorError loc ->
- "Error at " <> prettyLocation loc <> ": Datatype constructors must be symbolic terms with bare variable arguments."
- DependentReplacementDomainNotSupported loc ->
- "Error at "
- <> prettyLocation loc
- <> ": dependent replacement domains are not yet supported."
- QuantifiedTermRequiresResolvedContext loc ->
- "Error at "
- <> prettyLocation loc
- <> ": a quantified term requires a resolved binding context."
- IotaTermNotSupported loc ->
- "Error at "
- <> prettyLocation loc
- <> ": definite-description terms are not supported."
- DefiniteFunctionAssumptionNotSupported loc ->
- "Error at "
- <> prettyLocation loc
- <> ": definite-function assumptions are not supported."
- GlossProofFunctionArgumentMismatch loc valueArgument domainArgument ->
- "Function definition error at "
- <> prettyLocation loc
- <> ": value argument "
- <> show valueArgument
- <> " does not match domain argument "
- <> show domainArgument
- <> "."
- GlossProofFunctionNameMismatch loc declaredFunction definedFunction ->
- "Function definition error at "
- <> prettyLocation loc
- <> ": declared function "
- <> show declaredFunction
- <> " does not match defined function "
- <> show definedFunction
- <> "."
- GlossAbbreviationError loc marker abbreviationError ->
- "Abbreviation error at "
- <> prettyLocation loc
- <> " (in "
- <> show marker
- <> "): "
- <> case abbreviationError of
- DuplicateAbbreviationParameters variables ->
- "The parameters "
- <> show (NonEmpty.toList variables)
- <> " occur more than once."
- FreeAbbreviationBodyVariables variables ->
- "The body contains free variables not present in the head: "
- <> show (NonEmpty.toList variables)
- <> "."
- DuplicateQuantifiedNounBinder firstLocation secondLocation name ->
- "Quantified noun binder "
- <> show name
- <> " at "
- <> prettyLocation secondLocation
- <> " duplicates the overlapping binder at "
- <> prettyLocation firstLocation
- <> "."
- GlossResolvedBinderAdapterError location adapterError ->
- "Resolved binder adapter error at "
- <> prettyLocation location
- <> ": "
- <> case adapterError of
- UnknownResolvedLocal localId ->
- "unknown local reference " <> show localId <> "."
- DuplicateResolvedLocalAssignment localId ->
- "duplicate legacy assignment for " <> show localId <> "."
- ResolvedLocalTokenCollision localId token ->
- "legacy token "
- <> show token
- <> " for "
- <> show localId
- <> " is not fresh."
-
-liftRelationApplication
- :: Either Sem.RelationApplicationError a
- -> Gloss a
-liftRelationApplication =
- either (throwError . GlossRelationApplicationError) pure
-
--- | Specialization of 'traverse' to 'Gloss'.
-each :: (Traversable t) => (a -> Gloss b) -> t a -> Gloss (t b)
-explain `each` as = traverse explain as
-infix 7 `each` -- In particular, 'each' has precedence over '(<$>)'.
-
--- | Wellformedness check for definitions.
--- The following conditions need to be met.
---
--- * Variables occurring in the lexical phrases on the left side must be linear,
--- i.e. each variable can only occur once.
--- * The arguments of the lexical phrases must be variables, not complex terms.
--- This is statically guaranteed by the grammar.
--- * The optional typing noun may not have any free variables.
--- * The rhs side may not have any free variables not occurring on the lhs.
--- * If a variable on the lhs does not occur on the rhs, a warning should we issued.
---
-isWellformedDefn :: Sem.Defn -> Either DefnError Sem.Defn
-isWellformedDefn defn =
- if | ls' /= ls -> Left DefnErrorLhsNotLinear
- | not (null rdiff) -> Left (DefnErrorRhsFree (toList rdiff))
- | not (null ldiff) -> case defn of
- Sem.DefnPredicate{} -> Left (DefnWarnLhsFree (toList ldiff))
- _ -> Right defn
- | otherwise -> Right defn
- where
- ls = lhsVars defn
- ls' = nubOrd ls
- rs = rhsVars defn
- (ldiff, rdiff) = symmetricDifferenceDecompose (Set.fromList ls') rs
-
-
-lhsVars :: Sem.Defn -> [VarSymbol]
-lhsVars = \case
- Sem.DefnPredicate _ _ vs _ -> toList vs
- Sem.DefnFun _ _ vs _ -> vs
- Sem.DefnOp _ vs _ -> vs
-
-rhsVars :: Sem.Defn -> Set VarSymbol
-rhsVars = \case
- Sem.DefnPredicate _ _ _ f -> Sem.freeVars f
- Sem.DefnFun _ _ _ e -> Sem.freeVars e
- Sem.DefnOp _ _ e -> Sem.freeVars e
-
-
--- | Validation errors for top-level definitions.
-data DefnError
- = DefnWarnLhsFree [VarSymbol]
- | DefnErrorLhsNotLinear
- | DefnErrorLhsTypeFree
- | DefnErrorRhsFree [VarSymbol]
- | DefnErrorQuantifiedRhsTerm
- deriving (Show, Eq, Ord)
-
-
--- | Context for 'Gloss' computations.
-data GlossState = GlossState
- { varCount :: Int
- -- ^ Counter for generating variables names for the output.
- , localCount :: Int
- -- ^ Counter for resolved quantified-noun binders.
- , localBinderTrivia :: Map LocalId BinderTrivia
- , legacyLocalTokens :: Map LocalId VarSymbol
- } deriving (Show, Eq)
-
-freshVar :: Gloss VarSymbol
-freshVar = do
- i <- gets varCount
- modify $ \s -> s {varCount = varCount s + 1}
- pure $ FreshVar i
-
-type H0LexicalEnvironment = [H0ResolvedBinder]
-
-type H0Expr = Sem.ExprOf ResolvedLocalRef
-
-freshH0Binder
- :: Location
- -> Maybe VarSymbol
- -> Gloss H0ResolvedBinder
-freshH0Binder termLocation writtenName = do
- nextLocal <- gets localCount
- let localId = LocalId nextLocal
- trivia = BinderTrivia
- { binderDisplayHint = writtenName >>= displayedVariableName
- , binderDeclarationLocation =
- maybe termLocation locate writtenName
- }
- binder = H0ResolvedBinder localId trivia
- modify \glossState ->
- glossState
- { localCount = nextLocal + 1
- , localBinderTrivia =
- Map.insert localId trivia (localBinderTrivia glossState)
- }
- pure binder
- where
- displayedVariableName = \case
- NamedVarAt _ name -> Just name
- FreshVarAt{} -> Nothing
-
-pushH0Binder
- :: H0ResolvedBinder
- -> H0LexicalEnvironment
- -> H0LexicalEnvironment
-pushH0Binder = (:)
-
-resolveH0Reference
- :: H0LexicalEnvironment
- -> VarSymbol
- -> ResolvedLocalRef
-resolveH0Reference environment variable = case variable of
- NamedVarAt _ name ->
- maybe
- (AmbientRef variable)
- (LocalRef . h0BinderId)
- (List.find hasDisplayName environment)
- where
- hasDisplayName binder =
- binderDisplayHint (h0BinderTrivia binder) == Just name
- FreshVarAt{} ->
- AmbientRef variable
-
-resolveH0Expr
- :: H0LexicalEnvironment
- -> Sem.Expr
- -> H0Expr
-resolveH0Expr environment =
- fmap (resolveH0Reference environment)
-
-lowerH0Expr :: H0Expr -> Gloss Sem.Expr
-lowerH0Expr =
- traverse \case
- AmbientRef variable ->
- pure variable
- LocalRef localId -> do
- trivia <- gets (Map.lookup localId . localBinderTrivia)
- throwError
- (GlossResolvedBinderAdapterError
- (maybe Nowhere binderDeclarationLocation trivia)
- (UnknownResolvedLocal localId))
-
-abstractH0Binder
- :: H0ResolvedBinder
- -> H0Expr
- -> Gloss (Scope VarSymbol Sem.ExprOf ResolvedLocalRef)
-abstractH0Binder binder body = do
- token <- allocateLegacyLocalToken binder body
- pure
- (abstract
- (\case
- LocalRef localId
- | localId == h0BinderId binder ->
- Just token
- _ ->
- Nothing)
- body)
-
-allocateLegacyLocalToken
- :: H0ResolvedBinder
- -> H0Expr
- -> Gloss VarSymbol
-allocateLegacyLocalToken binder body = do
- assignments <- gets legacyLocalTokens
- case Map.lookup localId assignments of
- Just _ ->
- throwAdapterError
- (DuplicateResolvedLocalAssignment localId)
- Nothing -> do
- let ambientTokens =
- Set.fromList
- [ token
- | AmbientRef token <- toList body
- ]
- assignedTokens =
- Set.fromList (Map.elems assignments)
- forbiddenTokens =
- ambientTokens <> assignedTokens
- token <- freshTokenOutside forbiddenTokens
- if token `Set.member` forbiddenTokens
- then
- throwAdapterError
- (ResolvedLocalTokenCollision localId token)
- else do
- modify \glossState ->
- glossState
- { legacyLocalTokens =
- Map.insert
- localId
- token
- (legacyLocalTokens glossState)
- }
- pure token
- where
- localId = h0BinderId binder
- binderLocation =
- binderDeclarationLocation (h0BinderTrivia binder)
- throwAdapterError =
- throwError
- . GlossResolvedBinderAdapterError binderLocation
-
- freshTokenOutside forbidden = do
- candidate <- freshVar
- if candidate `Set.member` forbidden
- then freshTokenOutside forbidden
- else pure candidate
-
-initialGlossState :: GlossState
-initialGlossState = GlossState
- { varCount = 0
- , localCount = 0
- , localBinderTrivia = mempty
- , legacyLocalTokens = mempty
- }
-
-glossStep :: GlossState -> Raw.Block -> Either GlossError (Sem.Block, GlossState)
-glossStep glossState block = case runState (runExceptT (glossBlock block)) glossState of
- (Left err, _nextGlossState) -> Left err
- (Right glossedBlock, nextGlossState) -> Right (glossedBlock, nextGlossState)
-
-meaning :: [Raw.Block] -> Either GlossError [Sem.Block]
-meaning blocks = evalState (runExceptT (glossBlocks blocks)) initialGlossState
-
-glossExpr :: Raw.Expr -> Gloss (Sem.ExprOf VarSymbol)
-glossExpr = \case
- Raw.ExprVar v ->
- pure $ Sem.TermVar v
- Raw.ExprInteger loc n ->
- pure $ Sem.TermSymbol loc (Sem.SymbolInteger n) []
- Raw.ExprOp loc f es ->
- Sem.TermSymbol loc <$> pure (Sem.SymbolMixfix f) <*> (glossExpr `each` es)
- Raw.ExprStructOp _loc tok maybeLabel -> do
- maybeLabel' <- traverse glossExpr maybeLabel
- pure $ Sem.TermSymbolStruct tok maybeLabel'
- Raw.ExprSep _loc x t phi -> do
- t' <- glossExpr t
- phi' <- glossStmt phi
- pure (Sem.TermSep x t' (abstract1 x phi'))
- Raw.ExprReplacePred _loc y x xBound stmt -> do
- xBound' <- glossExpr xBound
- stmt' <- glossStmt stmt
- let toReplacementVar z = if
- | z == x -> Just Sem.ReplacementDomVar
- | z == y -> Just Sem.ReplacementRangeVar
- | otherwise -> Nothing
- let scope = abstract toReplacementVar stmt'
- pure (Sem.ReplacePred y x xBound' scope)
- Raw.ExprReplace _loc e bounds phi -> do
- e' <- glossExpr e
- bounds' <- glossReplaceBounds bounds
- let xs = fst <$> bounds'
- phi'' <- case phi of
- Just phi' -> glossStmt phi'
- Nothing -> pure Sem.Top
- let abstractBoundVars = abstract (\x -> List.find (== x) (toList xs))
- pure $ Sem.ReplaceFun bounds' (abstractBoundVars e') (abstractBoundVars phi'')
- where
- glossReplaceBounds
- :: NonEmpty (VarSymbol, Raw.Expr)
- -> Gloss (NonEmpty (VarSymbol, Sem.Term))
- glossReplaceBounds
- ((firstBinder, firstDomain) :| remainingBounds) = do
- firstDomain' <- glossExpr firstDomain
- remainingBounds' <-
- go (Set.singleton firstBinder) remainingBounds
- pure ((firstBinder, firstDomain') :| remainingBounds')
- where
- go
- :: Set VarSymbol
- -> [(VarSymbol, Raw.Expr)]
- -> Gloss [(VarSymbol, Sem.Term)]
- go _precedingBinders [] = pure []
- go precedingBinders ((binder, domain) : laterBounds) = do
- domain' <- glossExpr domain
- -- Folding a glossed domain visits only free occurrences.
- case List.find
- (`Set.member` precedingBinders)
- (toList domain') of
- Just occurrence ->
- throwError
- (DependentReplacementDomainNotSupported
- (locate occurrence))
- Nothing -> do
- laterBounds' <-
- go
- (Set.insert binder precedingBinders)
- laterBounds
- pure ((binder, domain') : laterBounds')
- Raw.ExprFiniteSet loc es -> do
- es' <- glossExpr `each` es
- pure (foldr cons (Sem.EmptySet loc) es')
- where
- cons x y = Sem.TermSymbol loc (Sem.SymbolMixfix Raw.ConsSymbol) [x, y]
-
-
-glossFormula :: Raw.Formula -> Gloss (Sem.ExprOf VarSymbol)
-glossFormula = \case
- Raw.FormulaChain ch ->
- glossChain ch
- Raw.Connected _loc conn phi psi ->
- glossConnective conn <*> glossFormula phi <*> glossFormula psi
- Raw.FormulaNeg loc f ->
- Sem.Not loc <$> glossFormula f
- Raw.FormulaPredicate loc predi _marker es ->
- Sem.Atomic loc <$> glossPrefixPredicate predi <*> glossExpr `each` toList es
- Raw.PropositionalConstant _loc c ->
- pure $ Sem.PropositionalConstant c
- Raw.FormulaQuantified _loc quantifier xs bound phi -> do
- bound' <- glossBound bound
- phi' <- glossFormula phi
- quantify <- glossQuantifier quantifier
- pure (quantify xs (bound' (toList xs)) phi')
-
-glossChain :: Sem.Chain -> Gloss (Sem.ExprOf VarSymbol)
-glossChain ch = Sem.makeConjunction <$> makeRels (conjuncts (splat ch))
- where
- -- | Separate each link of the chain into separate triples.
- splat :: Raw.Chain -> [(NonEmpty Raw.Expr, Sign, Raw.Relation, NonEmpty Raw.Expr)]
- splat = \case
- Raw.ChainBase es sign rel es'
- -> [(es, sign, rel, es')]
- Raw.ChainCons es sign rel ch'@(Raw.ChainBase es' _ _ _)
- -> (es, sign, rel, es') : splat ch'
- Raw.ChainCons es sign rel ch'@(Raw.ChainCons es' _ _ _)
- -> (es, sign, rel, es') : splat ch'
-
- -- | Take each triple and combine the lhs/rhs to make all the conjuncts.
- conjuncts :: [(NonEmpty Raw.Expr, Sign, Raw.Relation, NonEmpty Raw.Expr)] -> [(Sign, Raw.Relation, Raw.Expr, Raw.Expr)]
- conjuncts triples = do
- (e1s, sign, rel, e2s) <- triples
- e1 <- toList e1s
- e2 <- toList e2s
- pure (sign, rel, e1, e2)
-
- makeRels :: [(Sign, Raw.Relation, Raw.Expr, Raw.Expr)] -> Gloss [Sem.Formula]
- makeRels triples = for triples makeRel
-
- makeRel :: (Sign, Raw.Relation, Raw.Expr, Raw.Expr) -> Gloss Sem.Formula
- makeRel (sign, rel, e1, e2) = do
- e1' <- glossExpr e1
- e2' <- glossExpr e2
- case rel of
- Raw.Relation loc rel' params -> do
- params' <- glossExpr `each` params
- buildRelation <-
- liftRelationApplication
- (Sem.makeRelationApplication loc rel' params')
- pure $ sign' loc $ buildRelation e1' e2'
- Raw.RelationExpr loc e -> do
- e' <- glossExpr e
- pure (sign' loc (Sem.IsElementOf loc (Sem.TermPair loc e1' e2') e'))
- where
- sign' = case sign of
- Positive -> \_ -> id
- Negative -> Sem.Not
-
-
-glossPrefixPredicate :: Raw.PrefixPredicate -> Gloss Sem.Predicate
-glossPrefixPredicate (Raw.PrefixPredicate symb _ar) = pure (Sem.PredicateSymbol symb)
-
-
-glossNPNonEmpty :: Raw.NounPhrase NonEmpty -> Gloss (NonEmpty VarSymbol, Sem.Formula)
-glossNPNonEmpty (Raw.NounPhrase leftAdjs noun vars rightAdjs maySuchThat) = do
- -- We interpret the noun as a predicate.
- noun' <- glossNoun noun
- -- Now we turn the noun and all its modifiers into statements.
- let typings = (\v' -> noun' (Sem.TermVar v')) <$> vars
- leftAdjs' <- forEach (toList vars) <$> glossAdjL `each` leftAdjs
- rightAdjs' <- forEach (toList vars) <$> glossAdjR `each` rightAdjs
- suchThat <- maybeToList <$> glossStmt `each` maySuchThat
- let constraints = toList typings <> leftAdjs' <> rightAdjs' <> suchThat
- pure (vars, Sem.makeConjunction constraints)
-
-
--- | If needed, we introduce a fresh variable to reduce this to the case @NounPhrase NonEmpty@.
-glossNPList :: Raw.NounPhrase [] -> Gloss (NonEmpty VarSymbol, Sem.Formula)
-glossNPList (Raw.NounPhrase leftAdjs noun vars rightAdjs maySuchThat) = do
- vars' <- case vars of
- [] -> (:| []) <$> freshVar
- v:vs -> pure (v :| vs)
- glossNPNonEmpty $ Raw.NounPhrase leftAdjs noun vars' rightAdjs maySuchThat
-
--- Returns a predicate for a term (the constraints) and the optional such-that clause.
--- We treat suchThat separately since multiple terms can share the same such-that clause.
-glossNPMaybe :: Raw.NounPhrase Maybe -> Gloss (Sem.Term -> Sem.Formula, Maybe Sem.Formula)
-glossNPMaybe (Raw.NounPhrase leftAdjs noun mayVar rightAdjs maySuchThat) = do
- case mayVar of
- Nothing -> do
- glossNP leftAdjs noun rightAdjs maySuchThat
- Just v' -> do
- -- Next we desugar all the modifiers into statements.
- leftAdjs' <- apply v' <$> glossAdjL `each` leftAdjs
- rightAdjs' <- apply v' <$> glossAdjR `each` rightAdjs
- maySuchThat' <- glossStmt `each` maySuchThat
- let constraints = leftAdjs' <> rightAdjs'
- -- Finally we translate the noun itself.
- noun' <- glossNoun noun
- pure case constraints of
- [] -> (\t -> noun' t, maySuchThat')
- _ -> (\t -> noun' t `Sem.And` Sem.makeConjunction (eq t v' : constraints), maySuchThat')
- where
- eq t v = Sem.Equals Nowhere t (Sem.TermVar v)
- apply :: VarSymbol -> [Sem.Term -> Sem.Formula] -> [Sem.Formula]
- apply v stmts = [stmt (Sem.TermVar v) | stmt <- stmts]
-
--- | Gloss a noun without a variable name.
--- Returns a predicate for a term (the constraints) and the optional such-that clause.
--- We treat suchThat separately since multiple terms can share the same such-that clause.
-glossNP :: [Raw.AdjL] -> Raw.Noun -> [Raw.AdjR] -> Maybe Raw.Stmt -> Gloss (Sem.Term -> Sem.ExprOf VarSymbol, Maybe Sem.Formula)
-glossNP leftAdjs noun rightAdjs maySuchThat = do
- noun' <- glossNoun noun
- leftAdjs' <- glossAdjL `each` leftAdjs
- rightAdjs' <- glossAdjR `each` rightAdjs
- maySuchThat' <- glossStmt `each` maySuchThat
- let constraints = [noun'] <> leftAdjs' <> rightAdjs'
- pure (\t -> Sem.makeConjunction (flap constraints t), maySuchThat')
-
-
--- | If we have a plural noun with multiple variables, then we need to desugar
--- adjectives to apply to each individual variable.
-forEach :: Applicative t => t VarSymbol -> t (Sem.Term -> a) -> t a
-forEach vs'' stmts = do
- v <- vs''
- stmt <- stmts
- pure $ stmt (Sem.TermVar v)
-
-
-glossAdjL :: Raw.AdjL -> Gloss (Sem.Term -> Sem.Formula)
-glossAdjL (Raw.AdjL loc pat es) = do
- (es', quantifies) <- unzip <$> glossTerm `each` es
- let quantify = compose $ reverse quantifies
- pure $ \t -> quantify $ Sem.FormulaAdj loc t pat es'
-
-
--- | Since we need to be able to remove negation in verb phrases,
--- we need to have 'Sem.Stmt' as the target. We do not yet have
--- the term representing the subject, hence the parameter 'Sem.Expr'.
-glossAdjR :: Raw.AdjR -> Gloss (Sem.Term -> Sem.Formula)
-glossAdjR = \case
- Raw.AdjR _loc pat [e] | pat == Raw.mkLexicalItem (unsafeReadPhrase "equal to ?") "eq" -> do
- (e', quantify) <- glossTerm e
- pure $ \t -> quantify $ Sem.Equals Nowhere t e'
- Raw.AdjR _loc pat es -> do
- (es', quantifies) <- unzip <$> glossTerm `each` es
- let quantify = compose $ reverse quantifies
- pure $ \t -> quantify $ Sem.FormulaAdj Nowhere t pat es'
- Raw.AttrRThat vp -> glossVP vp
-
-
-glossAdj :: Raw.AdjOf Raw.Term -> Gloss (Sem.ExprOf VarSymbol -> Sem.Formula)
-glossAdj adj = case adj of
- Raw.Adj loc pat [e] | pat == Raw.mkLexicalItem (unsafeReadPhrase "equal to ?") "eq" -> do
- (e', quantify) <- glossTerm e
- pure $ \t -> quantify $ Sem.Equals loc t e'
- Raw.Adj loc pat es -> do
- (es', quantifies) <- unzip <$> glossTerm `each` es
- let quantify = compose $ reverse quantifies
- pure $ \t -> quantify $ Sem.FormulaAdj loc t pat es'
-
-glossVP :: Raw.VerbPhrase -> Gloss (Sem.Term -> Sem.Formula)
-glossVP = \case
- Raw.VPVerb verb -> glossVerb verb
- Raw.VPAdj adjs -> do
- mkAdjs <- glossAdj `each` toList adjs
- pure (\x -> Sem.makeConjunction [mkAdj x | mkAdj <- mkAdjs])
- Raw.VPVerbNot verb -> (Sem.Not Nowhere .) <$> glossVerb verb
- Raw.VPAdjNot adjs -> (Sem.Not Nowhere .) <$> glossVP (Raw.VPAdj adjs)
-
-
-glossVerb :: Raw.Verb -> Gloss (Sem.Term -> Sem.Formula)
-glossVerb (Raw.Verb loc pat es) = do
- (es', quantifies) <- unzip <$> glossTerm `each` es
- let quantify = compose $ reverse quantifies
- pure $ \ t -> quantify $ Sem.FormulaVerb loc t pat es'
-
-
-glossNoun :: Raw.Noun -> Gloss (Sem.Term -> Sem.Formula)
-glossNoun (Raw.Noun loc pat es) = do
- (es', quantifies) <- unzip <$> glossTerm `each` es
- let quantify = compose $ reverse quantifies
- pure case Raw.sg (Raw.lexicalItemSgPlPhrase pat) of
- -- Everything is a set
- [Just (Sem.Word "set")] -> const Sem.Top
- _ -> \e' -> quantify (Sem.FormulaNoun loc e' pat es')
-
-
-glossFun :: Raw.Fun -> Gloss (Sem.Term, Sem.Formula -> Sem.Formula)
-glossFun (Raw.Fun loc phrase es) = do
- (es', quantifies) <- unzip <$> glossTerm `each` es
- let quantify = compose $ reverse quantifies
- pure (Sem.TermSymbol loc (Sem.SymbolFun phrase) es', quantify)
-
-
-glossTerm :: Raw.Term -> Gloss (Sem.Term, Sem.Formula -> Sem.Formula)
-glossTerm = \case
- Raw.TermExpr e ->
- (, id) <$> glossExpr e
- Raw.TermFun f ->
- glossFun f
- Raw.TermIota location _variable _statement ->
- rejectIotaTerm location
- Raw.TermQuantified _quantifier loc _nounPhrase ->
- throwError (QuantifiedTermRequiresResolvedContext loc)
-
-rejectIotaTerm :: Location -> Gloss a
-rejectIotaTerm =
- throwError . IotaTermNotSupported
-
-
-data H0QuantifiedTerm = H0QuantifiedTerm
- { h0Quantifier :: Raw.Quantifier
- , h0QuantifiedBinder :: H0ResolvedBinder
- , h0QuantifiedConstraints :: [H0Expr]
- }
-
-data H0TermPlan = H0TermPlan
- { h0TermExpression :: H0Expr
- , h0TermEnvironment :: H0LexicalEnvironment
- , h0TermQuantifiers :: [H0QuantifiedTerm]
- }
-
-data H0TermsPlan = H0TermsPlan
- { h0TermExpressions :: [H0Expr]
- , h0TermsEnvironment :: H0LexicalEnvironment
- , h0TermsQuantifiers :: [H0QuantifiedTerm]
- }
-
-glossH0Terms
- :: H0LexicalEnvironment
- -> [Raw.Term]
- -> Gloss H0TermsPlan
-glossH0Terms initialEnvironment =
- go initialEnvironment mempty [] []
- where
- go environment _seenBinders expressions quantifiers [] =
- pure
- H0TermsPlan
- { h0TermExpressions = reverse expressions
- , h0TermsEnvironment = environment
- , h0TermsQuantifiers = reverse quantifiers
- }
- go environment seenBinders expressions quantifiers (term : terms) = do
- termPlan <- glossH0Term environment term
- nextSeenBinders <-
- foldM
- addSiblingBinder
- seenBinders
- (h0TermQuantifiers termPlan)
- go
- (h0TermEnvironment termPlan)
- nextSeenBinders
- (h0TermExpression termPlan : expressions)
- (reverse (h0TermQuantifiers termPlan) <> quantifiers)
- terms
-
- addSiblingBinder seenBinders quantifiedTerm =
- case binderDisplayHint binderTrivia of
- Nothing ->
- pure seenBinders
- Just displayName ->
- case Map.lookup displayName seenBinders of
- Nothing ->
- pure
- (Map.insert
- displayName
- binderTrivia
- seenBinders)
- Just firstBinderTrivia ->
- throwError
- (DuplicateQuantifiedNounBinder
- (binderDeclarationLocation
- firstBinderTrivia)
- (binderDeclarationLocation
- binderTrivia)
- displayName)
- where
- binderTrivia =
- h0BinderTrivia
- (h0QuantifiedBinder quantifiedTerm)
-
-glossH0Term
- :: H0LexicalEnvironment
- -> Raw.Term
- -> Gloss H0TermPlan
-glossH0Term environment = \case
- Raw.TermExpr expression -> do
- expression' <- resolveH0Expr environment <$> glossExpr expression
- pure
- H0TermPlan
- { h0TermExpression = expression'
- , h0TermEnvironment = environment
- , h0TermQuantifiers = []
- }
- Raw.TermFun (Raw.Fun location symbol arguments) -> do
- argumentsPlan <- glossH0Terms environment arguments
- pure
- H0TermPlan
- { h0TermExpression =
- Sem.TermSymbol
- location
- (Sem.SymbolFun symbol)
- (h0TermExpressions argumentsPlan)
- , h0TermEnvironment =
- h0TermsEnvironment argumentsPlan
- , h0TermQuantifiers =
- h0TermsQuantifiers argumentsPlan
- }
- Raw.TermIota location _variable _statement ->
- rejectIotaTerm location
- Raw.TermQuantified quantifier location nounPhrase -> do
- let writtenName = case nounPhrase of
- Raw.NounPhrase _ _ name _ _ -> name
- binder <- freshH0Binder location writtenName
- let nextEnvironment = pushH0Binder binder environment
- witness = Sem.TermVar (LocalRef (h0BinderId binder))
- constraints <-
- glossH0QuantifiedNoun
- nextEnvironment
- witness
- nounPhrase
- pure
- H0TermPlan
- { h0TermExpression = witness
- , h0TermEnvironment = nextEnvironment
- , h0TermQuantifiers =
- [ H0QuantifiedTerm
- { h0Quantifier = quantifier
- , h0QuantifiedBinder = binder
- , h0QuantifiedConstraints = constraints
- }
- ]
- }
-
-applyH0Quantifiers
- :: [H0QuantifiedTerm]
- -> H0Expr
- -> Gloss H0Expr
-applyH0Quantifiers quantifiers body =
- foldrM applyQuantifier body quantifiers
- where
- applyQuantifier quantifiedTerm continuation = do
- let constrainedBody =
- applyQuantifierConstraints
- (h0Quantifier quantifiedTerm)
- (h0QuantifiedConstraints quantifiedTerm)
- continuation
- scope <-
- abstractH0Binder
- (h0QuantifiedBinder quantifiedTerm)
- constrainedBody
- pure case h0Quantifier quantifiedTerm of
- Raw.Universally ->
- Sem.Quantified Sem.Universally scope
- Raw.Existentially ->
- Sem.Quantified Sem.Existentially scope
- Raw.Nonexistentially ->
- Sem.Not
- Nowhere
- (Sem.Quantified Sem.Existentially scope)
-
-glossH0QuantifiedNoun
- :: H0LexicalEnvironment
- -> H0Expr
- -> Raw.NounPhrase Maybe
- -> Gloss [H0Expr]
-glossH0QuantifiedNoun
- environment
- witness
- (Raw.NounPhrase leftAdjectives noun _name rightAdjectives maySuchThat) = do
- nounConstraint <- glossH0Noun environment witness noun
- leftConstraints <-
- for leftAdjectives (glossH0AdjL environment witness)
- rightConstraints <-
- for rightAdjectives (glossH0AdjR environment witness)
- suchThatConstraint <-
- traverse (glossH0Stmt environment) maySuchThat
- pure
- ( maybeToList suchThatConstraint
- <> [ Sem.makeConjunction
- ( nounConstraint
- : leftConstraints
- <> rightConstraints
- )
- ]
- )
-
-glossH0NPMaybe
- :: H0LexicalEnvironment
- -> H0Expr
- -> Raw.NounPhrase Maybe
- -> Gloss (H0Expr, Maybe H0Expr)
-glossH0NPMaybe
- environment
- subject
- (Raw.NounPhrase leftAdjectives noun mayName rightAdjectives maySuchThat) = do
- nounConstraint <- glossH0Noun environment subject noun
- suchThatConstraint <-
- traverse (glossH0Stmt environment) maySuchThat
- case mayName of
- Nothing -> do
- leftConstraints <-
- for leftAdjectives (glossH0AdjL environment subject)
- rightConstraints <-
- for rightAdjectives (glossH0AdjR environment subject)
- pure
- ( Sem.makeConjunction
- ( nounConstraint
- : leftConstraints
- <> rightConstraints
- )
- , suchThatConstraint
- )
- Just name -> do
- let namedSubject =
- Sem.TermVar
- (resolveH0Reference environment name)
- leftConstraints <-
- for leftAdjectives
- (glossH0AdjL environment namedSubject)
- rightConstraints <-
- for rightAdjectives
- (glossH0AdjR environment namedSubject)
- let modifierConstraints =
- leftConstraints <> rightConstraints
- constraint = case modifierConstraints of
- [] ->
- nounConstraint
- _ ->
- nounConstraint
- `Sem.And`
- Sem.makeConjunction
- ( Sem.Equals
- Nowhere
- subject
- namedSubject
- : modifierConstraints
- )
- pure (constraint, suchThatConstraint)
-
-glossH0AdjL
- :: H0LexicalEnvironment
- -> H0Expr
- -> Raw.AdjL
- -> Gloss H0Expr
-glossH0AdjL environment subject (Raw.AdjL location lexicalPattern arguments) = do
- argumentsPlan <- glossH0Terms environment arguments
- applyH0Quantifiers
- (h0TermsQuantifiers argumentsPlan)
- (Sem.FormulaAdj
- location
- subject
- lexicalPattern
- (h0TermExpressions argumentsPlan))
-
-glossH0AdjR
- :: H0LexicalEnvironment
- -> H0Expr
- -> Raw.AdjR
- -> Gloss H0Expr
-glossH0AdjR environment subject = \case
- Raw.AdjR _location lexicalPattern [argument]
- | lexicalPattern
- == Raw.mkLexicalItem
- (unsafeReadPhrase "equal to ?")
- "eq" -> do
- argumentPlan <-
- glossH0Term environment argument
- applyH0Quantifiers
- (h0TermQuantifiers argumentPlan)
- (Sem.Equals
- Nowhere
- subject
- (h0TermExpression argumentPlan))
- Raw.AdjR _location lexicalPattern arguments -> do
- argumentsPlan <- glossH0Terms environment arguments
- applyH0Quantifiers
- (h0TermsQuantifiers argumentsPlan)
- (Sem.FormulaAdj
- Nowhere
- subject
- lexicalPattern
- (h0TermExpressions argumentsPlan))
- Raw.AttrRThat verbPhrase ->
- glossH0VP environment subject verbPhrase
-
-glossH0Adj
- :: H0LexicalEnvironment
- -> H0Expr
- -> Raw.Adj
- -> Gloss H0Expr
-glossH0Adj environment subject = \case
- Raw.Adj location lexicalPattern [argument]
- | lexicalPattern
- == Raw.mkLexicalItem
- (unsafeReadPhrase "equal to ?")
- "eq" -> do
- argumentPlan <-
- glossH0Term environment argument
- applyH0Quantifiers
- (h0TermQuantifiers argumentPlan)
- (Sem.Equals
- location
- subject
- (h0TermExpression argumentPlan))
- Raw.Adj location lexicalPattern arguments -> do
- argumentsPlan <- glossH0Terms environment arguments
- applyH0Quantifiers
- (h0TermsQuantifiers argumentsPlan)
- (Sem.FormulaAdj
- location
- subject
- lexicalPattern
- (h0TermExpressions argumentsPlan))
-
-glossH0VP
- :: H0LexicalEnvironment
- -> H0Expr
- -> Raw.VerbPhrase
- -> Gloss H0Expr
-glossH0VP environment subject = \case
- Raw.VPVerb verb ->
- glossH0Verb environment subject verb
- Raw.VPAdj adjectives ->
- Sem.makeConjunction
- <$> for
- (toList adjectives)
- (glossH0Adj environment subject)
- Raw.VPVerbNot verb ->
- Sem.Not Nowhere
- <$> glossH0Verb environment subject verb
- Raw.VPAdjNot adjectives ->
- Sem.Not Nowhere
- <$> glossH0VP
- environment
- subject
- (Raw.VPAdj adjectives)
-
-glossH0Verb
- :: H0LexicalEnvironment
- -> H0Expr
- -> Raw.Verb
- -> Gloss H0Expr
-glossH0Verb environment subject (Raw.Verb location lexicalPattern arguments) = do
- argumentsPlan <- glossH0Terms environment arguments
- applyH0Quantifiers
- (h0TermsQuantifiers argumentsPlan)
- (Sem.FormulaVerb
- location
- subject
- lexicalPattern
- (h0TermExpressions argumentsPlan))
-
-glossH0Noun
- :: H0LexicalEnvironment
- -> H0Expr
- -> Raw.Noun
- -> Gloss H0Expr
-glossH0Noun environment subject (Raw.Noun location lexicalPattern arguments) = do
- argumentsPlan <- glossH0Terms environment arguments
- let constraint = case Raw.sg (Raw.lexicalItemSgPlPhrase lexicalPattern) of
- [Just (Sem.Word "set")] ->
- Sem.Top
- _ ->
- Sem.FormulaNoun
- location
- subject
- lexicalPattern
- (h0TermExpressions argumentsPlan)
- applyH0Quantifiers
- (h0TermsQuantifiers argumentsPlan)
- constraint
-
-
-
-glossStmt :: Raw.Stmt -> Gloss Sem.Formula
-glossStmt statement = do
- resolvedStatement <- glossH0Stmt [] statement
- lowerH0Expr resolvedStatement
-
-glossH0Stmt
- :: H0LexicalEnvironment
- -> Raw.Stmt
- -> Gloss H0Expr
-glossH0Stmt environment = \case
- Raw.StmtFormula formula ->
- resolveH0Expr environment <$> glossFormula formula
- Raw.StmtNeg location statement ->
- Sem.Not location <$> glossH0Stmt environment statement
- Raw.StmtVerbPhrase ts vp -> do
- termsPlan <- glossH0Terms environment (toList ts)
- statements <-
- for
- (h0TermExpressions termsPlan)
- (\term ->
- glossH0VP
- (h0TermsEnvironment termsPlan)
- term
- vp)
- applyH0Quantifiers
- (h0TermsQuantifiers termsPlan)
- (Sem.makeConjunction statements)
- Raw.StmtNoun ts np -> do
- termsPlan <- glossH0Terms environment (toList ts)
- statements <-
- for (h0TermExpressions termsPlan) \term -> do
- (nounConstraint, maySuchThat) <-
- glossH0NPMaybe
- (h0TermsEnvironment termsPlan)
- term
- np
- pure case maySuchThat of
- Just suchThat ->
- nounConstraint `Sem.And` suchThat
- Nothing ->
- nounConstraint
- applyH0Quantifiers
- (h0TermsQuantifiers termsPlan)
- (Sem.makeConjunction statements)
- Raw.StmtStruct t sp -> do
- termPlan <- glossH0Term environment t
- applyH0Quantifiers
- (h0TermQuantifiers termPlan)
- (Sem.TermSymbol
- (locate t)
- (Sem.SymbolPredicate
- (Sem.PredicateNounStruct sp))
- [h0TermExpression termPlan])
- Raw.StmtConnected connective _location left right ->
- Sem.Connected connective
- <$> glossH0Stmt environment left
- <*> glossH0Stmt environment right
- Raw.StmtQuantPhrase _location (Raw.QuantPhrase quantifier np) statement -> do
- (vars, constraints) <- glossNPList np
- let nestedEnvironment =
- hideH0Binders vars environment
- constraints' =
- resolveH0Expr nestedEnvironment constraints
- statement' <-
- glossH0Stmt nestedEnvironment statement
- pure
- (quantifyH0Ambient
- quantifier
- vars
- [constraints']
- statement')
- Raw.StmtExists _location np -> do
- (vars, constraints) <- glossNPList np
- let nestedEnvironment =
- hideH0Binders vars environment
- pure
- (quantifyH0Ambient
- Raw.Existentially
- vars
- []
- (resolveH0Expr nestedEnvironment constraints))
- Raw.SymbolicQuantified _loc quant vs bound suchThat have -> do
- let nestedEnvironment =
- hideH0Binders vs environment
- bound' <- glossBound bound
- let boundConstraints =
- resolveH0Expr nestedEnvironment
- <$> bound' (toList vs)
- suchThatConstraints <-
- maybeToList
- <$> traverse
- (glossH0Stmt nestedEnvironment)
- suchThat
- have' <- glossH0Stmt nestedEnvironment have
- pure
- (quantifyH0Ambient
- quant
- vs
- (boundConstraints <> suchThatConstraints)
- have')
-
--- Other binder forms stay on the legacy path and only mask outer H0 names.
-hideH0Binders
- :: Foldable f
- => f VarSymbol
- -> H0LexicalEnvironment
- -> H0LexicalEnvironment
-hideH0Binders variables =
- List.filter \binder ->
- maybe
- True
- (`Set.notMember` displayedNames)
- (binderDisplayHint (h0BinderTrivia binder))
- where
- displayedNames =
- Set.fromList
- [ name
- | NamedVarAt _ name <- toList variables
- ]
-
-quantifyH0Ambient
- :: Foldable f
- => Raw.Quantifier
- -> f VarSymbol
- -> [H0Expr]
- -> H0Expr
- -> H0Expr
-quantifyH0Ambient quantifier variables constraints body =
- case quantifier of
- Raw.Universally ->
- Sem.Quantified Sem.Universally scope
- Raw.Existentially ->
- Sem.Quantified Sem.Existentially scope
- Raw.Nonexistentially ->
- Sem.Not
- Nowhere
- (Sem.Quantified Sem.Existentially scope)
- where
- constrainedBody =
- applyQuantifierConstraints quantifier constraints body
- scope =
- abstract
- (\case
- AmbientRef variable
- | variable `elem` variables ->
- Just variable
- _ ->
- Nothing)
- constrainedBody
-
--- | A bound applies to all listed variables. Note the use of '<**>'.
---
--- >>> ([1, 2, 3] <**> [(+ 10)]) == [11, 12, 13]
---
-glossBound :: Raw.Bound -> Gloss ([VarSymbol] -> [Sem.Formula])
-glossBound = \case
- Raw.Unbounded -> pure (const [])
- Raw.Bounded loc sign rel term -> do
- term' <- glossExpr term
- let sign' = case sign of
- Positive -> id
- Negative -> Sem.Not loc
- bound <- case rel of
- Raw.Relation loc' rel' params -> do
- params' <- glossExpr `each` params
- buildRelation <-
- liftRelationApplication
- (Sem.makeRelationApplication loc' rel' params')
- pure $ \v -> sign' $
- buildRelation (Sem.TermVar v) term'
- Raw.RelationExpr loc' e -> do
- e' <- glossExpr e
- pure $ \v -> sign' $
- Sem.IsElementOf loc' (Sem.TermPair loc' (Sem.TermVar v) term') e'
- pure \vs -> vs <**> [bound]
-
-
-glossConnective :: Raw.Connective -> Gloss (Sem.Formula -> Sem.Formula -> Sem.Formula)
-glossConnective conn = pure (Sem.Connected conn)
-
-
-glossAsm :: Raw.Asm -> Gloss [Sem.Asm]
-glossAsm = \case
- Raw.AsmSuppose s -> do
- s' <- glossStmt s
- pure [Sem.Asm s']
- Raw.AsmLetNoun vs np -> do
- (np', maySuchThat) <- glossNPMaybe np
- let f v = Sem.Asm (np' (Sem.TermVar v) )
- let suchThat = Sem.Asm <$> maybeToList maySuchThat
- pure (suchThat <> fmap f (toList vs))
- Raw.AsmLetIn vs e -> do
- e' <- glossExpr e
- let f v = Sem.Asm (Sem.IsElementOf Nowhere (Sem.TermVar v) e')
- pure $ fmap f (toList vs)
- Raw.AsmLetStruct structLabel structPhrase ->
- pure [Sem.AsmStruct structLabel structPhrase]
- Raw.AsmLetThe _variable fun ->
- throwError
- (DefiniteFunctionAssumptionNotSupported
- (locate fun))
- Raw.AsmLetEq x e -> do
- e' <- glossExpr e
- pure (Sem.Asm (Sem.Equals Nowhere (Sem.TermVar x) e') : [])
-
-
--- | A quantifier is interpreted as a quantification function that takes a nonempty list of variables,
--- a list of formulas expressing the constraints, and the formula to be quantified as arguments.
--- It then returns the quantification with the correct connective for the constraints.
-glossQuantifier
- :: (Foldable t, Applicative f)
- => Raw.Quantifier
- -> f (t VarSymbol
- -> [Sem.ExprOf VarSymbol]
- -> Sem.Formula
- -> Sem.Formula)
-glossQuantifier quantifier = pure quantify
- where
- quantify vs constraints body = case quantifier of
- Raw.Universally ->
- Sem.makeForall
- vs
- (applyQuantifierConstraints
- quantifier
- constraints
- body)
- Raw.Existentially ->
- Sem.makeExists
- vs
- (applyQuantifierConstraints
- quantifier
- constraints
- body)
- Raw.Nonexistentially ->
- Sem.Not
- Nowhere
- (Sem.makeExists
- vs
- (applyQuantifierConstraints
- quantifier
- constraints
- body))
-
-applyQuantifierConstraints
- :: Raw.Quantifier
- -> [Sem.ExprOf a]
- -> Sem.ExprOf a
- -> Sem.ExprOf a
-applyQuantifierConstraints _quantifier [] body =
- body
-applyQuantifierConstraints quantifier constraints body =
- case quantifier of
- Raw.Universally ->
- Sem.makeConjunction constraints `Sem.Implies` body
- Raw.Existentially ->
- Sem.makeConjunction constraints `Sem.And` body
- Raw.Nonexistentially ->
- Sem.makeConjunction constraints `Sem.And` body
-
-
-glossAsms :: [Raw.Asm] -> Gloss [Sem.Asm]
-glossAsms asms = do
- asms' <- glossAsm `each` asms
- pure $ concat asms'
-
-
-glossAxiom :: Raw.Axiom -> Gloss Sem.Axiom
-glossAxiom (Raw.Axiom asms f) = Sem.Axiom <$> glossAsms asms <*> glossStmt f
-
-
-glossLemma :: Raw.Claim -> Gloss Sem.Lemma
-glossLemma (Raw.Claim asms f) = Sem.Lemma <$> glossAsms asms <*> glossStmt f
-
-
-glossDefn
- :: Location
- -> Sem.Marker
- -> Raw.Defn
- -> Gloss Sem.Defn
-glossDefn blockLocation blockMarker = \case
- Raw.Defn asms h f ->
- glossDefnHead blockLocation h <*> glossAsms asms <*> glossStmt f
- Raw.DefnFun asms (Raw.Fun _loc fun vs) _ e -> do
- asms' <- glossAsms asms
- e' <- case e of
- Raw.TermQuantified _ loc _ ->
- throwError
- (GlossDefnError
- loc
- DefnErrorQuantifiedRhsTerm
- blockMarker)
- _ -> fst <$> glossTerm e
- pure $ Sem.DefnFun asms' fun vs e'
- Raw.DefnOp (Raw.SymbolPattern op vs) e ->
- Sem.DefnOp op vs <$> glossExpr e
-
-
--- | A definition head is interpreted as a builder of a definition,
--- depending on a previous assumptions and on a rhs.
-glossDefnHead
- :: Location
- -> Raw.DefnHead
- -> Gloss ([Sem.Asm] -> Sem.Formula -> Sem.Defn)
-glossDefnHead blockLocation = \case
- -- TODO add info from NP.
- Raw.DefnAdj _mnp v (Raw.Adj _loc adj vs) -> do
- pure $ \asms f -> Sem.DefnPredicate asms (Sem.PredicateAdj adj) (v :| vs) f
- --mnp' <- glossNPMaybe `each` mnp
- --pure $ case mnp' of
- -- Nothing -> \asms f -> Sem.DefnPredicate asms (Sem.PredicateAdj adj') (v :| vs) f
- -- Just np' -> \asms f -> Sem.DefnPredicate asms (Sem.PredicateAdj adj') (v :| vs) (Sem.FormulaAnd (np' v) f)
- Raw.DefnVerb _mnp v (Raw.Verb _loc verb vs) ->
- pure $ \asms f -> Sem.DefnPredicate asms (Sem.PredicateVerb verb) (v :| vs) f
- Raw.DefnNoun v (Raw.Noun _loc noun vs) ->
- pure $ \asms f -> Sem.DefnPredicate asms (Sem.PredicateNoun noun) (v :| vs) f
- Raw.DefnRel v1 rel params v2 -> do
- liftRelationApplication
- (Sem.checkRelationParameterArity
- blockLocation
- rel
- params)
- pure \asms f ->
- let args = case params of
- p : ps -> p :| (ps <> [v1, v2])
- [] -> v1 :| [v2]
- in Sem.DefnPredicate asms (Sem.PredicateRelation rel) args f
- Raw.DefnSymbolicPredicate (Raw.PrefixPredicate symb _ar) _marker vs ->
- pure $ \asms f -> Sem.DefnPredicate asms (Sem.PredicateSymbol symb) vs f
-
-
-glossProof :: Raw.Proof -> Gloss Sem.Proof
-glossProof = \case
- Raw.Omitted loc ->
- pure (Sem.Omitted loc)
- Raw.Qed loc by ->
- pure (Sem.Qed loc by)
- Raw.Contradiction loc by ->
- pure (Sem.Contradiction loc by)
- Raw.ByContradiction loc proof ->
- Sem.ByContradiction loc <$> glossProof proof
- Raw.BySetInduction loc mt proof ->
- Sem.BySetInduction loc <$> mmt' <*> glossProof proof
- where
- mmt' = case mt of
- Nothing -> pure Nothing
- Just (Raw.TermExpr (Raw.ExprVar x)) -> pure (Just (Sem.TermVar x))
- Just _t -> throwError (GlossInductionError loc)
- Raw.ByOrdInduction loc proof ->
- Sem.ByOrdInduction loc <$> glossProof proof
- Raw.ByCase loc cases -> Sem.ByCase loc <$> glossCase `each` cases
- Raw.Have loc _ms s by proof -> case s of
- -- Pragmatics: an existential @Have@ implicitly
- -- introduces the witness and is interpreted as a @Take@ construct.
- Raw.SymbolicExists _loc vs bound suchThat -> do
- bound' <- glossBound bound
- suchThat' <- glossStmt suchThat
- proof' <- glossProof proof
- pure (Sem.Take loc vs (Sem.makeConjunction (suchThat' : bound' (toList vs))) by proof')
- _otherwise ->
- Sem.Have loc <$> glossStmt s <*> pure by <*> glossProof proof
- Raw.Assume loc stmt proof ->
- Sem.Assume loc <$> glossStmt stmt <*> glossProof proof
- Raw.FixSymbolic loc xs bound proof -> do
- bound' <- glossBound bound
- proof' <- glossProof proof
- pure (Sem.Fix loc xs (Sem.makeConjunction (bound' (toList xs))) proof')
- Raw.FixSuchThat loc xs stmt proof -> do
- stmt' <- glossStmt stmt
- proof' <- glossProof proof
- pure (Sem.Fix loc xs stmt' proof')
- Raw.TakeVar loc vs bound suchThat by proof -> do
- bound' <- glossBound bound
- suchThat' <- glossStmt suchThat
- proof' <- glossProof proof
- pure (Sem.Take loc vs (Sem.makeConjunction (suchThat' : bound' (toList vs))) by proof')
- Raw.TakeNoun loc np by proof -> do
- (vs, constraints) <- glossNPList np
- proof' <- glossProof proof
- pure $ Sem.Take loc vs constraints by proof'
- Raw.Subclaim loc subclaim subproof proof ->
- Sem.Subclaim loc <$> glossStmt subclaim <*> glossProof subproof <*> glossProof proof
- Raw.Suffices loc reduction by proof ->
- Sem.Suffices loc <$> glossStmt reduction <*> pure by <*> glossProof proof
- Raw.Define loc var term proof ->
- Sem.Define loc var <$> glossExpr term <*> glossProof proof
- Raw.DefineFunction loc funVar argVar valueExpr domVar domExpr proof ->
- if domVar == argVar
- then Sem.DefineFunction loc funVar argVar <$> glossExpr valueExpr <*> glossExpr domExpr <*> glossProof proof
- else
- throwError
- (GlossProofFunctionArgumentMismatch
- loc
- argVar
- domVar)
-
- Raw.DefineFunctionLocal loc funVar domVar ranExpr funVar2 argVar definitions proof -> do
- if funVar == funVar2
- then Sem.DefineFunctionLocal loc funVar argVar domVar <$> glossExpr ranExpr <*> (glossLocalFunctionExprDef `each` definitions) <*> glossProof proof
- else
- throwError
- (GlossProofFunctionNameMismatch
- loc
- funVar
- funVar2)
- Raw.Calc loc calcQuant calc proof ->
- Sem.Calc loc <$> glossCalcQuantifier calcQuant <*> glossCalc calc <*> glossProof proof
-
-glossCalcQuantifier :: Maybe Raw.CalcQuantifier -> Gloss Sem.CalcQuantifier
-glossCalcQuantifier Nothing = pure Sem.CalcUnquantified
-glossCalcQuantifier (Just (Raw.CalcQuantifier xs bound maySuchThat)) = do
- bound' <- glossBound bound
- maySuchThat' <- glossStmt `each` maySuchThat
- let constraints = bound' (toList xs) <> maybeToList maySuchThat'
- let calcGuard = case constraints of
- [] -> Nothing
- _ -> Just (Sem.makeConjunction constraints)
- pure (Sem.CalcForall xs calcGuard)
-
-glossLocalFunctionExprDef :: (Raw.Expr, Raw.Formula) -> Gloss (Sem.Term, Sem.Formula)
-glossLocalFunctionExprDef (definingExpression, localDomain) = do
- e <- glossExpr definingExpression
- d <- glossFormula localDomain
- pure (e,d)
-
-
-glossCase :: Raw.Case -> Gloss Sem.Case
-glossCase (Raw.Case caseOf proof) = Sem.Case <$> glossStmt caseOf <*> glossProof proof
-
-glossCalc :: Raw.Calc -> Gloss Sem.Calc
-glossCalc = \case
- Raw.Equation e eqns -> do
- e' <- glossExpr e
- eqns' <- (\(ei, ji) -> (,ji) <$> glossExpr ei) `each` eqns
- pure (Sem.Equation e' eqns')
- Raw.Biconditionals p ps -> do
- p' <- glossFormula p
- ps' <- (\(pi, ji) -> (,ji) <$> glossFormula pi) `each` ps
- pure (Sem.Biconditionals p' ps')
-
-glossSignature :: Raw.Signature -> Gloss Sem.Signature
-glossSignature sig = case sig of
- Raw.SignatureAdj v (Raw.Adj _loc adj vs) ->
- pure $ Sem.SignaturePredicate (Sem.PredicateAdj adj) (v :| vs)
- Raw.SignatureVerb v (Raw.Verb _loc verb vs) ->
- pure $ Sem.SignaturePredicate (Sem.PredicateVerb verb) (v :| vs)
- Raw.SignatureNoun v (Raw.Noun _loc noun vs) ->
- pure $ Sem.SignaturePredicate (Sem.PredicateNoun noun) (v :| vs)
- Raw.SignatureSymbolic (Raw.SymbolPattern op vs) np -> do
- (np', maySuchThat) <- glossNPMaybe np
- let andSuchThat phi = case maySuchThat of
- Just suchThat -> phi `Sem.And` suchThat
- Nothing -> phi
- let op' = Sem.TermOp Nowhere op (Sem.TermVar <$> vs)
- v <- freshVar
- let v' = Sem.TermVar v
- pure $ Sem.SignatureFormula $ Sem.makeForall [v] ((Sem.Equals Nowhere v' op') `Sem.Implies` andSuchThat (np' v'))
-
-
-glossStructDefn :: Raw.StructDefn -> Gloss Sem.StructDefn
-glossStructDefn (Raw.StructDefn phrase base carrier fixes assumes) = do
- assumes' <- (\(m, stmt) -> (m,) <$> glossStmt stmt) `each` assumes
- let base' = Set.fromList base
- let fixes' = Set.fromList fixes
- pure $ Sem.StructDefn phrase base' carrier fixes' assumes'
-
-
-glossAbbreviation
- :: Location
- -> Sem.Marker
- -> Raw.Abbreviation
- -> Gloss Sem.Abbreviation
-glossAbbreviation blockLocation blockMarker = \case
- Raw.AbbreviationAdj x (Raw.Adj _loc adj xs) stmt ->
- build
- (Sem.SymbolPredicate (Sem.PredicateAdj adj))
- (x : xs)
- (glossStmt stmt)
- Raw.AbbreviationVerb x (Raw.Verb _loc verb xs) stmt ->
- build
- (Sem.SymbolPredicate (Sem.PredicateVerb verb))
- (x : xs)
- (glossStmt stmt)
- Raw.AbbreviationNoun x (Raw.Noun _loc noun xs) stmt ->
- build
- (Sem.SymbolPredicate (Sem.PredicateNoun noun))
- (x : xs)
- (glossStmt stmt)
- Raw.AbbreviationRel x rel params y stmt -> do
- liftRelationApplication
- (Sem.checkRelationParameterArity
- blockLocation
- rel
- params)
- build
- (Sem.SymbolPredicate (Sem.PredicateRelation rel))
- (params <> [x, y])
- (glossStmt stmt)
- Raw.AbbreviationFun (Raw.Fun _loc fun xs) t ->
- build
- (Sem.SymbolFun fun)
- xs
- (fst <$> glossTerm t)
- Raw.AbbreviationEq (Raw.SymbolPattern op xs) e ->
- build
- (Sem.SymbolMixfix op)
- xs
- (glossExpr e)
- where
- build =
- makeAbbreviation blockLocation blockMarker
-
-makeAbbreviation
- :: Location
- -> Sem.Marker
- -> Sem.Symbol
- -> [VarSymbol]
- -> Gloss Sem.Expr
- -> Gloss Sem.Abbreviation
-makeAbbreviation blockLocation blockMarker symbol rawParameters elaborateBody = do
- parameters <-
- either
- (throwError
- . GlossAbbreviationError
- blockLocation
- blockMarker
- . DuplicateAbbreviationParameters)
- pure
- (validateAbbreviationParameters rawParameters)
- body <- elaborateBody
- scope <-
- either
- (throwError
- . GlossAbbreviationError
- blockLocation
- blockMarker
- . FreeAbbreviationBodyVariables)
- pure
- (abstractClosedAbbreviation parameters body)
- pure (Sem.Abbreviation symbol scope)
- where
- validateAbbreviationParameters
- :: [VarSymbol]
- -> Either
- (NonEmpty VarSymbol)
- (Map VarSymbol Int)
- validateAbbreviationParameters parameters =
- case NonEmpty.nonEmpty (duplicateParameters parameters) of
- Just duplicates ->
- Left duplicates
- Nothing ->
- Right (Map.fromList (zip parameters [0 ..]))
-
- abstractClosedAbbreviation
- :: Map VarSymbol Int
- -> Sem.Expr
- -> Either
- (NonEmpty VarSymbol)
- (Scope Int Sem.ExprOf Void)
- abstractClosedAbbreviation parameterIndices body =
- case NonEmpty.nonEmpty unknownVariables of
- Just variables ->
- Left variables
- Nothing ->
- case traverse bindParameter body of
- Left variable ->
- Left (variable :| [])
- Right scopedBody ->
- Right (toScope scopedBody)
- where
- unknownVariables =
- Set.toAscList
- ( Sem.freeVars body
- `Set.difference`
- Map.keysSet parameterIndices
- )
-
- bindParameter
- :: VarSymbol
- -> Either
- VarSymbol
- (Var Int Void)
- bindParameter variable =
- case Map.lookup variable parameterIndices of
- Nothing ->
- Left variable
- Just parameterIndex ->
- Right (B parameterIndex)
-
- duplicateParameters :: [VarSymbol] -> [VarSymbol]
- duplicateParameters =
- reverse . third . foldl' step (mempty, mempty, [])
- where
- step (seen, reported, duplicates) variable
- | variable `Set.notMember` seen =
- (Set.insert variable seen, reported, duplicates)
- | variable `Set.member` reported =
- (seen, reported, duplicates)
- | otherwise =
- ( seen
- , Set.insert variable reported
- , variable : duplicates
- )
-
- third (_seen, _reported, duplicates) =
- duplicates
-
-glossInductive :: Raw.Inductive -> Gloss Sem.Inductive
-glossInductive (Raw.Inductive (Raw.SymbolPattern symbol args) domain rules) =
- Sem.Inductive symbol args <$> glossExpr domain <*> (glossRule `each` rules)
- where
- glossRule (Raw.IntroRule phis psi) = Sem.IntroRule <$> (glossFormula `each` phis) <*> glossFormula psi
-
-glossDatatype :: Raw.Datatype -> Gloss Sem.Datatype
-glossDatatype rawDatatype = do
- let datatypeHeadExpr = Raw.datatypeHeadExpr rawDatatype
- rawClauses = Raw.datatypeClauses rawDatatype
- datatypeHead <- glossDatatypeHead datatypeHeadExpr
- datatypeClauses <- glossDatatypeClause datatypeHead `each` rawClauses
- pure (Sem.Datatype datatypeHead datatypeClauses)
- where
- glossDatatypeHead :: Raw.Expr -> Gloss Sem.SymbolPattern
- glossDatatypeHead expr = case expr of
- Raw.ExprOp _loc item [] ->
- pure (Sem.SymbolPattern item [])
- _ ->
- throwError (GlossDatatypeHeadError (locate expr))
-
- glossDatatypeClause :: Sem.SymbolPattern -> Raw.DatatypeClause -> Gloss Sem.DatatypeClause
- glossDatatypeClause datatypeHead rawClause = do
- let constructorExpr = Raw.datatypeClauseConstructorExpr rawClause
- targetExpr = Raw.datatypeClauseTargetExpr rawClause
- rawPremises = Raw.datatypeClausePremises rawClause
- datatypeTarget <- glossDatatypeHead targetExpr
- unless (datatypeTarget == datatypeHead) do
- throwError (GlossDatatypeClauseTargetError (locate targetExpr))
- datatypeClauseConstructor <- glossDatatypeConstructor constructorExpr
- datatypeClausePremises <- traverse glossDatatypePremise rawPremises
- pure (Sem.DatatypeClause datatypeClauseConstructor datatypeClausePremises)
-
- glossDatatypeConstructor :: Raw.Expr -> Gloss Sem.SymbolPattern
- glossDatatypeConstructor expr = case expr of
- Raw.ExprOp _loc item args -> do
- vars <- traverse glossConstructorArg args
- pure (Sem.SymbolPattern item vars)
- _ ->
- throwError (GlossDatatypeConstructorError (locate expr))
-
- glossConstructorArg :: Raw.Expr -> Gloss VarSymbol
- glossConstructorArg = \case
- Raw.ExprVar x -> pure x
- expr -> throwError (GlossDatatypeConstructorError (locate expr))
-
- glossDatatypePremise :: (VarSymbol, Raw.Expr) -> Gloss (VarSymbol, Sem.Expr)
- glossDatatypePremise (x, domain) =
- (x,) <$> glossExpr domain
-
-glossBlock :: Raw.Block -> Gloss Sem.Block
-glossBlock = \case
- Raw.BlockAxiom loc _title marker axiom ->
- Sem.BlockAxiom loc marker <$> glossAxiom axiom
- Raw.BlockClaim _claimKind loc _title marker lemma ->
- Sem.BlockLemma loc marker <$> glossLemma lemma
- Raw.BlockProof startLoc proof endLoc ->
- Sem.BlockProof startLoc endLoc <$> glossProof proof
- Raw.BlockDefn loc _title marker defn -> do
- defn' <- glossDefn loc marker defn
- whenLeft (isWellformedDefn defn') (\err -> throwError (GlossDefnError loc err marker))
- pure $ Sem.BlockDefn loc marker defn'
- Raw.BlockAbbr loc _title marker abbr ->
- Sem.BlockAbbr loc marker
- <$> glossAbbreviation loc marker abbr
- Raw.BlockSig loc _title marker asms sig ->
- Sem.BlockSig loc marker <$> glossAsms asms <*> glossSignature sig
- Raw.BlockStruct loc _title m structDefn ->
- Sem.BlockStruct loc m <$> glossStructDefn structDefn
- Raw.BlockData loc _title marker datatype ->
- Sem.BlockData loc marker <$> glossDatatype datatype
- Raw.BlockInductive loc _title marker ind ->
- Sem.BlockInductive loc marker <$> glossInductive ind
-
-
-glossBlocks :: [Raw.Block] -> Gloss [Sem.Block]
-glossBlocks blocks = glossBlock `each` blocks