summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authoradelon <22380201+adelon@users.noreply.github.com>2025-12-09 18:47:46 +0100
committeradelon <22380201+adelon@users.noreply.github.com>2025-12-09 18:47:46 +0100
commit82ba804585cb80f66d58de41b0401fc2049d14d7 (patch)
tree7b1d4e541220b73c98a101ae2f9e6d31a608fb7d /source
parente1e821890f54aeb0565df83d0cb9034353b3b204 (diff)
Gather some location info from parser
WIP
Diffstat (limited to 'source')
-rw-r--r--source/Checking.hs46
-rw-r--r--source/Meaning.hs122
-rw-r--r--source/Report/Location.hs26
-rw-r--r--source/Syntax/Abstract.hs101
-rw-r--r--source/Syntax/Adapt.hs66
-rw-r--r--source/Syntax/Concrete.hs259
-rw-r--r--source/Syntax/Internal.hs30
7 files changed, 367 insertions, 283 deletions
diff --git a/source/Checking.hs b/source/Checking.hs
index 449102f..63ab99c 100644
--- a/source/Checking.hs
+++ b/source/Checking.hs
@@ -391,9 +391,9 @@ checkAxiom (Axiom asms axiom) = addFactWithAsms asms axiom
checkProof :: Proof -> Checking
checkProof = \case
- Qed JustificationEmpty->
+ Qed pos JustificationEmpty->
tellTasks
- Qed JustificationSetExt -> do
+ Qed pos JustificationSetExt -> do
goals <- gets checkingGoals
case goals of
[goal] -> do
@@ -402,11 +402,11 @@ checkProof = \case
tellTasks
[] -> pure ()
_ -> throwWithMarker (MismatchedSetExt goals)
- Qed (JustificationRef ms) ->
+ Qed pos (JustificationRef ms) ->
byRef ms
- Qed JustificationLocal ->
+ Qed pos JustificationLocal ->
byAssumption
- ByContradiction proof -> do
+ ByContradiction pos proof -> do
goals <- gets checkingGoals
case goals of
[goal] -> do
@@ -414,11 +414,11 @@ checkProof = \case
byContradiction
checkProof proof
_ -> throwWithMarker ByContradictionOnMultipleGoals
- ByCase splits -> do
+ ByCase pos splits -> do
for_ splits checkCase
setGoals [makeDisjunction (caseOf <$> splits)]
tellTasks
- BySetInduction mx continue -> do
+ BySetInduction pos mx continue -> do
goals <- gets checkingGoals
case goals of
Forall scope : goals' -> do
@@ -442,7 +442,7 @@ checkProof = \case
_ -> do
m <- gets blockLabel
throwIO (BySetInductionSyntacticMismatch m)
- ByOrdInduction continue -> do
+ ByOrdInduction pos continue -> do
goals <- gets checkingGoals
case goals of
Forall scope : goals' -> case fromScope scope of
@@ -463,52 +463,52 @@ checkProof = \case
checkProof continue
_ -> error ("could not match transfinite induction with syntactic structure of the first goal: " <> show goals)
_ -> error ("the first goal must be universally quantifier to apply transfinite induction: " <> show goals)
- Assume phi continue -> do
+ Assume pos phi continue -> do
goals' <- matchAssumptionWithGoal phi
assume [Asm phi]
setGoals goals'
checkProof continue
- Fix xs suchThat continue -> do
+ Fix pos xs suchThat continue -> do
fixing xs
checkProof case suchThat of
Top -> continue
- _ -> Assume suchThat continue
- Subclaim subclaim subproof continue -> do
+ _ -> Assume pos suchThat continue
+ Subclaim pos subclaim subproof continue -> do
locally (checkLemmaWithProof (Lemma [] subclaim) subproof)
assume [Asm subclaim]
checkProof continue
Omitted -> do
setGoals []
- Suffices reduction by proof -> do
+ Suffices pos reduction by proof -> do
goals <- gets checkingGoals
setGoals [reduction `Implies` makeConjunction goals]
justify by
setGoals [reduction]
checkProof proof
- Take _witnesses _suchThat JustificationSetExt _continue ->
- error "cannot justify existential statement with setext"
- Take witnesses suchThat by continue -> locally do
+ Take pos _witnesses _suchThat JustificationSetExt _continue ->
+ error $ "Error at " <> show pos <> "\nCannot justify existential statement with setext"
+ Take pos witnesses suchThat by continue -> locally do
goals <- gets checkingGoals
setGoals [makeExists witnesses suchThat]
justify by
assume [Asm suchThat]
setGoals goals
checkProof continue
- Have claim (JustificationRef ms) continue -> locally do
+ Have pos claim (JustificationRef ms) continue -> locally do
goals <- gets checkingGoals
setGoals [claim]
byRef ms -- locally prove things with just refs and local assumptions
assume [Asm claim]
setGoals goals
checkProof continue
- Have claim JustificationLocal continue -> locally do
+ Have pos claim JustificationLocal continue -> locally do
goals <- gets checkingGoals
setGoals [claim]
byAssumption -- locally prove things with just local assumptions
assume [Asm claim]
setGoals goals
checkProof continue
- Have claim by continue -> do
+ Have pos claim by continue -> do
locally do
goals <- gets checkingGoals
claims <- case by of
@@ -522,7 +522,7 @@ checkProof = \case
assume [Asm claim]
setGoals goals
checkProof continue
- Define x t continue -> locally do
+ Define pos x t continue -> locally do
assume [Asm case t of
TermSep y yBound phi ->
makeForall [y] $
@@ -533,7 +533,7 @@ checkProof = \case
_ -> Equals (TermVar x) t
]
checkProof continue
- DefineFunction funVar argVar valueExpr domExpr continue -> do
+ DefineFunction pos funVar argVar valueExpr domExpr continue -> do
-- we're given f, x, e, d
assume
[ Asm (TermOp DomSymbol [TermVar funVar] `Equals` domExpr) -- dom(f) = d
@@ -542,11 +542,11 @@ checkProof = \case
, Asm (relationNoun (TermVar funVar))
]
checkProof continue
- Calc quant calc continue -> do
+ Calc pos quant calc continue -> do
checkCalc quant calc
assume [Asm (calcResult quant calc)]
checkProof continue
- DefineFunctionLocal funVar argVar domVar ranExpr definitions continue -> do
+ DefineFunctionLocal pos funVar argVar domVar ranExpr definitions continue -> do
-- We have f: X \to Y and x \mapsto ...
-- definition is a nonempty list of (expresssion e, formula phi)
-- such that f(x) = e if phi(x)
diff --git a/source/Meaning.hs b/source/Meaning.hs
index 160640e..3bf2c9c 100644
--- a/source/Meaning.hs
+++ b/source/Meaning.hs
@@ -16,7 +16,7 @@ import Syntax.Internal (VarSymbol(..))
import Syntax.Internal qualified as Sem
import Syntax.LexicalPhrase (unsafeReadPhrase)
import Syntax.Lexicon
-
+import Text.Megaparsec.Pos
import Bound
import Bound.Scope (abstractEither)
@@ -325,7 +325,7 @@ forEach vs'' stmts = do
glossAdjL :: Raw.AdjL -> Gloss (Sem.Term -> Sem.Formula)
-glossAdjL (Raw.AdjL pat es) = do
+glossAdjL (Raw.AdjL pos pat es) = do
(es', quantifies) <- unzip <$> glossTerm `each` es
let quantify = compose $ reverse quantifies
pure $ \t -> quantify $ Sem.FormulaAdj t pat es'
@@ -336,10 +336,10 @@ glossAdjL (Raw.AdjL pat es) = do
-- the term representing the subject, hence the parameter 'Sem.Expr'.
glossAdjR :: Raw.AdjR -> Gloss (Sem.Term -> Sem.Formula)
glossAdjR = \case
- Raw.AdjR pat [e] | pat == unsafeReadPhrase "equal to ?" -> do
+ Raw.AdjR pos pat [e] | pat == unsafeReadPhrase "equal to ?" -> do
(e', quantify) <- glossTerm e
pure $ \t -> quantify $ Sem.Equals t e'
- Raw.AdjR pat es -> do
+ Raw.AdjR pos pat es -> do
(es', quantifies) <- unzip <$> glossTerm `each` es
let quantify = compose $ reverse quantifies
pure $ \t -> quantify $ Sem.FormulaAdj t pat es'
@@ -348,10 +348,10 @@ glossAdjR = \case
glossAdj :: Raw.AdjOf Raw.Term -> Gloss (Sem.ExprOf VarSymbol -> Sem.Formula)
glossAdj adj = case adj of
- Raw.Adj pat [e] | pat == unsafeReadPhrase "equal to ?" -> do
+ Raw.Adj pos pat [e] | pat == unsafeReadPhrase "equal to ?" -> do
(e', quantify) <- glossTerm e
pure $ \t -> quantify $ Sem.Equals t e'
- Raw.Adj pat es -> do
+ Raw.Adj pos pat es -> do
(es', quantifies) <- unzip <$> glossTerm `each` es
let quantify = compose $ reverse quantifies
pure $ \t -> quantify $ Sem.FormulaAdj t pat es'
@@ -367,7 +367,7 @@ glossVP = \case
glossVerb :: Raw.Verb -> Gloss (Sem.Term -> Sem.Formula)
-glossVerb (Raw.Verb pat es) = do
+glossVerb (Raw.Verb pos pat es) = do
(es', quantifies) <- unzip <$> glossTerm `each` es
let quantify = compose $ reverse quantifies
pure $ \ t -> quantify $ Sem.FormulaVerb t pat es'
@@ -384,7 +384,7 @@ glossNoun (Raw.Noun pat es) = do
glossFun :: Raw.Fun -> Gloss (Sem.Term, Sem.Formula -> Sem.Formula)
-glossFun (Raw.Fun phrase es) = do
+glossFun (Raw.Fun pos phrase es) = do
(es', quantifies) <- unzip <$> glossTerm `each` es
let quantify = compose $ reverse quantifies
pure (Sem.TermSymbol (Sem.SymbolFun phrase) es', quantify)
@@ -396,11 +396,11 @@ glossTerm = \case
(, id) <$> glossExpr e
Raw.TermFun f ->
glossFun f
- Raw.TermIota x stmt -> do
+ Raw.TermIota pos x stmt -> do
stmt' <- glossStmt stmt
_TODO "glossTerm TermIota"
--pure (Sem.Iota x (abstract1 x stmt'), id)
- Raw.TermQuantified quantifier np -> do
+ Raw.TermQuantified quantifier pos np -> do
quantify <- glossQuantifier quantifier
(mkConstraint, maySuchThat) <- glossNPMaybe np
v <- freshVar
@@ -413,13 +413,13 @@ glossTerm = \case
glossStmt :: Raw.Stmt -> Gloss Sem.Formula
glossStmt = \case
Raw.StmtFormula f -> glossFormula f
- Raw.StmtNeg s -> Sem.Not <$> glossStmt s
+ Raw.StmtNeg pos s -> Sem.Not <$> glossStmt s
Raw.StmtVerbPhrase ts vp -> do
(ts', quantifies) <- NonEmpty.unzip <$> glossTerm `each` ts
vp' <- glossVP vp
let phi = Sem.makeConjunction (vp' <$> toList ts')
pure (compose quantifies phi)
- Raw.StmtNoun ts np -> do
+ Raw.StmtNoun pos ts np -> do
(ts', quantifies) <- NonEmpty.unzip <$> glossTerm `each` ts
(np', maySuchThat) <- glossNPMaybe np
let andSuchThat phi = case maySuchThat of
@@ -427,19 +427,19 @@ glossStmt = \case
Nothing -> phi
psi = Sem.makeConjunction (andSuchThat . np' <$> toList ts')
pure (compose quantifies psi)
- Raw.StmtStruct t sp -> do
+ Raw.StmtStruct pos t sp -> do
(t', quantify) <- glossTerm t
pure (quantify (Sem.TermSymbol (Sem.SymbolPredicate (Sem.PredicateNounStruct sp)) [t']))
- Raw.StmtConnected conn s1 s2 -> glossConnective conn <*> glossStmt s1 <*> glossStmt s2
- Raw.StmtQuantPhrase (Raw.QuantPhrase quantifier np) f -> do
+ Raw.StmtConnected conn mpos s1 s2 -> glossConnective conn <*> glossStmt s1 <*> glossStmt s2
+ Raw.StmtQuantPhrase pos (Raw.QuantPhrase quantifier np) f -> do
(vars, constraints) <- glossNPList np
f' <- glossStmt f
quantify <- glossQuantifier quantifier
pure (quantify vars [constraints] f')
- Raw.StmtExists np -> do
+ Raw.StmtExists pos np -> do
(vars, constraints) <- glossNPList np
pure (Sem.makeExists vars constraints)
- Raw.SymbolicQuantified quant vs bound suchThat have -> do
+ Raw.SymbolicQuantified pos quant vs bound suchThat have -> do
quantify <- glossQuantifier quant
bound' <- glossBound bound
suchThatConstraints <- maybeToList <$> glossStmt `each` suchThat
@@ -547,11 +547,11 @@ glossLemma (Raw.Lemma asms f) = Sem.Lemma <$> glossAsms asms <*> glossStmt f
glossDefn :: Raw.Defn -> Gloss Sem.Defn
glossDefn = \case
Raw.Defn asms h f -> glossDefnHead h <*> glossAsms asms <*> glossStmt f
- Raw.DefnFun asms (Raw.Fun fun vs) _ e -> do
+ Raw.DefnFun asms (Raw.Fun pos fun vs) _ e -> do
asms' <- glossAsms asms
e' <- case e of
-- TODO improve error handling or make grammar stricter
- Raw.TermQuantified _ _ -> error $ "Quantified term in definition: " <> show e
+ Raw.TermQuantified _ p _ -> error $ "Quantified term in definition at" <> sourcePosPretty p <> " : " <> show e
_ -> fst <$> glossTerm e
pure $ Sem.DefnFun asms' fun vs e'
Raw.DefnOp (Raw.SymbolPattern op vs) e ->
@@ -563,13 +563,13 @@ glossDefn = \case
glossDefnHead :: Raw.DefnHead -> Gloss ([Sem.Asm] -> Sem.Formula -> Sem.Defn)
glossDefnHead = \case
-- TODO add info from NP.
- Raw.DefnAdj _mnp v (Raw.Adj adj vs) -> do
+ Raw.DefnAdj _mnp v (Raw.Adj pos 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 verb vs) ->
+ Raw.DefnVerb _mnp v (Raw.Verb pos verb vs) ->
pure $ \asms f -> Sem.DefnPredicate asms (Sem.PredicateVerb verb) (v :| vs) f
Raw.DefnNoun v (Raw.Noun noun vs) ->
pure $ \asms f -> Sem.DefnPredicate asms (Sem.PredicateNoun noun) (v :| vs) f
@@ -587,66 +587,66 @@ glossProof :: Raw.Proof -> Gloss Sem.Proof
glossProof = \case
Raw.Omitted ->
pure Sem.Omitted
- Raw.Qed by ->
- pure (Sem.Qed by)
- Raw.ByContradiction proof ->
- Sem.ByContradiction <$> glossProof proof
- Raw.BySetInduction mt proof ->
- Sem.BySetInduction <$> mmt' <*> glossProof proof
+ Raw.Qed pos by ->
+ pure (Sem.Qed pos by)
+ Raw.ByContradiction pos proof ->
+ Sem.ByContradiction pos <$> glossProof proof
+ Raw.BySetInduction pos mt proof ->
+ Sem.BySetInduction pos <$> 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
- Raw.ByOrdInduction proof ->
- Sem.ByOrdInduction <$> glossProof proof
- Raw.ByCase cases -> Sem.ByCase <$> glossCase `each` cases
- Raw.Have _ms s by proof -> case s of
+ Raw.ByOrdInduction pos proof ->
+ Sem.ByOrdInduction pos <$> glossProof proof
+ Raw.ByCase pos cases -> Sem.ByCase pos <$> glossCase `each` cases
+ Raw.Have pos _ms s by proof -> case s of
-- Pragmatics: an existential @Have@ implicitly
-- introduces the witness and is interpreted as a @Take@ construct.
- Raw.SymbolicExists vs bound suchThat -> do
+ Raw.SymbolicExists pos vs bound suchThat -> do
bound' <- glossBound bound
suchThat' <- glossStmt suchThat
proof' <- glossProof proof
- pure (Sem.Take vs (Sem.makeConjunction (suchThat' : bound' (toList vs))) by proof')
+ pure (Sem.Take pos vs (Sem.makeConjunction (suchThat' : bound' (toList vs))) by proof')
_otherwise ->
- Sem.Have <$> glossStmt s <*> pure by <*> glossProof proof
- Raw.Assume stmt proof ->
- Sem.Assume <$> glossStmt stmt <*> glossProof proof
- Raw.FixSymbolic xs bound proof -> do
+ Sem.Have pos <$> glossStmt s <*> pure by <*> glossProof proof
+ Raw.Assume pos stmt proof ->
+ Sem.Assume pos <$> glossStmt stmt <*> glossProof proof
+ Raw.FixSymbolic pos xs bound proof -> do
bound' <- glossBound bound
proof' <- glossProof proof
- pure (Sem.Fix xs (Sem.makeConjunction (bound' (toList xs))) proof')
- Raw.FixSuchThat xs stmt proof -> do
+ pure (Sem.Fix pos xs (Sem.makeConjunction (bound' (toList xs))) proof')
+ Raw.FixSuchThat pos xs stmt proof -> do
stmt' <- glossStmt stmt
proof' <- glossProof proof
- pure (Sem.Fix xs stmt' proof')
- Raw.TakeVar vs bound suchThat by proof -> do
+ pure (Sem.Fix pos xs stmt' proof')
+ Raw.TakeVar pos vs bound suchThat by proof -> do
bound' <- glossBound bound
suchThat' <- glossStmt suchThat
proof' <- glossProof proof
- pure (Sem.Take vs (Sem.makeConjunction (suchThat' : bound' (toList vs))) by proof')
- Raw.TakeNoun np by proof -> do
+ pure (Sem.Take pos vs (Sem.makeConjunction (suchThat' : bound' (toList vs))) by proof')
+ Raw.TakeNoun pos np by proof -> do
(vs, constraints) <- glossNPList np
proof' <- glossProof proof
- pure $ Sem.Take vs constraints by proof'
- Raw.Subclaim subclaim subproof proof ->
- Sem.Subclaim <$> glossStmt subclaim <*> glossProof subproof <*> glossProof proof
- Raw.Suffices reduction by proof ->
- Sem.Suffices <$> glossStmt reduction <*> pure by <*> glossProof proof
- Raw.Define var term proof ->
- Sem.Define var <$> glossExpr term <*> glossProof proof
- Raw.DefineFunction funVar argVar valueExpr domVar domExpr proof ->
+ pure $ Sem.Take pos vs constraints by proof'
+ Raw.Subclaim pos subclaim subproof proof ->
+ Sem.Subclaim pos <$> glossStmt subclaim <*> glossProof subproof <*> glossProof proof
+ Raw.Suffices pos reduction by proof ->
+ Sem.Suffices pos <$> glossStmt reduction <*> pure by <*> glossProof proof
+ Raw.Define pos var term proof ->
+ Sem.Define pos var <$> glossExpr term <*> glossProof proof
+ Raw.DefineFunction pos funVar argVar valueExpr domVar domExpr proof ->
if domVar == argVar
- then Sem.DefineFunction funVar argVar <$> glossExpr valueExpr <*> glossExpr domExpr <*> glossProof proof
+ then Sem.DefineFunction pos funVar argVar <$> glossExpr valueExpr <*> glossExpr domExpr <*> glossProof proof
else error "mismatched variables in function definition."
- Raw.DefineFunctionLocal funVar domVar ranExpr funVar2 argVar definitions proof -> do
+ Raw.DefineFunctionLocal pos funVar domVar ranExpr funVar2 argVar definitions proof -> do
if funVar == funVar2
- then Sem.DefineFunctionLocal funVar argVar domVar <$> glossExpr ranExpr <*> (glossLocalFunctionExprDef `each` definitions) <*> glossProof proof
+ then Sem.DefineFunctionLocal pos funVar argVar domVar <$> glossExpr ranExpr <*> (glossLocalFunctionExprDef `each` definitions) <*> glossProof proof
else error "missmatched function names"
- Raw.Calc calcQuant calc proof ->
- Sem.Calc <$> glossCalcQuantifier calcQuant <*> glossCalc calc <*> glossProof proof
+ Raw.Calc pos calcQuant calc proof ->
+ Sem.Calc pos <$> glossCalcQuantifier calcQuant <*> glossCalc calc <*> glossProof proof
glossCalcQuantifier :: Maybe Raw.CalcQuantifier -> Gloss Sem.CalcQuantifier
glossCalcQuantifier Nothing = pure Sem.CalcUnquantified
@@ -680,9 +680,9 @@ glossCalc = \case
glossSignature :: Raw.Signature -> Gloss Sem.Signature
glossSignature sig = case sig of
- Raw.SignatureAdj v (Raw.Adj adj vs) ->
+ Raw.SignatureAdj v (Raw.Adj pos adj vs) ->
pure $ Sem.SignaturePredicate (Sem.PredicateAdj adj) (v :| vs)
- Raw.SignatureVerb v (Raw.Verb verb vs) ->
+ Raw.SignatureVerb v (Raw.Verb pos verb vs) ->
pure $ Sem.SignaturePredicate (Sem.PredicateVerb verb) (v :| vs)
Raw.SignatureNoun v (Raw.Noun noun vs) ->
pure $ Sem.SignaturePredicate (Sem.PredicateNoun noun) (v :| vs)
@@ -717,15 +717,15 @@ annotateCarrierFormula lbl = \case
glossAbbreviation :: Raw.Abbreviation -> Gloss Sem.Abbreviation
glossAbbreviation = \case
- Raw.AbbreviationAdj x (Raw.Adj adj xs) stmt ->
+ Raw.AbbreviationAdj x (Raw.Adj pos adj xs) stmt ->
makeAbbrStmt (Sem.SymbolPredicate (Sem.PredicateAdj adj)) (x : xs) stmt
- Raw.AbbreviationVerb x (Raw.Verb verb xs) stmt ->
+ Raw.AbbreviationVerb x (Raw.Verb pos verb xs) stmt ->
makeAbbrStmt (Sem.SymbolPredicate (Sem.PredicateVerb verb)) (x : xs) stmt
Raw.AbbreviationNoun x (Raw.Noun noun xs) stmt ->
makeAbbrStmt (Sem.SymbolPredicate (Sem.PredicateNoun noun)) (x : xs) stmt
Raw.AbbreviationRel x rel params y stmt ->
makeAbbrStmt (Sem.SymbolPredicate (Sem.PredicateRelation rel)) (params <> [x, y]) stmt
- Raw.AbbreviationFun (Raw.Fun fun xs) t ->
+ Raw.AbbreviationFun (Raw.Fun pos fun xs) t ->
makeAbbrTerm (Sem.SymbolFun fun) xs t
Raw.AbbreviationEq (Raw.SymbolPattern op xs) e ->
makeAbbrExpr (Sem.SymbolMixfix op) xs e
diff --git a/source/Report/Location.hs b/source/Report/Location.hs
new file mode 100644
index 0000000..bcc575e
--- /dev/null
+++ b/source/Report/Location.hs
@@ -0,0 +1,26 @@
+module Report.Location where
+
+import Base
+import Text.Megaparsec.Pos
+
+
+
+class Locatable a where
+ locate :: a -> SourcePos
+
+nowhere :: SourcePos
+nowhere = initialPos "Nowhere"
+
+instance Locatable SourcePos where
+ locate = id
+
+instance Locatable a => Locatable [a] where
+ locate [] = nowhere
+ locate (x:_) = locate x
+
+instance Locatable a => Locatable (Maybe a) where
+ locate Nothing = nowhere
+ locate (Just x) = locate x
+
+instance Locatable a => Locatable (NonEmpty a) where
+ locate (x :| _) = locate x
diff --git a/source/Syntax/Abstract.hs b/source/Syntax/Abstract.hs
index ebbf9e9..00e43ca 100644
--- a/source/Syntax/Abstract.hs
+++ b/source/Syntax/Abstract.hs
@@ -3,7 +3,8 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE StandaloneDeriving #-}
-
+{-# LANGUAGE OverloadedRecordDot #-}
+{-# LANGUAGE DuplicateRecordFields #-}
-- | Data types for the abstract syntax tree and helper functions
-- for constructing the lexicon.
@@ -18,6 +19,7 @@ module Syntax.Abstract
import Base
import Syntax.LexicalPhrase (LexicalPhrase, SgPl(..), unsafeReadPhraseSgPl, unsafeReadPhrase)
import Syntax.Token (Token(..))
+import Report.Location
import Text.Earley.Mixfix (Holey)
import Data.Text qualified as Text
@@ -32,6 +34,8 @@ data VarSymbol
instance IsString VarSymbol where
fromString v = NamedVar $ Text.pack v
+instance Locatable VarSymbol where
+ locate _ = nowhere -- TODO more info?
data Expr
= ExprVar VarSymbol
@@ -199,7 +203,7 @@ data Nameless a = Nameless deriving (Show, Eq, Ord)
-- e.g. /@even@/, /@continuous@/, and /@σ-finite@/.
type AdjL = AdjLOf Term
data AdjLOf a
- = AdjL LexicalPhrase [a]
+ = AdjL SourcePos LexicalPhrase [a]
deriving (Show, Eq, Ord)
@@ -210,29 +214,32 @@ data AdjLOf a
-- by an additional such-that phrase.
type AdjR = AdjROf Term
data AdjROf a
- = AdjR LexicalPhrase [a]
+ = AdjR SourcePos LexicalPhrase [a]
| AttrRThat VerbPhrase
deriving (Show, Eq, Ord)
+instance Locatable (AdjROf a) where
+ locate (AdjR p _ _) = p
+ locate (AttrRThat vp) = nowhere -- TODO
-- | Adjectives for parts of the AST where adjectives are not used
-- to modify nouns and the L/R distinction does not matter, such as
-- when then are used together with a copula (like /@n is even@/).
type Adj = AdjOf Term
data AdjOf a
- = Adj LexicalPhrase [a]
+ = Adj SourcePos LexicalPhrase [a]
deriving (Show, Eq, Ord)
type Verb = VerbOf Term
data VerbOf a
- = Verb (SgPl LexicalPhrase) [a]
+ = Verb SourcePos (SgPl LexicalPhrase) [a]
deriving (Show, Eq, Ord)
type Fun = FunOf Term
data FunOf a
- = Fun (SgPl LexicalPhrase) [a]
+ = Fun {pos :: SourcePos, phrase :: SgPl LexicalPhrase, funArgs :: [a]}
deriving (Show, Eq, Ord)
@@ -259,35 +266,49 @@ data Term
-- ^ A symbolic expression.
| TermFun Fun
-- ^ Definite noun phrase, e.g. /@the derivative of $f$@/.
- | TermIota VarSymbol Stmt
+ | TermIota SourcePos VarSymbol Stmt
-- ^ Definite descriptor, e.g. /@an $x$ such that ...@//
- | TermQuantified Quantifier (NounPhrase Maybe)
+ | TermQuantified Quantifier SourcePos (NounPhrase Maybe)
-- ^ Indefinite quantified notion, e.g. /@every even integer that divides $k$ ...@/.
deriving (Show, Eq, Ord)
+instance Locatable Term where
+ locate :: Term -> SourcePos
+ locate (TermExpr _) = nowhere -- TODO
+ locate (TermFun f) = f.pos
+ locate (TermIota p _ _) = p
+ locate (TermQuantified _ p _) = p
+
data Stmt
- = StmtFormula Formula -- ^ E.g.: /@We have \<Formula\>@/.
- | StmtVerbPhrase (NonEmpty Term) VerbPhrase -- ^ E.g.: /@\<Term\> and \<Term\> \<verb\>@/.
- | StmtNoun (NonEmpty Term) (NounPhrase Maybe) -- ^ E.g.: /@\<Term\> is a(n) \<NP\>@/.
- | StmtStruct Term StructPhrase
- | StmtNeg Stmt -- ^ E.g.: /@It is not the case that \<Stmt\>@/.
- | StmtExists (NounPhrase []) -- ^ E.g.: /@There exists a(n) \<NP\>@/.
- | StmtConnected Connective Stmt Stmt
- | StmtQuantPhrase QuantPhrase Stmt
- | SymbolicQuantified Quantifier (NonEmpty VarSymbol) Bound (Maybe Stmt) Stmt
+ = StmtFormula {formula :: Formula} -- ^ E.g.: /@We have \<Formula\>@/.
+ | StmtVerbPhrase {args :: NonEmpty Term, verb :: VerbPhrase} -- ^ E.g.: /@\<Term\> and \<Term\> \<verb\>@/.
+ | StmtNoun {pos :: SourcePos, args :: NonEmpty Term, noun :: (NounPhrase Maybe)} -- ^ E.g.: /@\<Term\> is a(n) \<NP\>@/.
+ | StmtStruct {pos :: SourcePos, arg :: Term, struct :: StructPhrase}
+ | StmtNeg {pos :: SourcePos, stmt :: Stmt} -- ^ E.g.: /@It is not the case that \<Stmt\>@/.
+ | StmtExists {pos :: SourcePos, np :: NounPhrase []} -- ^ E.g.: /@There exists a(n) \<NP\>@/.
+ | StmtConnected {conn :: Connective, mpos :: Maybe SourcePos, stmt1 :: Stmt, stmt2 :: Stmt}
+ | StmtQuantPhrase {pos :: SourcePos, qp :: QuantPhrase, stmt :: Stmt}
+ | SymbolicQuantified {pos :: SourcePos, quant :: Quantifier, xs :: NonEmpty VarSymbol, b :: Bound, suchThat :: Maybe Stmt, stmt :: Stmt}
deriving (Show, Eq, Ord)
+instance Locatable Stmt where
+ locate :: Stmt -> SourcePos
+ locate (StmtFormula _) = nowhere -- TODO
+ locate StmtConnected{mpos = Nothing, stmt1 = s} = locate s
+ locate StmtVerbPhrase{args = a :| _} = locate a
+ locate s = s.pos
+
data Bound = Unbounded | Bounded Sign Relation Expr deriving (Show, Eq, Ord)
-pattern SymbolicForall :: NonEmpty VarSymbol -> Bound -> Maybe Stmt -> Stmt -> Stmt
-pattern SymbolicForall vs bound suchThat have = SymbolicQuantified Universally vs bound suchThat have
+pattern SymbolicForall :: SourcePos -> NonEmpty VarSymbol -> Bound -> Maybe Stmt -> Stmt -> Stmt
+pattern SymbolicForall pos vs bound suchThat have = SymbolicQuantified pos Universally vs bound suchThat have
-pattern SymbolicExists :: NonEmpty VarSymbol -> Bound -> Stmt -> Stmt
-pattern SymbolicExists vs bound suchThat = SymbolicQuantified Existentially vs bound Nothing suchThat
+pattern SymbolicExists :: SourcePos -> NonEmpty VarSymbol -> Bound -> Stmt -> Stmt
+pattern SymbolicExists pos vs bound suchThat = SymbolicQuantified pos Existentially vs bound Nothing suchThat
-pattern SymbolicNotExists :: NonEmpty VarSymbol -> Bound -> Stmt -> Stmt
-pattern SymbolicNotExists vs bound suchThat = StmtNeg (SymbolicExists vs bound suchThat)
+makeSymbolicNotExists :: SourcePos -> NonEmpty VarSymbol -> Bound -> Stmt -> Stmt
+makeSymbolicNotExists p vs bound st = StmtNeg p (SymbolicExists p vs bound st)
data Asm
= AsmSuppose Stmt
@@ -344,32 +365,32 @@ data CalcQuantifier
data Proof
= Omitted
- | Qed Justification
+ | Qed (Maybe SourcePos) Justification
-- ^ Ends of a proof, leaving automation to discharge the current goal using the given justification.
- | ByCase [Case]
- | ByContradiction Proof
- | BySetInduction (Maybe Term) Proof
+ | ByCase SourcePos [Case]
+ | ByContradiction SourcePos Proof
+ | BySetInduction SourcePos (Maybe Term) Proof
-- ^ ∈-induction.
- | ByOrdInduction Proof
+ | ByOrdInduction SourcePos Proof
-- ^ Transfinite induction for ordinals.
- | Assume Stmt Proof
- | FixSymbolic (NonEmpty VarSymbol) Bound Proof
- | FixSuchThat (NonEmpty VarSymbol) Stmt Proof
- | Calc (Maybe CalcQuantifier) Calc Proof
+ | Assume SourcePos Stmt Proof
+ | FixSymbolic SourcePos (NonEmpty VarSymbol) Bound Proof
+ | FixSuchThat SourcePos (NonEmpty VarSymbol) Stmt Proof
+ | Calc SourcePos (Maybe CalcQuantifier) Calc Proof
-- ^ Simplify goals that are implications or disjunctions.
- | TakeVar (NonEmpty VarSymbol) Bound Stmt Justification Proof
- | TakeNoun (NounPhrase []) Justification Proof
- | Have (Maybe Stmt) Stmt Justification Proof
+ | TakeVar SourcePos (NonEmpty VarSymbol) Bound Stmt Justification Proof
+ | TakeNoun SourcePos (NounPhrase []) Justification Proof
+ | Have SourcePos (Maybe Stmt) Stmt Justification Proof
-- ^ /@Since \<stmt\>, we have \<stmt\> by \<ref\>.@/
- | Suffices Stmt Justification Proof
+ | Suffices SourcePos Stmt Justification Proof
-- ^ /@It suffices to show that [...]. [...]@/
- | Subclaim Stmt Proof Proof
+ | Subclaim SourcePos Stmt Proof Proof
-- ^ A claim is a sublemma with its own proof:
-- /@Show \<goal stmt\>. \<steps\>. \<continue other proof\>.@/
- | Define VarSymbol Expr Proof
+ | Define SourcePos VarSymbol Expr Proof
-- ^ Local definition.
--
- | DefineFunction VarSymbol VarSymbol Expr VarSymbol Expr Proof
+ | DefineFunction SourcePos VarSymbol VarSymbol Expr VarSymbol Expr Proof
-- ^ Local function definition, e.g. /@Let $f(x) = e$ for $x\\in d$@/.
-- The first 'VarSymbol' is the newly defined symbol, the second one is the argument.
-- The first 'Expr' is the value, the final variable and expr specify a bound (the domain of the function).
@@ -377,7 +398,7 @@ data Proof
- | DefineFunctionLocal VarSymbol VarSymbol Expr VarSymbol VarSymbol (NonEmpty (Expr, Formula)) Proof
+ | DefineFunctionLocal SourcePos VarSymbol VarSymbol Expr VarSymbol VarSymbol (NonEmpty (Expr, Formula)) Proof
-- ^ Local function definition, but in this case we give the domain and target an the rules for $xs$ in some sub domains.
--
deriving (Show, Eq, Ord)
diff --git a/source/Syntax/Adapt.hs b/source/Syntax/Adapt.hs
index 77f80d6..fbfbdef 100644
--- a/source/Syntax/Adapt.hs
+++ b/source/Syntax/Adapt.hs
@@ -32,7 +32,7 @@ scanChunk ltoks =
Located{startPos = pos, unLocated = BeginEnv "abbreviation"} : _ ->
matchOrErr abbreviation "abbreviation" pos
Located{startPos = pos, unLocated = (BeginEnv "struct")} :_ ->
- matchOrErr struct "struct definition" pos
+ matchOrErr structRE "struct definition" pos
Located{startPos = pos, unLocated = (BeginEnv "inductive")} :_ ->
matchOrErr inductive "inductive definition" pos
_ -> []
@@ -66,9 +66,9 @@ definition :: RE Token [ScannedLexicalItem]
definition = do
sym (BeginEnv "definition")
few notEndOfLexicalEnvToken
- m <- label
+ m <- labelRE
few anySym
- lexicalItem <- head
+ lexicalItem <- headRE
few anySym
sym (EndEnv "definition")
skipUntilNextLexicalEnv
@@ -78,9 +78,9 @@ abbreviation :: RE Token [ScannedLexicalItem]
abbreviation = do
sym (BeginEnv "abbreviation")
few anySym
- m <- label
+ m <- labelRE
few anySym
- lexicalItem <- head
+ lexicalItem <- headRE
few anySym
sym (EndEnv "abbreviation")
skipUntilNextLexicalEnv
@@ -90,9 +90,9 @@ signatureExtension :: RE Token [ScannedLexicalItem]
signatureExtension = do
sym (BeginEnv "signature")
few notEndOfLexicalEnvToken
- m <- label
+ m <- labelRE
few anySym
- lexicalItem <- head
+ lexicalItem <- headRE
few anySym
sym (EndEnv "signature")
skipUntilNextLexicalEnv
@@ -102,7 +102,7 @@ signatureExtensionAtom :: RE Token [ScannedLexicalItem]
signatureExtensionAtom = do
sym (BeginEnv "signatureatom")
few notEndOfLexicalEnvToken
- m <- label
+ m <- labelRE
few anySym
lexicalItem <- sigPred
few anySym
@@ -110,22 +110,22 @@ signatureExtensionAtom = do
skipUntilNextLexicalEnv
pure [lexicalItem m]
-label :: RE Token Marker
-label = msym \case
+labelRE :: RE Token Marker
+labelRE = msym \case
Label m -> Just (Marker m)
_ -> Nothing
-- | 'RE' that matches the head of a definition.
-head :: RE Token (Marker -> ScannedLexicalItem)
+headRE :: RE Token (Marker -> ScannedLexicalItem)
-- Note that @<|>@ is left biased for 'RE', so we can just
-- place 'adj' before 'verb' and do not have to worry about
-- overlapping patterns.
-head = ScanNoun <$> noun
- <|> ScanAdj <$> adj
- <|> ScanVerb <$> verb
- <|> ScanFun <$> fun
- <|> ScanRelationSymbol . fst <$> relationSymbol
- <|> ScanFunctionSymbol <$> functionSymbol
+headRE = ScanNoun <$> nounRE
+ <|> ScanAdj <$> adjRE
+ <|> ScanVerb <$> verbRE
+ <|> ScanFun <$> funRE
+ <|> ScanRelationSymbol . fst <$> relationSymbolRE
+ <|> ScanFunctionSymbol <$> functionSymbolRE
<|> ScanPrefixPredicate <$> prefixPredicate
sigPred :: RE Token (Marker -> ScannedLexicalItem)
@@ -137,7 +137,7 @@ inductive :: RE Token [ScannedLexicalItem]
inductive = do
sym (BeginEnv "inductive")
few notEndOfLexicalEnvToken
- m <- label
+ m <- labelRE
few anySym
lexicalItem <- functionSymbolInductive
few anySym
@@ -145,11 +145,11 @@ inductive = do
skipUntilNextLexicalEnv
pure [ScanFunctionSymbol lexicalItem m]
-struct :: RE Token [ScannedLexicalItem]
-struct = do
+structRE :: RE Token [ScannedLexicalItem]
+structRE = do
sym (BeginEnv "struct")
few anySym
- m <- label
+ m <- labelRE
few anySym
lexicalItem <- ScanStructNoun . toLexicalPhrase <$> (an *> structPat <* math var)
few anySym
@@ -172,20 +172,20 @@ structOp = do
op <- math command
pure (ScanStructOp op)
-noun :: RE Token LexicalPhrase
-noun = toLexicalPhrase <$> (math var *> is *> an *> pat <* iff)
+nounRE :: RE Token LexicalPhrase
+nounRE = toLexicalPhrase <$> (math var *> is *> an *> pat <* iff)
-adj :: RE Token LexicalPhrase
-adj = toLexicalPhrase <$> (math var *> is *> pat <* iff)
+adjRE :: RE Token LexicalPhrase
+adjRE = toLexicalPhrase <$> (math var *> is *> pat <* iff)
-verb :: RE Token LexicalPhrase
-verb = toLexicalPhrase <$> (math var *> pat <* iff)
+verbRE :: RE Token LexicalPhrase
+verbRE = toLexicalPhrase <$> (math var *> pat <* iff)
-fun :: RE Token LexicalPhrase
-fun = toLexicalPhrase <$> (the *> pat <* (is <|> comma))
+funRE :: RE Token LexicalPhrase
+funRE = toLexicalPhrase <$> (the *> pat <* (is <|> comma))
-relationSymbol :: RE Token (RelationSymbol, Int)
-relationSymbol = do
+relationSymbolRE :: RE Token (RelationSymbol, Int)
+relationSymbolRE = do
beginMath
var
rel <- symbol
@@ -200,8 +200,8 @@ relationSymbol = do
vars <- many (sym InvisibleBraceL *> var <* sym InvisibleBraceR)
pure (length vars)
-functionSymbol :: RE Token FunctionSymbol
-functionSymbol = do
+functionSymbolRE :: RE Token FunctionSymbol
+functionSymbolRE = do
sym (BeginEnv "math")
toks <- few nonDefinitionKeyword
sym (Symbol "=")
diff --git a/source/Syntax/Concrete.hs b/source/Syntax/Concrete.hs
index ada6227..00f0574 100644
--- a/source/Syntax/Concrete.hs
+++ b/source/Syntax/Concrete.hs
@@ -10,6 +10,7 @@ import Syntax.Abstract
import Syntax.Concrete.Keywords
import Syntax.Lexicon (Lexicon(..), lexiconAdjs, splitOnVariableSlot)
import Syntax.Token
+import Report.Location
import Data.HashSet qualified as HS
import Data.List.NonEmpty qualified as NonEmpty
@@ -172,10 +173,10 @@ grammar lexicon@Lexicon{..} = mdo
termExpr <- rule $ TermExpr <$> math expr
termFun <- rule $ TermFun <$> (optional _the *> fun)
- termIota <- rule $ TermIota <$> (_the *> var) <* _suchThat <*> stmt
- termAll <- rule $ TermQuantified Universally <$> (_every *> nounPhraseMay)
- termSome <- rule $ TermQuantified Existentially <$> (_some *> nounPhraseMay)
- termNo <- rule $ TermQuantified Nonexistentially <$> (_no *> nounPhraseMay)
+ termIota <- rule $ TermIota <$> _the <*> var <* _suchThat <*> stmt
+ termAll <- rule $ TermQuantified Universally <$> _every <*> nounPhraseMay
+ termSome <- rule $ TermQuantified Existentially <$> _some <*> nounPhraseMay
+ termNo <- rule $ TermQuantified Nonexistentially <$> _no <*> nounPhraseMay
termQuantified <- rule $ termAll <|> termSome <|> termNo
term <- rule $ termExpr <|> termFun <|> termQuantified <|> termIota
@@ -186,51 +187,79 @@ grammar lexicon@Lexicon{..} = mdo
stmtVerbSg <- rule $ StmtVerbPhrase <$> singletonTerm <*> verbPhraseSg
stmtVerbPl <-rule $ StmtVerbPhrase <$> andList1 term <*> verbPhrasePl
stmtVerb <- rule $ stmtVerbSg <|> stmtVerbPl
- stmtNounIs <- rule $ StmtNoun <$> singletonTerm <* _is <* _an <*> nounPhrase
- stmtNounAre <- rule $ StmtNoun <$> (nonemptyTerms <* _are) <*> nounPhrasePlMay
- stmtNounIsNot <- rule $ StmtNeg <$> (StmtNoun <$> singletonTerm <* _is <* _not <* _an <*> nounPhrase)
- stmtNounAreNot <- rule $ StmtNeg <$> (StmtNoun <$> nonemptyTerms <* (_are *> _not) <*> nounPhrasePlMay)
+ stmtNounIs <- rule do
+ ts <- singletonTerm
+ np <- _is *> _an *> nounPhrase
+ pure let t :| _ = ts in (StmtNoun (locate t) ts np)
+ stmtNounAre <- rule do
+ ts <- nonemptyTerms <* _are
+ np <- nounPhrasePlMay
+ pure let t :| _ = ts in (StmtNoun (locate t) ts np)
+ stmtNounIsNot <- rule do
+ ts <- singletonTerm
+ np <- _is *> _not *> _an *> nounPhrase
+ pure let t :| _ = ts in (StmtNeg (locate t) (StmtNoun (locate t) ts np))
+ stmtNounAreNot <- rule do
+ ts <- nonemptyTerms
+ np <- _are *> _not *> nounPhrasePlMay
+ pure let t :| _ = ts in (StmtNeg (locate t) (StmtNoun (locate t) ts np))
stmtNoun <- rule $ stmtNounIs <|> stmtNounIsNot <|> stmtNounAre <|> stmtNounAreNot
- stmtStruct <- rule $ StmtStruct <$> (term <* _is <* _an) <*> structNounNameless
- stmtExists <- rule $ StmtExists <$> (_exists *> _an *> nounPhrase')
- stmtExist <- rule $ StmtExists <$> (_exist *> nounPhrasePl)
- stmtExistsNot <- rule $ StmtNeg . StmtExists <$> (_exists *> _no *> nounPhrase')
+ stmtStruct <- rule do
+ t <- term
+ s <- _is *> _an *> structNounNameless
+ pure (StmtStruct (locate t) t s)
+ stmtExists <- rule $ StmtExists <$> _exists <*> (_an *> nounPhrase')
+ stmtExist <- rule $ StmtExists <$> _exist <*> nounPhrasePl
+ stmtExistsNot <- rule do
+ p <- _exists *> _no
+ np <- nounPhrase'
+ pure (StmtNeg p (StmtExists p np))
stmtFormula <- rule $ StmtFormula <$> math formula
- stmtFormualNeg <- rule $ StmtNeg . StmtFormula <$> (_not *> math formula)
+ stmtFormualNeg <- rule do
+ p <- _not
+ phi <- math formula
+ pure (StmtNeg p (StmtFormula phi))
stmtBot <- rule $ StmtFormula (PropositionalConstant IsBottom) <$ _contradiction
stmt' <- rule $ stmtVerb <|> stmtNoun <|> stmtStruct <|> stmtFormula <|> stmtFormualNeg <|> stmtBot
- stmtOr <- rule $ stmt' <|> (StmtConnected Disjunction <$> stmt' <* _or <*> stmt)
- stmtAnd <- rule $ stmtOr <|> (StmtConnected Conjunction <$> stmtOr <* _and <*> stmt)
- stmtIff <- rule $ stmtAnd <|> (StmtConnected Equivalence <$> stmtAnd <* _iff <*> stmt)
- stmtIf <- rule $ StmtConnected Implication <$> (_if *> stmt) <* optional _comma <* _then <*> stmt
- stmtXor <- rule $ StmtConnected ExclusiveOr <$> (_either *> stmt) <* _or <*> stmt
- stmtNor <- rule $ StmtConnected NegatedDisjunction <$> (_neither *> stmt) <* _nor <*> stmt
- stmtNeg <- rule $ StmtNeg <$> (_itIsWrong *> stmt)
+ stmtOr <- rule $ stmt' <|> (StmtConnected Disjunction Nothing <$> stmt' <* _or <*> stmt)
+ stmtAnd <- rule $ stmtOr <|> (StmtConnected Conjunction Nothing <$> stmtOr <* _and <*> stmt)
+ stmtIff <- rule $ stmtAnd <|> (StmtConnected Equivalence Nothing <$> stmtAnd <* _iff <*> stmt)
+ stmtIf <- rule $ StmtConnected Implication <$> (Just <$> _if) <*> stmt <* optional _comma <* _then <*> stmt
+ stmtXor <- rule $ StmtConnected ExclusiveOr <$> (Just <$>_either) <*> stmt <* _or <*> stmt
+ stmtNor <- rule $ StmtConnected NegatedDisjunction <$> (Just <$> _neither) <*> stmt <* _nor <*> stmt
+ stmtNeg <- rule $ StmtNeg <$> _itIsWrong <*> stmt
- stmtQuantPhrase <- rule $ StmtQuantPhrase <$> (_for *> quant) <* optional _comma <* optional _have <*> stmt
+ stmtQuantPhrase <- rule $ StmtQuantPhrase <$> _for <*> quant <* optional _comma <* optional _have <*> stmt
suchStmt <- rule $ _suchThat *> stmt <* optional _comma
-- Symbolic quantifications with or without generalized bounds.
- symbolicForall <- rule $ SymbolicForall
- <$> ((_forAll <|> _forEvery) *> beginMath *> varSymbols)
- <*> maybeBounded <* endMath
- <*> optional suchStmt
- <* optional _have <*> stmt
- symbolicExists <- rule $ SymbolicExists
- <$> ((_exists <|> _exist) *> beginMath *> varSymbols)
- <*> maybeBounded <* endMath
- <*> ((_suchThat *> stmt) <|> pure (StmtFormula (PropositionalConstant IsTop)))
- symbolicNotExists <- rule $ SymbolicNotExists
- <$> (_exists *> _no *> beginMath *> varSymbols)
- <*> maybeBounded <* endMath
- <* _suchThat <*> stmt
+ symbolicForall <- rule do
+ p <- _forAll <|> _forEvery
+ xs <- beginMath *> varSymbols
+ b <- maybeBounded <* endMath
+ ms <- optional suchStmt
+ s <- optional _have *> stmt
+ pure (SymbolicForall p xs b ms s)
+ symbolicExists <- rule do
+ p <- _exists <|> _exist
+ xs <- beginMath *> varSymbols
+ b <- maybeBounded <* endMath
+ s <- (_suchThat *> stmt) <|> pure (StmtFormula (PropositionalConstant IsTop))
+ pure (SymbolicExists p xs b s)
+ symbolicNotExists <- rule do
+ p <- _exists *> _no
+ xs <- beginMath *> varSymbols
+ b <- maybeBounded <* endMath
+ s <- _suchThat *> stmt
+ pure (makeSymbolicNotExists p xs b s)
symbolicBound <- rule $ Bounded <$> relationSign <*> relation <*> expr
maybeBounded <- rule (pure Unbounded <|> symbolicBound)
symbolicQuantified <- rule $ symbolicForall <|> symbolicExists <|> symbolicNotExists
- stmt <- rule $ asum [stmtNeg, stmtIf, stmtXor, stmtNor, stmtExists, stmtExist, stmtExistsNot, stmtQuantPhrase, stmtIff, symbolicQuantified] <?> "a statement"
+ stmt :: Prod r Text (Located Token) Stmt <- rule $ asum [stmtNeg, stmtIf, stmtXor, stmtNor, stmtExists, stmtExist, stmtExistsNot, stmtQuantPhrase, stmtIff, symbolicQuantified] <?> "a statement"
+
asmLetIn <- rule $ uncurry AsmLetIn <$> (_let *> math typing)
asmLetNoun <- rule $ AsmLetNoun <$> (_let *> fmap pure var <* (_be <|> _denote) <* _an) <*> nounPhrase
@@ -315,10 +344,10 @@ grammar lexicon@Lexicon{..} = mdo
justificationLocal <- rule $ JustificationLocal <$ (_by *> (_assumption <|> _definition))
justification <- rule (justificationSet <|> justificationRef <|> justificationLocal <|> pure JustificationEmpty)
- trivial <- rule $ Qed JustificationEmpty <$ _trivial <* _dot
+ trivial <- rule $ Qed . Just <$> _trivial <* _dot <*> pure JustificationEmpty
omitted <- rule $ Omitted <$ _omitted <* _dot
- qedJustified <- rule $ Qed <$> (_follows *> justification <* _dot)
- qed <- rule $ qedJustified <|> trivial <|> omitted <|> pure (Qed JustificationEmpty)
+ qedJustified <- rule $ Qed . Just <$> _follows <*> (justification <* _dot)
+ qed <- rule $ qedJustified <|> trivial <|> omitted <|> pure (Qed Nothing JustificationEmpty)
let alignedEq = symbol "&=" <?> "\"&=\""
explanation <- rule $ (text justification) <|> pure JustificationEmpty
@@ -330,71 +359,56 @@ grammar lexicon@Lexicon{..} = mdo
biconditionals <- rule $ Biconditionals <$> formula <*> (many1 biconditionalItem) <* optional _dot
- calcQuantifier <- rule $ CalcQuantifier <$>
- ((_forAll <|> _forEvery) *> beginMath *> varSymbols)
- <*> maybeBounded <* endMath
- <*> optional suchStmt
- <* optional _have
+ calcQuantifier <- rule do
+ pos <- _forAll <|> _forEvery
+ xs <- beginMath *> varSymbols
+ mb <- maybeBounded <* endMath
+ st <- optional suchStmt
+ optional _have
+ pure (pos, CalcQuantifier xs mb st)
- calc <- rule $ Calc <$> optional calcQuantifier <*> align (equations <|> biconditionals) <*> proof
+ calc <- rule do
+ mquant <- optional calcQuantifier
+ psteps <- align (equations <|> biconditionals)
+ pf <- proof
+ pure let (pos2, steps) = psteps in case mquant of
+ Nothing -> Calc pos2 Nothing steps pf
+ Just (pos, q) -> Calc pos (Just q) steps pf
caseOf <- rule $ command "caseOf" *> token InvisibleBraceL *> stmt <* _dot <* token InvisibleBraceR
- byCases <- rule $ ByCase <$> env_ "byCase" (many1_ (Case <$> caseOf <*> proof))
- byContradiction <- rule $ ByContradiction <$ _suppose <* _not <* _dot <*> proof
- bySetInduction <- rule $ BySetInduction <$> proofBy (_in *> word "-induction" *> optional (word "on" *> term)) <*> proof
- byOrdInduction <- rule $ ByOrdInduction <$> proofBy (word "transfinite" *> word "induction" *> proof)
- assume <- rule $ Assume <$> (_suppose *> stmt <* _dot) <*> proof
-
- fixSymbolic <- rule $ FixSymbolic <$> (_fix *> beginMath *> varSymbols) <*> maybeBounded <* endMath <* _dot <*> proof
- fixSuchThat <- rule $ FixSuchThat <$> (_fix *> math varSymbols) <* _suchThat <*> stmt <* _dot <*> proof
+ byCases <- rule $ uncurry ByCase <$> envPos_ "byCase" (many1_ (Case <$> caseOf <*> proof))
+ byContradiction <- rule $ ByContradiction <$> _suppose <* _not <* _dot <*> proof
+ bySetInduction <- rule $ uncurry BySetInduction <$> proofBy (_in *> word "-induction" *> optional (word "on" *> term)) <*> proof
+ byOrdInduction <- rule $ uncurry ByOrdInduction <$> proofBy (word "transfinite" *> word "induction" *> proof)
+ assume <- rule $ Assume <$> _suppose <*> (stmt <* _dot) <*> proof
+
+ fixSymbolic <- rule $ FixSymbolic <$> _fix <*> (beginMath *> varSymbols) <*> maybeBounded <* endMath <* _dot <*> proof
+ fixSuchThat <- rule $ FixSuchThat <$> _fix <*> math varSymbols <* _suchThat <*> stmt <* _dot <*> proof
fix <- rule $ fixSymbolic <|> fixSuchThat
- takeVar <- rule $ TakeVar <$> (_take *> beginMath *> varSymbols) <*> maybeBounded <* endMath <* _suchThat <*> stmt <*> justification <* _dot <*> proof
- takeNoun <- rule $ TakeNoun <$> (_take *> _an *> (nounPhrase' <|> nounPhrasePl)) <*> justification <* _dot <*> proof
+ takeVar <- rule $ TakeVar <$> _take <*> (beginMath *> varSymbols) <*> maybeBounded <* endMath <* _suchThat <*> stmt <*> justification <* _dot <*> proof
+ takeNoun <- rule $ TakeNoun <$> _take <*> (_an *> (nounPhrase' <|> nounPhrasePl)) <*> justification <* _dot <*> proof
take <- rule $ takeVar <|> takeNoun
- suffices <- rule $ Suffices <$> (_sufficesThat *> stmt) <*> (justification <* _dot) <*> proof
- subclaim <- rule $ Subclaim <$> (_show *> stmt <* _dot) <*> env_ "subproof" proof <*> proof
- have <- rule $ Have <$> optional (_since *> stmt <* _comma <* _have) <* optional _haveIntro <*> stmt <*> justification <* _dot <*> proof
-
-
- define <- rule $ Define <$> (_let *> beginMath *> varSymbol <* _eq) <*> expr <* endMath <* _dot <*> proof
- defineFunction <- rule $ DefineFunction <$> (_let *> beginMath *> varSymbol) <*> paren varSymbol <* _eq <*> expr <* endMath <* _for <* beginMath <*> varSymbol <* _in <*> expr <* endMath <* _dot <*> proof
-
-
-
-
-
-
- -- Define $f $\fromTo{X}{Y} such that,
- -- Define function $f: X \to Y$,
- -- \begin{align}
- -- &x \mapsto 3*x &,
- -- &x \mapsto 4*k &, \forall k \in \N. x \in \Set{k}
- -- \end{align}
- --
+ suffices <- rule $ Suffices <$> _sufficesThat <*> stmt <*> (justification <* _dot) <*> proof
+ subclaim <- rule $ Subclaim <$> _show <*> (stmt <* _dot) <*> env_ "subproof" proof <*> proof
+ have <- rule do
+ msince <- optional ((,) <$> _since <*> stmt <* _comma <* _have)
+ mpos <- optional _haveIntro
+ s <- stmt
+ j <- justification <* _dot
+ pf <- proof
+ pure
+ let pos = case (msince, mpos) of
+ (Just (p, _), _) -> p
+ (_, Just p) -> p
+ _ -> locate s
+ in (Have pos (snd <$> msince) s j pf)
- -- Follwing is the definition right now.
- -- Define function $f: X \to Y$ such that,
- -- \begin{cases}
- -- 1 & \text{if } x \in \mathbb{Q}\\
- -- 0 & \text{if } x \in \mathbb{R}\setminus\mathbb{Q}
- -- 3 & \text{else}
- -- \end{cases}
- functionDefineCase <- rule $ (,) <$> (optional _ampersand *> expr) <*> (_ampersand *> text _if *> formula)
- defineFunctionLocal <- rule $ DefineFunctionLocal
- <$> (_define *> beginMath *> varSymbol) -- Define $ f
- <*> (_colon *> varSymbol) -- : 'var' \to 'var'
- <*> (_to *> expr <* endMath <* _suchThat)
- -- <*> (_suchThat *> align (many1 ((_ampersand *> varSymbol <* _mapsto) <*> exprApp <*> (_ampersand *> formula))))
- -- <*> (_suchThat *> align (many1 (varSymbol <* exprApp <* formula)))
- <*> (beginMath *> varSymbol) <*> (paren varSymbol <* _eq )
- <*> cases (many1 functionDefineCase) <* endMath <* optional _dot
- <*> proof
+ define <- rule $ Define <$> _let <*> (beginMath *> varSymbol <* _eq) <*> expr <* endMath <* _dot <*> proof
+ defineFunction <- rule $ DefineFunction <$> _let <*> (beginMath *> varSymbol) <*> paren varSymbol <* _eq <*> expr <* endMath <* _for <* beginMath <*> varSymbol <* _in <*> expr <* endMath <* _dot <*> proof
-
-
- proof <- rule $ asum [byContradiction, byCases, bySetInduction, byOrdInduction, calc, subclaim, assume, fix, take, have, suffices, define, defineFunction, defineFunctionLocal, qed]
+ proof <- rule $ asum [byContradiction, byCases, bySetInduction, byOrdInduction, calc, subclaim, assume, fix, take, have, suffices, define, defineFunction, qed]
blockAxiom <- rule $ uncurry3 BlockAxiom <$> envPos "axiom" axiom
@@ -412,9 +426,11 @@ grammar lexicon@Lexicon{..} = mdo
pure block
-proofBy :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a
-proofBy method = bracket $ word "proof" *> word "by" *> method
-
+proofBy :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (SourcePos, a)
+proofBy method = bracket do
+ pos <- word "proof" *> word "by"
+ a <- method
+ pure (pos, a)
lemmaEnv :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (SourcePos, Marker, a)
lemmaEnv content = asum
@@ -482,40 +498,58 @@ enumeratedMarked1 p = begin "enumerate" *> many1 ((,) <$> (command "item" *> lab
-- instead of with specialized variants.
--
phraseOf
- :: (pat -> [a] -> b)
+ :: forall pat a b r. Locatable a
+ => (SourcePos -> pat -> [a] -> b)
-> Lexicon
-> (Lexicon -> HashSet pat)
-> (pat -> LexicalPhrase)
-> Prod r Text (Located Token) a
-> Prod r Text (Located Token) b
phraseOf constr lexicon selector proj arg =
- uncurry constr <$> asum (fmap make pats)
+ uncurry3 constr <$> asum (fmap make pats)
where
+ pats :: [pat]
pats = HS.toList (selector lexicon)
- make pat = (\args -> (pat, args)) <$> go (proj pat)
+
+ make :: pat -> Prod r Text (Located Token) (SourcePos, pat, [a])
+ make pat = (\(pos, args) -> (pos, pat, args)) <$> goPos (proj pat)
+
+ goPos :: LexicalPhrase -> Prod r Text (Located Token) (SourcePos, [a])
+ goPos = \case
+ Just w : ws -> (,) <$> tokenPos w <*> go ws
+ Nothing : ws -> do
+ a <- arg
+ rest <- go ws
+ pure (locate a, a : rest)
+ [] -> error "phraseOf.goPos: empty phrase"
+
+ go :: LexicalPhrase -> Prod r Text (Located Token) [a]
go = \case
- Just w : ws -> token w *> go ws
- Nothing : ws -> (:) <$> arg <*> go ws
+ Just w : ws -> tokenPos w *> go ws
+ Nothing : ws -> do
+ a <- arg
+ rest <- go ws
+ pure (a : rest)
[] -> pure []
-adjLOf :: Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjLOf arg)
+adjLOf :: Locatable arg => Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjLOf arg)
adjLOf lexicon arg = phraseOf AdjL lexicon (HM.keysSet . lexiconAdjLs) id arg <?> "a left adjective"
-adjROf :: Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjROf arg)
+adjROf :: Locatable arg =>Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjROf arg)
adjROf lexicon arg = phraseOf AdjR lexicon (HM.keysSet . lexiconAdjRs) id arg <?> "a right adjective"
-adjOf :: Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjOf arg)
+adjOf :: Locatable arg =>Lexicon -> Prod r Text (Located Token) arg -> Prod r Text (Located Token) (AdjOf arg)
adjOf lexicon arg = phraseOf Adj lexicon (HM.keysSet . lexiconAdjs) id arg <?> "an adjective"
verbOf
- :: Lexicon
+ :: Locatable a => Lexicon
-> (SgPl LexicalPhrase -> LexicalPhrase)
-> Prod r Text (Located Token) a
-> Prod r Text (Located Token) (VerbOf a)
verbOf lexicon proj arg = phraseOf Verb lexicon (HM.keysSet . lexiconVerbs) proj arg
funOf
- :: Lexicon
+ :: Locatable a => Lexicon
-> (SgPl LexicalPhrase -> LexicalPhrase)
-> Prod r Text (Located Token) a
-> Prod r Text (Located Token) (FunOf a)
@@ -524,7 +558,7 @@ funOf lexicon proj arg = phraseOf Fun lexicon (HM.keysSet . lexiconFuns) proj ar
-- | A noun with a @t VarSymbol@ as name(s).
nounOf
- :: Lexicon
+ :: Locatable arg => Lexicon
-> (SgPl LexicalPhrase -> LexicalPhrase)
-> Prod r Text (Located Token) arg
-> Prod r Text (Located Token) (t VarSymbol)
@@ -542,7 +576,7 @@ nounOf lexicon proj arg vars =
[] -> pure []
structNounOf
- :: Lexicon
+ :: Locatable arg => Lexicon
-> (SgPl LexicalPhrase -> LexicalPhrase)
-> Prod r Text (Located Token) arg
-> Prod r Text (Located Token) name
@@ -630,6 +664,9 @@ ref = terminal \ltok -> case unLocated ltok of
math :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a
math body = beginMath *> body <* endMath
+mathPos :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (SourcePos, a)
+mathPos body = (,) <$> beginMath <*> body <* endMath
+
text :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a
text body = begin "text" *> body <* end "text" <?> "\"\\text{...}\""
@@ -649,8 +686,8 @@ brace body = token VisibleBraceL *> body <* token VisibleBraceR <?> "\"\\{...\\
group :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a
group body = token InvisibleBraceL *> body <* token InvisibleBraceR <?> "\"{...}\""
-align :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a
-align body = begin "align*" *> body <* end "align*"
+align :: Prod r Text (Located Token) a -> Prod r Text (Located Token) (SourcePos, a)
+align body = (,) <$> begin "align*" <*> body <* end "align*"
cases :: Prod r Text (Located Token) a -> Prod r Text (Located Token) a
cases body = begin "cases" *> body <* end "cases"
diff --git a/source/Syntax/Internal.hs b/source/Syntax/Internal.hs
index 7089d74..73b41de 100644
--- a/source/Syntax/Internal.hs
+++ b/source/Syntax/Internal.hs
@@ -407,34 +407,34 @@ data Proof
= Omitted
-- ^ Ends a proof without further verification.
-- This results in a “gap” in the formalization.
- | Qed Justification
+ | Qed {mpos :: Maybe SourcePos, by :: Justification}
-- ^ Ends of a proof, leaving automation to discharge the current goal using the given justification.
- | ByContradiction Proof
+ | ByContradiction SourcePos Proof
-- ^ Take the dual of the current goal as an assumption and
-- set the goal to absurdity.
- | BySetInduction (Maybe Term) Proof
+ | BySetInduction SourcePos (Maybe Term) Proof
-- ^ ∈-induction.
- | ByOrdInduction Proof
+ | ByOrdInduction SourcePos Proof
-- ^ Transfinite induction for ordinals.
- | Assume Formula Proof
+ | Assume SourcePos Formula Proof
-- ^ Simplify goals that are implications or disjunctions.
- | Fix (NonEmpty VarSymbol) Formula Proof
+ | Fix SourcePos (NonEmpty VarSymbol) Formula Proof
-- ^ Simplify universal goals (with an optional bound or such that statement)
- | Take (NonEmpty VarSymbol) Formula Justification Proof
+ | Take SourcePos (NonEmpty VarSymbol) Formula Justification Proof
-- ^ Use existential assumptions.
- | Suffices Formula Justification Proof
- | ByCase [Case]
+ | Suffices SourcePos Formula Justification Proof
+ | ByCase SourcePos [Case]
-- ^ Proof by case. Disjunction of the case hypotheses 'Case'
-- must hold for this step to succeed. Each case starts a subproof,
-- keeping the same goal but adding the case hypothesis as an assumption.
-- Often this will be a classical split between /@P@/ and /@not P@/, in
-- which case the proof that /@P or not P@/ holds is easy.
--
- | Have Formula Justification Proof
+ | Have SourcePos Formula Justification Proof
-- ^ An affirmation, e.g.: /@We have \<stmt\> by \<ref\>@/.
--
- | Calc CalcQuantifier Calc Proof
- | Subclaim Formula Proof Proof
+ | Calc SourcePos CalcQuantifier Calc Proof
+ | Subclaim SourcePos Formula Proof Proof
-- ^ A claim is a sublemma with its own proof:
--
-- /@Show \<goal stmt\>. \<steps\>. \<continue other proof\>.@/
@@ -442,10 +442,10 @@ data Proof
-- A successful first proof adds the claimed formula as an assumption
-- for the remaining proof.
--
- | Define VarSymbol Term Proof
- | DefineFunction VarSymbol VarSymbol Term Term Proof
+ | Define SourcePos VarSymbol Term Proof
+ | DefineFunction SourcePos VarSymbol VarSymbol Term Term Proof
- | DefineFunctionLocal VarSymbol VarSymbol VarSymbol Term (NonEmpty (Term, Formula)) Proof
+ | DefineFunctionLocal SourcePos VarSymbol VarSymbol VarSymbol Term (NonEmpty (Term, Formula)) Proof
deriving instance Show Proof
deriving instance Eq Proof