remove big mutual blocks in parser

This commit is contained in:
rhiannon morris 2023-04-26 02:23:59 +02:00
parent adebfe090c
commit b5f42cde64

View file

@ -189,10 +189,6 @@ data PCasePat =
| PBox BName | PBox BName
%runElab derive "PCasePat" [Eq, Ord, Show] %runElab derive "PCasePat" [Eq, Ord, Show]
public export
PCaseArm : Type
PCaseArm = (PCasePat, PTerm)
||| either `zero` or `0` ||| either `zero` or `0`
export export
zeroPat : Grammar True () zeroPat : Grammar True ()
@ -210,6 +206,174 @@ casePat =
<|> delim "[" "]" [|PBox patVar|] <|> delim "[" "]" [|PBox patVar|]
<|> fatalError "invalid pattern" <|> fatalError "invalid pattern"
export covering
term : Grammar True PTerm
export covering
typeLine : Grammar True (BName, PTerm)
typeLine = do
resC "["
mustWork $ do
i <- option Nothing $ patVar <* resC ""
t <- term <* needRes "]"
pure (i, t)
||| box term `[t]` or type `[π.A]`
export covering
boxTerm : Grammar True PTerm
boxTerm = do
res "["; commit
q <- optional $ qty <* res "."
t <- mustWork $ term <* needRes "]"
pure $ maybe (Box t) (\q => BOX q t) q
||| tuple term like `(a, b)`, or parenthesised single term.
||| allows terminating comma. more than two elements are nested on the right:
||| `(a, b, c, d) = (a, (b, (c, d)))`.
export covering
tupleTerm : Grammar True PTerm
tupleTerm = foldr1 Pair <$> delimSep1 "(" ")" "," term
||| argument/atomic term: single-token terms, or those with delimiters e.g.
||| `[t]`
export covering
termArg : Grammar True PTerm
termArg = [|TYPE universe1|]
<|> [|Enum enumType|]
<|> [|Tag tag|]
<|> boxTerm
<|> Nat <$ res ""
<|> Zero <$ res "zero"
<|> [|fromNat nat|]
<|> [|V qname|]
<|> tupleTerm
export covering
coeTerm : Grammar True PTerm
coeTerm = resC "coe" *> mustWork [|Coe typeLine dimArg dimArg termArg|]
export covering
compBranch : Grammar True (DimConst, BName, PTerm)
compBranch = [|(,,) dimConst patVar (needRes "" *> term)|]
export covering
compTerm : Grammar True PTerm
compTerm = do
resC "comp"
mustWork $ do
a <- typeLine
p <- dimArg; q <- dimArg
s <- termArg; r <- dimArg
needRes "{"
s0 <- compBranch; needRes ";"
s1 <- compBranch; optRes ";"
needRes "}"
case (fst s0, fst s1) of
(Zero, One) => pure $ Comp a p q s r (snd s0) (snd s1)
(One, Zero) => pure $ Comp a p q s r (snd s1) (snd s0)
(_, _) =>
fatalError "body of 'comp' needs one 0 case and one 1 case"
export covering
splitUniverseTerm : Grammar True PTerm
splitUniverseTerm = resC "" *> mustWork [|TYPE nat|]
export covering
eqTerm : Grammar True PTerm
eqTerm = resC "Eq" *> mustWork [|Eq typeLine termArg termArg|]
export covering
succTerm : Grammar True PTerm
succTerm = resC "succ" *> mustWork [|Succ termArg|]
||| a dimension argument with an `@` prefix, or
||| a term argument with no prefix
export covering
anyArg : Grammar True (Either PDim PTerm)
anyArg = dimArg <||> termArg
export covering
normalAppTerm : Grammar True PTerm
normalAppTerm = foldl ap <$> termArg <*> many anyArg
where ap : PTerm -> Either PDim PTerm -> PTerm
ap f (Left p) = f :% p
ap f (Right s) = f :@ s
||| application term `f x @y z`, or other terms that look like application
||| like `succ` or `coe`.
export covering
appTerm : Grammar True PTerm
appTerm = coeTerm
<|> compTerm
<|> splitUniverseTerm
<|> eqTerm
<|> succTerm
<|> normalAppTerm
export covering
infixEqTerm : Grammar True PTerm
infixEqTerm = do
l <- appTerm; commit
rest <- optional $ res "" *> [|(,) term (needRes ":" *> appTerm)|]
pure $ maybe l (\rest => Eq (Nothing, snd rest) l (fst rest)) rest
export covering
annTerm : Grammar True PTerm
annTerm = do
tm <- infixEqTerm; commit
ty <- optional $ res "" *> term
pure $ maybe tm (tm :#) ty
export covering
lamTerm : Grammar True PTerm
lamTerm = do
k <- DLam <$ res "δ" <|> Lam <$ res "λ"
mustWork $ do
xs <- some patVar; needRes ""
body <- term; commit
pure $ foldr k body xs
-- [todo] fix the backtracking in e.g. (F x y z × B)
export covering
properBinders : Grammar True (List1 BName, PTerm)
properBinders = do
res "("
xs <- some patVar; resC ":"
t <- term; needRes ")"
pure (xs, t)
export covering
piTerm : Grammar True PTerm
piTerm = do
q <- qty; resC "."
dom <- piBinder; needRes ""
cod <- term; commit
pure $ foldr (\x => Pi q x (snd dom)) cod (fst dom)
where
piBinder : Grammar True (List1 BName, PTerm)
piBinder = properBinders <|> [|(singleton Nothing,) termArg|]
export covering
sigmaTerm : Grammar True PTerm
sigmaTerm =
(properBinders >>= continueDep)
<|> (annTerm >>= continueNondep)
where
continueDep : (List1 BName, PTerm) -> Grammar True PTerm
continueDep (names, dom) = do
cod <- needRes "×" *> sigmaTerm
pure $ foldr (\x => Sig x dom) cod names
continueNondep : PTerm -> Grammar False PTerm
continueNondep dom = do
rest <- optional $ resC "×" *> sepBy1 (res "×") annTerm
Core.pure $ foldr1 (Sig Nothing) $ dom ::: maybe [] forget rest
public export
PCaseArm : Type
PCaseArm = (PCasePat, PTerm)
export export
checkCaseArms : List PCaseArm -> Grammar False PCaseBody checkCaseArms : List PCaseArm -> Grammar False PCaseBody
checkCaseArms [] = checkCaseArms [] =
@ -235,191 +399,29 @@ checkCaseArms ((PBox x, rhs) :: rest) = do
let [] = rest | _ => fatalError "unexpected pattern after box" let [] = rest | _ => fatalError "unexpected pattern after box"
pure $ CaseBox x rhs pure $ CaseBox x rhs
export covering
caseArm : Grammar True PCaseArm
caseArm = [|(,) casePat (needRes "" *> term)|]
mutual export covering
export covering caseBody : Grammar True PCaseBody
typeLine : Grammar True (BName, PTerm) caseBody = delimSep "{" "}" ";" caseArm >>= checkCaseArms
typeLine = do
resC "["
mustWork $ do
i <- option Nothing $ patVar <* resC ""
t <- term <* needRes "]"
pure (i, t)
||| argument/atomic term: single-token terms, or those with delimiters e.g. export covering
||| `[t]` caseTerm : Grammar True PTerm
export covering caseTerm = do
termArg : Grammar True PTerm qty <- caseIntro; commit
termArg = [|TYPE universe1|] head <- mustWork term; needRes "return"
<|> [|Enum enumType|] ret <- mustWork [|(,) (option Nothing $ patVar <* resC "") term|]
<|> [|Tag tag|] needRes "of"
<|> boxTerm body <- mustWork caseBody
<|> Nat <$ res "" pure $ Case qty head ret body
<|> Zero <$ res "zero"
<|> [|fromNat nat|]
<|> [|V qname|]
<|> tupleTerm
||| box term `[t]` or type `[π.A]`
export covering
boxTerm : Grammar True PTerm
boxTerm = do
res "["; commit
q <- optional $ qty <* res "."
t <- mustWork $ term <* needRes "]"
pure $ maybe (Box t) (\q => BOX q t) q
||| tuple term like `(a, b)`, or parenthesised single term. term = lamTerm
||| allows terminating comma. more than two elements are nested on the right: <|> caseTerm
||| `(a, b, c, d) = (a, (b, (c, d)))`. <|> piTerm
export covering <|> sigmaTerm
tupleTerm : Grammar True PTerm
tupleTerm = foldr1 Pair <$> delimSep1 "(" ")" "," term
||| application term `f x @y z`, or other terms that look like application
||| like `succ` or `coe`.
export covering
appTerm : Grammar True PTerm
appTerm = coeTerm
<|> compTerm
<|> splitUniverseTerm
<|> eqTerm
<|> succTerm
<|> normalAppTerm
export covering
coeTerm : Grammar True PTerm
coeTerm = resC "coe" *> mustWork [|Coe typeLine dimArg dimArg termArg|]
export covering
compTerm : Grammar True PTerm
compTerm = do
resC "comp"
mustWork $ do
a <- typeLine
p <- dimArg; q <- dimArg
s <- termArg; r <- dimArg
needRes "{"
s0 <- compBranch; needRes ";"
s1 <- compBranch; optRes ";"
needRes "}"
case (fst s0, fst s1) of
(Zero, One) => pure $ Comp a p q s r (snd s0) (snd s1)
(One, Zero) => pure $ Comp a p q s r (snd s1) (snd s0)
(_, _) =>
fatalError "body of 'comp' needs one 0 case and one 1 case"
export covering
compBranch : Grammar True (DimConst, BName, PTerm)
compBranch = [|(,,) dimConst patVar (needRes "" *> term)|]
export covering
splitUniverseTerm : Grammar True PTerm
splitUniverseTerm = resC "" *> mustWork [|TYPE nat|]
export covering
eqTerm : Grammar True PTerm
eqTerm = resC "Eq" *> mustWork [|Eq typeLine termArg termArg|]
export covering
succTerm : Grammar True PTerm
succTerm = resC "succ" *> mustWork [|Succ termArg|]
export covering
normalAppTerm : Grammar True PTerm
normalAppTerm = foldl ap <$> termArg <*> many anyArg
where ap : PTerm -> Either PDim PTerm -> PTerm
ap f (Left p) = f :% p
ap f (Right s) = f :@ s
||| a dimension argument with an `@` prefix, or
||| a term argument with no prefix
export covering
anyArg : Grammar True (Either PDim PTerm)
anyArg = dimArg <||> termArg
export covering
term : Grammar True PTerm
term = lamTerm
<|> caseTerm
<|> piTerm
<|> sigmaTerm
export covering
lamTerm : Grammar True PTerm
lamTerm = do
k <- DLam <$ res "δ" <|> Lam <$ res "λ"
mustWork $ do
xs <- some patVar; needRes ""
body <- term; commit
pure $ foldr k body xs
export covering
piTerm : Grammar True PTerm
piTerm = do
q <- qty; resC "."
dom <- piBinder; needRes ""
cod <- term; commit
pure $ foldr (\x => Pi q x (snd dom)) cod (fst dom)
where
piBinder : Grammar True (List1 BName, PTerm)
piBinder = properBinders <|> [|(singleton Nothing,) termArg|]
-- [todo] fix the backtracking in e.g. (F x y z × B)
export covering
properBinders : Grammar True (List1 BName, PTerm)
properBinders = do
res "("
xs <- some patVar; resC ":"
t <- term; needRes ")"
pure (xs, t)
export covering
sigmaTerm : Grammar True PTerm
sigmaTerm =
(properBinders >>= continueDep)
<|> (annTerm >>= continueNondep)
where
continueDep : (List1 BName, PTerm) -> Grammar True PTerm
continueDep (names, dom) = do
cod <- needRes "×" *> sigmaTerm
pure $ foldr (\x => Sig x dom) cod names
continueNondep : PTerm -> Grammar False PTerm
continueNondep dom = do
rest <- optional $ resC "×" *> sepBy1 (res "×") annTerm
Core.pure $ foldr1 (Sig Nothing) $ dom ::: maybe [] forget rest
export covering
annTerm : Grammar True PTerm
annTerm = do
tm <- infixEqTerm; commit
ty <- optional $ res "" *> term
pure $ maybe tm (tm :#) ty
export covering
infixEqTerm : Grammar True PTerm
infixEqTerm = do
l <- appTerm; commit
rest <- optional $ res "" *> [|(,) term (needRes ":" *> appTerm)|]
pure $ maybe l (\rest => Eq (Nothing, snd rest) l (fst rest)) rest
export covering
caseTerm : Grammar True PTerm
caseTerm = do
qty <- caseIntro; commit
head <- mustWork term; needRes "return"
ret <- mustWork [|(,) (option Nothing $ patVar <* resC "") term|]
needRes "of"
body <- mustWork caseBody
pure $ Case qty head ret body
export covering
caseBody : Grammar True PCaseBody
caseBody = delimSep "{" "}" ";" caseArm >>= checkCaseArms
export covering
caseArm : Grammar True PCaseArm
caseArm = [|(,) casePat (needRes "" *> term)|]
||| `def` alone means `defω` ||| `def` alone means `defω`
@ -429,31 +431,32 @@ defIntro = Zero <$ resC "def0"
<|> Any <$ resC "defω" <|> Any <$ resC "defω"
<|> resC "def" *> option Any (qty <* needRes ".") <|> resC "def" *> option Any (qty <* needRes ".")
mutual
export covering
definition : Grammar True PDefinition
definition = do
qty <- defIntro
name <- baseName
type <- optional $ resC ":" *> mustWork term
term <- needRes "=" *> mustWork term
optRes ";"
pure $ MkPDef {qty, name, type, term}
export covering export covering
namespace_ : Grammar True PNamespace decl : Grammar True PDecl
namespace_ = do
ns <- resC "namespace" *> qname; needRes "{"
decls <- nsInner; optRes ";"
pure $ MkPNamespace (ns.mods :< ns.base) decls
where
nsInner : Grammar True (List PDecl)
nsInner = [] <$ resC "}"
<|> [|(decl <* commit) :: nsInner|]
export covering export covering
decl : Grammar True PDecl definition : Grammar True PDefinition
decl = [|PDef definition|] <|> [|PNs namespace_|] definition = do
qty <- defIntro
name <- baseName
type <- optional $ resC ":" *> mustWork term
term <- needRes "=" *> mustWork term
optRes ";"
pure $ MkPDef {qty, name, type, term}
export covering
namespace_ : Grammar True PNamespace
namespace_ = do
ns <- resC "namespace" *> qname; needRes "{"
decls <- nsInner; optRes ";"
pure $ MkPNamespace (ns.mods :< ns.base) decls
where
nsInner : Grammar True (List PDecl)
nsInner = [] <$ resC "}"
<|> [|(decl <* commit) :: nsInner|]
decl = [|PDef definition|] <|> [|PNs namespace_|]
export covering export covering
load : Grammar True String load : Grammar True String