2Module : Idris.Parser.Expr
3Description : Parse Expressions.
6Maintainer : The Idris Community.
8{-# LANGUAGE FlexibleContexts, TupleSections #-}
9module Idris.Parser.Expr where
15import Idris.Parser.Helpers
16import Idris.Parser.Ops
18import Prelude hiding (pi)
20import Control.Applicative
21import Control.Arrow (left)
23import Control.Monad.State.Strict
24import Data.Function (on)
27import Text.Megaparsec ((<?>))
28import qualified Text.Megaparsec as P
29import qualified Text.Megaparsec.Char as P
30import qualified Text.Megaparsec.Expr as P
32-- | Allow implicit type declarations
33allowImp :: SyntaxInfo -> SyntaxInfo
34allowImp syn = syn { implicitAllowed = True,
35 constraintAllowed = False }
37-- | Disallow implicit type declarations
38disallowImp :: SyntaxInfo -> SyntaxInfo
39disallowImp = scopedImp
41-- | Implicits hare are scoped rather than top level
42scopedImp :: SyntaxInfo -> SyntaxInfo
43scopedImp syn = syn { implicitAllowed = False,
44 constraintAllowed = False }
46-- | Allow scoped constraint arguments
47allowConstr :: SyntaxInfo -> SyntaxInfo
48allowConstr syn = syn { constraintAllowed = True }
50{-| Parses an expression as a whole
52 FullExpr ::= Expr EOF_t;
55fullExpr :: SyntaxInfo -> IdrisParser PTerm
56fullExpr syn = do x <- expr syn
59 return $ debindApp syn (desugar syn i x)
61tryFullExpr :: SyntaxInfo -> IState -> String -> Either Err PTerm
62tryFullExpr syn st = left (Msg . show . parseErrorDoc) . runparser (fullExpr syn) st ""
64{- | Parses an expression
69expr :: SyntaxInfo -> IdrisParser PTerm
72{- | Parses an expression with possible operator applied
74 OpExpr ::= {- Expression Parser with Operators based on Expr' -};
77opExpr :: SyntaxInfo -> IdrisParser PTerm
78opExpr syn = do i <- get
79 P.makeExprParser (expr' syn) (table (idris_infixes i))
81{- | Parses either an internally defined expression or
84Expr' ::= "External (User-defined) Syntax"
88expr' :: SyntaxInfo -> IdrisParser PTerm
89expr' syn = P.try (externalExpr syn)
93{- | Parses a user-defined expression -}
94externalExpr :: SyntaxInfo -> IdrisParser PTerm
95externalExpr syn = do i <- get
96 (FC fn start _) <- getFC
97 expr <- extensions syn (syntaxRulesList $ syntax_rules i)
99 let outerFC = FC fn start end
100 return (mapPTermFC (fixFC outerFC) (fixFCH fn outerFC) expr)
101 <?> "user-defined expression"
102 where -- Fix non-highlighting FCs by approximating with the span of the syntax application
103 fixFC outer inner | inner `fcIn` outer = inner
105 -- Fix highlighting FCs by making them useless, to avoid spurious highlights
106 fixFCH fn outer inner | inner `fcIn` outer = inner
107 | otherwise = FileFC fn
109{- | Parses a simple user-defined expression -}
110simpleExternalExpr :: SyntaxInfo -> IdrisParser PTerm
111simpleExternalExpr syn = do i <- get
112 extensions syn (filter isSimple (syntaxRulesList $ syntax_rules i))
114 isSimple (Rule (Expr x:xs) _ _) = False
115 isSimple (Rule (SimpleExpr x:xs) _ _) = False
116 isSimple (Rule [Keyword _] _ _) = True
117 isSimple (Rule [Symbol _] _ _) = True
118 isSimple (Rule (_:xs) _ _) = case last xs of
124{- | Tries to parse a user-defined expression given a list of syntactic extensions -}
125extensions :: SyntaxInfo -> [Syntax] -> IdrisParser PTerm
126extensions syn rules = extension syn [] (filter isValid rules)
127 <?> "user-defined expression"
129 isValid :: Syntax -> Bool
130 isValid (Rule _ _ AnySyntax) = True
131 isValid (Rule _ _ PatternSyntax) = inPattern syn
132 isValid (Rule _ _ TermSyntax) = not (inPattern syn)
133 isValid (DeclRule _ _) = False
135data SynMatch = SynTm PTerm | SynBind FC Name -- ^ the FC is for highlighting information
138extension :: SyntaxInfo -> [Maybe (Name, SynMatch)] -> [Syntax] -> IdrisParser PTerm
139extension syn ns rules =
140 P.choice $ flip map (groupBy (ruleGroup `on` syntaxSymbols) rules) $ \rs ->
141 case head rs of -- can never be []
142 Rule (symb:_) _ _ -> P.try $ do
143 n <- extensionSymbol symb
144 extension syn (n : ns) [Rule ss t ctx | (Rule (_:ss) t ctx) <- rs]
145 -- If we have more than one Rule in this bucket, our grammar is
147 Rule [] ptm _ -> return (flatten (updateSynMatch (mapMaybe id ns) ptm))
149 ruleGroup [] [] = True
150 ruleGroup (s1:_) (s2:_) = s1 == s2
151 ruleGroup _ _ = False
153 extensionSymbol :: SSymbol -> IdrisParser (Maybe (Name, SynMatch))
154 extensionSymbol (Keyword n) = do fc <- reservedFC (show n)
155 highlightP fc AnnKeyword
157 extensionSymbol (Expr n) = do tm <- expr syn
158 return $ Just (n, SynTm tm)
159 extensionSymbol (SimpleExpr n) = do tm <- simpleExpr syn
160 return $ Just (n, SynTm tm)
161 extensionSymbol (Binding n) = do (b, fc) <- name
162 return $ Just (n, SynBind fc b)
163 extensionSymbol (Symbol s) = do fc <- symbolFC s
164 highlightP fc AnnKeyword
167 flatten :: PTerm -> PTerm -- flatten application
168 flatten (PApp fc (PApp _ f as) bs) = flatten (PApp fc f (as ++ bs))
171updateSynMatch = update
173 updateB :: [(Name, SynMatch)] -> (Name, FC) -> (Name, FC)
174 updateB ns (n, fc) = case lookup n ns of
175 Just (SynBind tfc t) -> (t, tfc)
178 update :: [(Name, SynMatch)] -> PTerm -> PTerm
179 update ns (PRef fc hls n) = case lookup n ns of
182 update ns (PPatvar fc n) = uncurry (flip PPatvar) $ updateB ns (n, fc)
183 update ns (PLam fc n nfc ty sc)
184 = let (n', nfc') = updateB ns (n, nfc)
185 in PLam fc n' nfc' (update ns ty) (update (dropn n ns) sc)
186 update ns (PPi p n fc ty sc)
187 = let (n', nfc') = updateB ns (n, fc)
188 in PPi (updTacImp ns p) n' nfc'
189 (update ns ty) (update (dropn n ns) sc)
190 update ns (PLet fc rc n nfc ty val sc)
191 = let (n', nfc') = updateB ns (n, nfc)
192 in PLet fc rc n' nfc' (update ns ty)
193 (update ns val) (update (dropn n ns) sc)
194 update ns (PApp fc t args)
195 = PApp fc (update ns t) (map (fmap (update ns)) args)
196 update ns (PAppBind fc t args)
197 = PAppBind fc (update ns t) (map (fmap (update ns)) args)
198 update ns (PMatchApp fc n) = let (n', nfc') = updateB ns (n, fc)
200 update ns (PIfThenElse fc c t f)
201 = PIfThenElse fc (update ns c) (update ns t) (update ns f)
202 update ns (PCase fc c opts)
203 = PCase fc (update ns c) (map (pmap (update ns)) opts)
204 update ns (PRewrite fc by eq tm mty)
205 = PRewrite fc by (update ns eq) (update ns tm) (fmap (update ns) mty)
206 update ns (PPair fc hls p l r) = PPair fc hls p (update ns l) (update ns r)
207 update ns (PDPair fc hls p l t r)
208 = PDPair fc hls p (update ns l) (update ns t) (update ns r)
209 update ns (PAs fc n t) = PAs fc (fst $ updateB ns (n, NoFC)) (update ns t)
210 update ns (PAlternative ms a as) = PAlternative ms a (map (update ns) as)
211 update ns (PHidden t) = PHidden (update ns t)
212 update ns (PGoal fc r n sc) = PGoal fc (update ns r) n (update ns sc)
213 update ns (PDoBlock ds) = PDoBlock $ map (upd ns) ds
214 where upd :: [(Name, SynMatch)] -> PDo -> PDo
215 upd ns (DoExp fc t) = DoExp fc (update ns t)
216 upd ns (DoBind fc n nfc t) = DoBind fc n nfc (update ns t)
217 upd ns (DoLet fc rc n nfc ty t) = DoLet fc rc n nfc (update ns ty) (update ns t)
218 upd ns (DoBindP fc i t ts)
219 = DoBindP fc (update ns i) (update ns t)
220 (map (\(l,r) -> (update ns l, update ns r)) ts)
221 upd ns (DoLetP fc i t) = DoLetP fc (update ns i) (update ns t)
222 upd ns (DoRewrite fc h) = DoRewrite fc (update ns h)
223 update ns (PIdiom fc t) = PIdiom fc $ update ns t
224 update ns (PMetavar fc n) = uncurry (flip PMetavar) $ updateB ns (n, fc)
225 update ns (PProof tacs) = PProof $ map (updTactic ns) tacs
226 update ns (PTactics tacs) = PTactics $ map (updTactic ns) tacs
227 update ns (PDisamb nsps t) = PDisamb nsps $ update ns t
228 update ns (PUnifyLog t) = PUnifyLog $ update ns t
229 update ns (PNoImplicits t) = PNoImplicits $ update ns t
230 update ns (PQuasiquote tm mty) = PQuasiquote (update ns tm) (fmap (update ns) mty)
231 update ns (PUnquote t) = PUnquote $ update ns t
232 update ns (PQuoteName n res fc) = let (n', fc') = (updateB ns (n, fc))
233 in PQuoteName n' res fc'
234 update ns (PRunElab fc t nsp) = PRunElab fc (update ns t) nsp
235 update ns (PConstSugar fc t) = PConstSugar fc $ update ns t
236 -- PConstSugar probably can't contain anything substitutable, but it's hard to track
239 updTactic :: [(Name, SynMatch)] -> PTactic -> PTactic
240 -- handle all the ones with Names explicitly, then use fmap for the rest with PTerms
241 updTactic ns (Intro ns') = Intro $ map (fst . updateB ns . (, NoFC)) ns'
242 updTactic ns (Focus n) = Focus . fst $ updateB ns (n, NoFC)
243 updTactic ns (Refine n bs) = Refine (fst $ updateB ns (n, NoFC)) bs
244 updTactic ns (Claim n t) = Claim (fst $ updateB ns (n, NoFC)) (update ns t)
245 updTactic ns (MatchRefine n) = MatchRefine (fst $ updateB ns (n, NoFC))
246 updTactic ns (LetTac n t) = LetTac (fst $ updateB ns (n, NoFC)) (update ns t)
247 updTactic ns (LetTacTy n ty tm) = LetTacTy (fst $ updateB ns (n, NoFC)) (update ns ty) (update ns tm)
248 updTactic ns (ProofSearch rec prover depth top psns hints) = ProofSearch rec prover depth
249 (fmap (fst . updateB ns . (, NoFC)) top) (map (fst . updateB ns . (, NoFC)) psns) (map (fst . updateB ns . (, NoFC)) hints)
250 updTactic ns (Try l r) = Try (updTactic ns l) (updTactic ns r)
251 updTactic ns (TSeq l r) = TSeq (updTactic ns l) (updTactic ns r)
252 updTactic ns (GoalType s tac) = GoalType s $ updTactic ns tac
253 updTactic ns (TDocStr (Left n)) = TDocStr . Left . fst $ updateB ns (n, NoFC)
254 updTactic ns t = fmap (update ns) t
256 updTacImp ns (TacImp o st scr r) = TacImp o st (update ns scr) r
259 dropn :: Name -> [(Name, a)] -> [(Name, a)]
261 dropn n ((x,t) : xs) | n == x = xs
262 | otherwise = (x,t):dropn n xs
265{- | Parses a (normal) built-in expression
282internalExpr :: SyntaxInfo -> IdrisParser PTerm
299{- | Parses the "impossible" keyword
301Impossible ::= 'impossible'
304impossible :: IdrisParser PTerm
305impossible = do fc <- reservedFC "impossible"
306 highlightP fc AnnKeyword
309{- | Parses a case expression
312 'case' Expr 'of' OpenBlock CaseOption+ CloseBlock;
315caseExpr :: SyntaxInfo -> IdrisParser PTerm
316caseExpr syn = do kw1 <- reservedFC "case"; fc <- getFC
317 scr <- expr syn; kw2 <- reservedFC "of";
318 opts <- indentedBlock1 (caseOption syn)
319 highlightP kw1 AnnKeyword
320 highlightP kw2 AnnKeyword
321 return (PCase fc scr opts)
322 <?> "case expression"
324{- | Parses a case in a case expression
327 Expr (Impossible | '=>' Expr) Terminator
331caseOption :: SyntaxInfo -> IdrisParser (PTerm, PTerm)
332caseOption syn = do lhs <- expr (disallowImp (syn { inPattern = True }))
333 r <- impossible <|> symbol "=>" *> expr syn
337warnTacticDeprecation :: FC -> IdrisParser ()
338warnTacticDeprecation fc =
339 parserWarning fc (Just NoOldTacticDeprecationWarnings) (Msg "This style of tactic proof is deprecated. See %runElab for the replacement.")
341{- | Parses a proof block
344 'proof' OpenBlock Tactic'* CloseBlock
348proofExpr :: SyntaxInfo -> IdrisParser PTerm
349proofExpr syn = do kw <- reservedFC "proof"
350 ts <- indentedBlock1 (tactic syn)
351 highlightP kw AnnKeyword
352 warnTacticDeprecation kw
356{- | Parses a tactics block
359 'tactics' OpenBlock Tactic'* CloseBlock
363tacticsExpr :: SyntaxInfo -> IdrisParser PTerm
364tacticsExpr syn = do kw <- reservedFC "tactics"
365 ts <- indentedBlock1 (tactic syn)
366 highlightP kw AnnKeyword
367 warnTacticDeprecation kw
371{- | Parses a simple expression
374 {- External (User-defined) Simple Expression -}
377 | 'Refl' ('{' Expr '}')?
395simpleExpr :: SyntaxInfo -> IdrisParser PTerm
397 P.try (simpleExternalExpr syn)
398 <|> do (x, FC f (l, c) end) <- P.try (lchar '?' *> name)
399 return (PMetavar (FC f (l, c-1) end) x)
400 <|> do lchar '%'; fc <- getFC; reserved "implementation"; return (PResolveTC fc)
401 <|> do lchar '%'; fc <- getFC; reserved "instance"
402 parserWarning fc Nothing $ Msg "The use of %instance is deprecated, use %implementation instead."
403 return (PResolveTC fc)
404 <|> do reserved "elim_for"; fc <- getFC; t <- fst <$> fnName; return (PRef fc [] (SN $ ElimN t))
407 <|> P.try (do fc <- reservedFC "Type*"; return $ PUniverse fc AllTypes)
408 <|> do fc <- reservedFC "AnyType"; return $ PUniverse fc AllTypes
409 <|> PType <$> reservedFC "Type"
410 <|> do fc <- reservedFC "UniqueType"; return $ PUniverse fc UniqueType
411 <|> do fc <- reservedFC "NullType"; return $ PUniverse fc NullType
412 <|> do (c, cfc) <- constant
414 return (modifyConst syn fc (PConstant cfc c))
415 <|> do symbol "'"; fc <- getFC; str <- fst <$> name
416 return (PApp fc (PRef fc [] (sUN "Symbol_"))
417 [pexp (PConstant NoFC (Str (show str)))])
418 <|> do (x, fc) <- fnName
420 then P.option (PRef fc [fc] x)
424 return (PAs fcIn x s))
425 else return (PRef fc [fc] x)
429 <|> do reservedOp "!"
432 return (PAppBind fc s [])
433 <|> bracketed (disallowImp syn)
437 <|> do lchar '_'; return Placeholder
440{- |Parses an expression in parentheses
442Bracketed ::= '(' Bracketed'
445bracketed :: SyntaxInfo -> IdrisParser PTerm
446bracketed syn = do (FC fn (sl, sc) _) <- getFC
447 lchar '(' <?> "parenthesized expression"
448 bracketed' (FC fn (sl, sc) (sl, sc+1)) (syn { withAppAllowed = True })
450{- |Parses the rest of an expression in braces
462bracketed' :: FC -> SyntaxInfo -> IdrisParser PTerm
464 do (FC f start (l, c)) <- getFC
466 return $ PTrue (spanFC open (FC f start (l, c+1))) TypeOrTerm
467 <|> P.try (dependentPair TypeOrTerm [] open syn)
468 <|> P.try (do (opName, fc) <- operatorName
469 guardNotPrefix opName
473 return $ PLam fc (sMN 1000 "ARG") NoFC Placeholder
474 (PApp fc (PRef fc [] opName) [pexp (PRef fc [] (sMN 1000 "ARG")),
476 <|> P.try (simpleExpr syn >>= \l ->
477 P.try (do (opName, _) <- operatorName
480 return $ PLam fc (sMN 1000 "ARG") NoFC Placeholder
481 (PApp fc (PRef fc [] opName) [pexp l,
482 pexp (PRef fc [] (sMN 1000 "ARG"))]))
483 <|> bracketedExpr syn open l)
484 <|> do l <- expr (allowConstr syn)
485 bracketedExpr (allowConstr syn) open l
487 justPrefix :: FixDecl -> Maybe Name
488 justPrefix (Fix (PrefixN _) opName) = Just (sUN opName)
489 justPrefix _ = Nothing
491 guardNotPrefix :: Name -> IdrisParser ()
492 guardNotPrefix opName = do
493 guard $ opName /= sUN "-"
494 guard $ opName /= sUN "!"
496 ops <- idris_infixes <$> get
497 guard . not . (opName `elem`) . mapMaybe justPrefix $ ops
499{-| Parses the rest of a dependent pair after '(' or '(Expr **' -}
500dependentPair :: PunInfo -> [(PTerm, Maybe (FC, PTerm), FC)] -> FC -> SyntaxInfo -> IdrisParser PTerm
501dependentPair pun prev openFC syn =
503 nametypePart <|> namePart
506 IsType -> nametypePart <|> namePart <|> exprPart True
507 IsTerm -> exprPart False
508 TypeOrTerm -> nametypePart <|> namePart <|> exprPart False
509 where nametypePart = do
510 (ln, lnfc, colonFC) <- P.try $ do
512 colonFC <- lcharFC ':'
513 return (ln, lnfc, colonFC)
515 starsFC <- reservedOpFC "**"
516 dependentPair IsType ((PRef lnfc [] ln, Just (colonFC, lty), starsFC):prev) openFC syn
517 namePart = P.try $ do
519 starsFC <- reservedOpFC "**"
520 dependentPair pun ((PRef lnfc [] ln, Nothing, starsFC):prev) openFC syn
524 let stars = (Left <$> reservedOpFC "**")
525 ending = (Right <$> lcharFC ')')
526 in if isEnd then ending else stars <|> ending
528 Left starsFC -> dependentPair IsTerm ((e, Nothing, starsFC):prev) openFC syn
530 return (mkPDPairs pun openFC closeFC (reverse prev) e)
531 mkPDPairs pun openFC closeFC ((e, cfclty, starsFC):bnds) r =
532 (PDPair openFC ([openFC] ++ maybe [] ((: []) . fst) cfclty ++ [starsFC, closeFC] ++ (=<<) (\(_,cfclty,sfc) -> maybe [] ((: []) . fst) cfclty ++ [sfc]) bnds)
533 pun e (maybe Placeholder snd cfclty) (mergePDPairs pun starsFC bnds r))
534 mergePDPairs pun starsFC' [] r = r
535 mergePDPairs pun starsFC' ((e, cfclty, starsFC):bnds) r =
536 PDPair starsFC' [] pun e (maybe Placeholder snd cfclty) (mergePDPairs pun starsFC bnds r)
538-- | Parse the contents of parentheses, after an expression has been parsed.
539bracketedExpr :: SyntaxInfo -> FC -> PTerm -> IdrisParser PTerm
540bracketedExpr syn openParenFC e =
541 do lchar ')'; return e
542 <|> do exprs <- some (do comma <- lcharFC ','
545 closeParenFC <- lcharFC ')'
546 let hilite = [openParenFC, closeParenFC] ++ map snd exprs
547 return $ PPair openParenFC hilite TypeOrTerm e (mergePairs exprs)
548 <|> do starsFC <- reservedOpFC "**"
549 dependentPair IsTerm [(e, Nothing, starsFC)] openParenFC syn
550 <?> "end of bracketed expression"
551 where mergePairs :: [(PTerm, FC)] -> PTerm
552 mergePairs [(t, fc)] = t
553 mergePairs ((t, fc):rs) = PPair fc [] TypeOrTerm t (mergePairs rs)
555-- bit of a hack here. If the integer doesn't fit in an Int, treat it as a
556-- big integer, otherwise try fromInteger and the constants as alternatives.
557-- a better solution would be to fix fromInteger to work with Integer, as the
558-- name suggests, rather than Int
559{-| Finds optimal type for integer constant -}
560modifyConst :: SyntaxInfo -> FC -> PTerm -> PTerm
561modifyConst syn fc (PConstant inFC (BI x))
562 | not (inPattern syn)
563 = PConstSugar inFC $ -- wrap in original location for highlighting
564 PAlternative [] FirstSuccess
565 (PApp fc (PRef fc [] (sUN "fromInteger")) [pexp (PConstant NoFC (BI (fromInteger x)))]
567 | otherwise = PConstSugar inFC $
568 PAlternative [] FirstSuccess consts
570 consts = [ PConstant inFC (BI x)
571 , PConstant inFC (I (fromInteger x))
572 , PConstant inFC (B8 (fromInteger x))
573 , PConstant inFC (B16 (fromInteger x))
574 , PConstant inFC (B32 (fromInteger x))
575 , PConstant inFC (B64 (fromInteger x))
577modifyConst syn fc x = x
579{- | Parses an alternative expression
581 Alt ::= '(|' Expr_List '|)';
585 | Expr' ',' Expr_List
589alt :: SyntaxInfo -> IdrisParser PTerm
590alt syn = do symbol "(|"; alts <- P.sepBy1 (expr' (syn { withAppAllowed = False })) (lchar ','); symbol "|)"
591 return (PAlternative [] FirstSuccess alts)
593{- | Parses a possibly hidden simple expression
601hsimpleExpr :: SyntaxInfo -> IdrisParser PTerm
609{- | Parses a unification log expression
611 '%' 'unifyLog' SimpleExpr
614unifyLog :: SyntaxInfo -> IdrisParser PTerm
615unifyLog syn = do (FC fn (sl, sc) kwEnd) <- P.try (lchar '%' *> reservedFC "unifyLog")
617 highlightP (FC fn (sl, sc-1) kwEnd) AnnKeyword
618 return (PUnifyLog tm)
619 <?> "unification log expression"
621{- | Parses a new-style tactics expression
623 '%' 'runElab' SimpleExpr
626runElab :: SyntaxInfo -> IdrisParser PTerm
627runElab syn = do (FC fn (sl, sc) kwEnd) <- P.try (lchar '%' *> reservedFC "runElab")
630 highlightP (FC fn (sl, sc-1) kwEnd) AnnKeyword
631 return $ PRunElab fc tm (syn_namespace syn)
632 <?> "new-style tactics expression"
634{- | Parses a disambiguation expression
639disamb :: SyntaxInfo -> IdrisParser PTerm
640disamb syn = do kw <- reservedFC "with"
641 ns <- P.sepBy1 (fst <$> name) (lchar ',')
643 highlightP kw AnnKeyword
644 return (PDisamb (map tons ns) tm)
645 <?> "namespace disambiguation expression"
646 where tons (NS n s) = txt (show n) : s
647 tons n = [txt (show n)]
648{- | Parses a no implicits expression
651 '%' 'noImplicits' SimpleExpr
655noImplicits :: SyntaxInfo -> IdrisParser PTerm
656noImplicits syn = do P.try (lchar '%' *> reserved "noImplicits")
658 return (PNoImplicits tm)
659 <?> "no implicits expression"
661{- | Parses a function application expression
669 SimpleExpr '<==' FnName
673app :: SyntaxInfo -> IdrisParser PTerm
674app syn = do f <- simpleExpr syn
675 (do P.try $ reservedOp "<=="
678 return (PLet fc RigW (sMN 0 "match") NoFC
681 (PRef fc [] (sMN 0 "match")))
682 <?> "matching application expression") <|>
685 args <- many (do notEndApp; arg syn)
686 wargs <- if withAppAllowed syn && not (inPattern syn)
687 then many (do notEndApp; reservedOp "|"; expr' syn)
691 _ -> return (withApp fc (flattenFromInt fc f args) wargs))
692 <?> "function application"
694 -- bit of a hack to deal with the situation where we're applying a
695 -- literal to an argument, which we may want for obscure applications
696 -- of fromInteger, and this will help disambiguate better.
697 -- We know, at least, it won't be one of the constants!
698 flattenFromInt fc (PAlternative _ x alts) args
699 | Just i <- getFromInt alts
700 = PApp fc (PRef fc [] (sUN "fromInteger")) (i : args)
701 flattenFromInt fc f args = PApp fc f args
703 withApp fc tm [] = tm
704 withApp fc tm (a : as) = withApp fc (PWithApp fc tm a) as
706 getFromInt ((PApp _ (PRef _ _ n) [a]) : _) | n == sUN "fromInteger" = Just a
707 getFromInt (_ : xs) = getFromInt xs
708 getFromInt _ = Nothing
710{-| Parses a function argument
719arg :: SyntaxInfo -> IdrisParser PArg
720arg syn = implicitArg syn
721 <|> constraintArg syn
722 <|> do e <- simpleExpr syn
724 <?> "function argument"
726{-| Parses an implicit function argument
729 '{' Name ('=' Expr)? '}'
733implicitArg :: SyntaxInfo -> IdrisParser PArg
734implicitArg syn = do lchar '{'
737 v <- P.option (PRef nfc [nfc] n) (do lchar '='
740 return (pimp n v True)
741 <?> "implicit function argument"
743{-| Parses a constraint argument (for selecting a named interface implementation)
750constraintArg :: SyntaxInfo -> IdrisParser PArg
751constraintArg syn = do symbol "@{"
755 <?> "constraint argument"
757{-| Parses a quasiquote expression (for building reflected terms using the elaborator)
759> Quasiquote ::= '`(' Expr ')'
762quasiquote :: SyntaxInfo -> IdrisParser PTerm
763quasiquote syn = do startFC <- symbolFC "`("
764 e <- expr syn { syn_in_quasiquote = (syn_in_quasiquote syn) + 1 ,
767 do fc <- symbolFC ":"
768 ty <- expr syn { inPattern = False } -- don't allow antiquotes
770 endFC <- symbolFC ")"
771 mapM_ (uncurry highlightP) [(startFC, AnnKeyword), (endFC, AnnKeyword), (spanFC startFC endFC, AnnQuasiquote)]
773 Just (_, fc) -> highlightP fc AnnKeyword
775 return $ PQuasiquote e (fst <$> g)
778{-| Parses an unquoting inside a quasiquotation (for building reflected terms using the elaborator)
780> Unquote ::= ',' Expr
783unquote :: SyntaxInfo -> IdrisParser PTerm
784unquote syn = do guard (syn_in_quasiquote syn > 0)
785 startFC <- symbolFC "~"
786 e <- simpleExpr syn { syn_in_quasiquote = syn_in_quasiquote syn - 1 }
788 highlightP startFC AnnKeyword
789 highlightP (spanFC startFC endFC) AnnAntiquote
793{-| Parses a quotation of a name (for using the elaborator to resolve boring details)
795> NameQuote ::= '`{' Name '}'
798namequote :: SyntaxInfo -> IdrisParser PTerm
799namequote syn = do (startFC, res) <-
800 P.try (do fc <- symbolFC "`{{"
801 return (fc, False)) <|>
802 (do fc <- symbolFC "`{"
805 endFC <- if res then symbolFC "}" else symbolFC "}}"
806 mapM_ (uncurry highlightP)
807 [ (startFC, AnnKeyword)
808 , (endFC, AnnKeyword)
809 , (spanFC startFC endFC, AnnQuasiquote)
811 return $ PQuoteName n res nfc
815{-| Parses a record field setter expression
818 'record' '{' FieldTypeList '}';
823 | FieldType ',' FieldTypeList
833data SetOrUpdate = FieldSet PTerm | FieldUpdate PTerm
835recordType :: SyntaxInfo -> IdrisParser PTerm
837 do kw <- reservedFC "record"
842 rec <- optional (do notEndApp; simpleExpr syn)
843 highlightP kw AnnKeyword
848 return (PLam fc (sMN 0 "fldx") NoFC Placeholder
849 (applyAll fc fields (PRef fc [] (sMN 0 "fldx"))))
850 Just v -> return (applyAll fc fields v)
854 return (PLam fc (sMN 0 "fldx") NoFC Placeholder
855 (getAll fc (reverse fields)
856 (PRef fc [] (sMN 0 "fldx"))))
857 Just v -> return (getAll fc (reverse fields) v)
859 <?> "record setting expression"
860 where fieldSet :: IdrisParser ([Name], SetOrUpdate)
861 fieldSet = do ns <- fieldGet
864 return (ns, FieldSet e))
867 return (ns, FieldUpdate e)
870 fieldGet :: IdrisParser [Name]
871 fieldGet = P.sepBy1 (fst <$> fnName) (symbol "->")
873 fieldGetOrSet :: IdrisParser (Either [([Name], SetOrUpdate)] [Name])
874 fieldGetOrSet = P.try (Left <$> P.sepBy1 fieldSet (lchar ','))
878 applyAll :: FC -> [([Name], SetOrUpdate)] -> PTerm -> PTerm
880 applyAll fc ((ns, e) : es) x
881 = applyAll fc es (doUpdate fc ns e x)
883 doUpdate fc ns (FieldUpdate e) get
884 = let get' = getAll fc (reverse ns) get in
885 doUpdate fc ns (FieldSet (PApp fc e [pexp get'])) get
886 doUpdate fc [n] (FieldSet e) get
887 = PApp fc (PRef fc [] (mkType n)) [pexp e, pexp get]
888 doUpdate fc (n : ns) e get
889 = PApp fc (PRef fc [] (mkType n))
890 [pexp (doUpdate fc ns e (PApp fc (PRef fc [] n) [pexp get])),
893 getAll :: FC -> [Name] -> PTerm -> PTerm
894 getAll fc [n] e = PApp fc (PRef fc [] n) [pexp e]
895 getAll fc (n:ns) e = PApp fc (PRef fc [] n) [pexp (getAll fc ns e)]
898-- | Creates setters for record types on necessary functions
899mkType :: Name -> Name
900mkType (UN n) = sUN ("set_" ++ str n)
901mkType (MN 0 n) = sMN 0 ("set_" ++ str n)
902mkType (NS n s) = NS (mkType n) s
904{- | Parses a type signature
911TypeExpr ::= ConstraintList? Expr;
914typeExpr :: SyntaxInfo -> IdrisParser PTerm
915typeExpr syn = do cs <- if implicitAllowed syn then constraintList syn else return []
916 sc <- expr (allowConstr syn)
917 return (bindList (\r -> PPi (constraint { pcount = r })) cs sc)
920{- | Parses a lambda expression
923 '\\' TypeOptDeclList LambdaTail
924 | '\\' SimpleExprList LambdaTail
930 | SimpleExpr ',' SimpleExprList
939lambda :: SyntaxInfo -> IdrisParser PTerm
940lambda syn = do lchar '\\' <?> "lambda expression"
941 ((do xt <- P.try $ tyOptDeclList (disallowImp syn)
944 return (bindList (\r -> PLam fc) xt sc))
946 (do ps <- P.sepBy (do fc <- getFC
947 e <- simpleExpr (disallowImp (syn { inPattern = True }))
951 return (pmList (zip [0..] ps) sc)))
952 <?> "lambda expression"
953 where pmList :: [(Int, (FC, PTerm))] -> PTerm -> PTerm
955 pmList ((i, (fc, x)) : xs) sc
956 = PLam fc (sMN i "lamp") NoFC Placeholder
957 (PCase fc (PRef fc [] (sMN i "lamp"))
959 lambdaTail :: IdrisParser PTerm
960 lambdaTail = impossible <|> symbol "=>" *> expr syn
962{- | Parses a term rewrite expression
965 'rewrite' Expr ('==>' Expr)? 'in' Expr
969rewriteTerm :: SyntaxInfo -> IdrisParser PTerm
970rewriteTerm syn = do kw <- reservedFC "rewrite"
973 giving <- optional (do symbol "==>"; expr' syn)
974 using <- optional (do reserved "using"
977 kw' <- reservedFC "in"; sc <- expr syn
978 highlightP kw AnnKeyword
979 highlightP kw' AnnKeyword
980 return (PRewrite fc using prf sc giving)
981 <?> "term rewrite expression"
983{- |Parses a let binding
986 'let' Name TypeSig'? '=' Expr 'in' Expr
987| 'let' Expr' '=' Expr' 'in' Expr
994let_ :: SyntaxInfo -> IdrisParser PTerm
995let_ syn = P.try (do kw <- reservedFC "let"
996 ls <- indentedBlock (let_binding syn)
997 kw' <- reservedFC "in"; sc <- expr syn
998 highlightP kw AnnKeyword; highlightP kw' AnnKeyword
999 return (buildLets ls sc))
1001 where buildLets [] sc = sc
1002 buildLets ((fc, PRef nfc _ n, ty, v, []) : ls) sc
1003 = PLet fc RigW n nfc ty v (buildLets ls sc)
1004 buildLets ((fc, pat, ty, v, alts) : ls) sc
1005 = PCase fc v ((pat, buildLets ls sc) : alts)
1007let_binding syn = do fc <- getFC;
1008 pat <- expr' (syn { inPattern = True })
1009 ty <- P.option Placeholder (do lchar ':'; expr' syn)
1011 v <- expr (syn { withAppAllowed = isVar pat })
1012 ts <- P.option [] (do lchar '|'
1013 P.sepBy1 (do_alt syn) (lchar '|'))
1014 return (fc,pat,ty,v,ts)
1015 where isVar (PRef _ _ _) = True
1018{- | Parses a conditional expression
1020If ::= 'if' Expr 'then' Expr 'else' Expr
1024if_ :: SyntaxInfo -> IdrisParser PTerm
1025if_ syn = (do ifFC <- reservedFC "if"
1028 thenFC <- reservedFC "then"
1030 elseFC <- reservedFC "else"
1032 mapM_ (flip highlightP AnnKeyword) [ifFC, thenFC, elseFC]
1033 return (PIfThenElse fc c t f))
1034 <?> "conditional expression"
1037{- | Parses a quote goal
1041 'quoteGoal' Name 'by' Expr 'in' Expr
1045quoteGoal :: SyntaxInfo -> IdrisParser PTerm
1046quoteGoal syn = do kw1 <- reservedFC "quoteGoal"; n <- fst <$> name;
1047 kw2 <- reservedFC "by"
1049 kw3 <- reservedFC "in"
1052 mapM_ (flip highlightP AnnKeyword) [kw1, kw2, kw3]
1053 return (PGoal fc r n sc)
1054 <?> "quote goal expression"
1056{- | Parses a dependent type signature
1059Pi ::= PiOpts Static? Pi'
1065 | '(' TypeDeclList ')' '->' Pi
1066 | '{' TypeDeclList '}' '->' Pi
1067 | '{' 'auto' TypeDeclList '}' '->' Pi
1068 | '{' 'default' SimpleExpr TypeDeclList '}' '->' Pi
1073bindsymbol opts st syn
1075 return (Exp opts st False RigW)
1077explicitPi opts st syn
1078 = do xt <- P.try (lchar '(' *> typeDeclList syn <* lchar ')')
1079 binder <- bindsymbol opts st syn
1080 sc <- expr (allowConstr syn)
1081 return (bindList (\r -> PPi (binder { pcount = r })) xt sc)
1083autoImplicit opts st syn
1084 = do kw <- reservedFC "auto"
1085 when (st == Static) $ fail "auto implicits can not be static"
1086 xt <- typeDeclList syn
1089 sc <- expr (allowConstr syn)
1090 highlightP kw AnnKeyword
1091 return (bindList (\r -> PPi
1092 (TacImp [] Dynamic (PTactics [ProofSearch True True 100 Nothing [] []]) r)) xt sc)
1094defaultImplicit opts st syn = do
1095 kw <- reservedFC "default"
1096 when (st == Static) $ fail "default implicits can not be static"
1098 script' <- simpleExpr syn
1099 let script = debindApp syn . desugar syn ist $ script'
1100 xt <- typeDeclList syn
1103 sc <- expr (allowConstr syn)
1104 highlightP kw AnnKeyword
1105 return (bindList (\r -> PPi (TacImp [] Dynamic script r)) xt sc)
1107normalImplicit opts st syn = do
1108 xt <- typeDeclList syn <* lchar '}'
1110 cs <- constraintList syn
1113 = if implicitAllowed syn
1114 then (Imp opts st False (Just (Impl False True False)) True RigW,
1116 else (Imp opts st False (Just (Impl False False False)) True RigW,
1117 Imp opts st False (Just (Impl True False False)) True RigW)
1118 return (bindList (\r -> PPi (im { pcount = r })) xt
1119 (bindList (\r -> PPi (cl { pcount = r })) cs sc))
1121constraintPi opts st syn =
1122 do cs <- constraintList1 syn
1124 if implicitAllowed syn
1125 then return (bindList (\r -> PPi constraint { pcount = r }) cs sc)
1126 else return (bindList (\r -> PPi (Imp opts st False (Just (Impl True False False)) True r))
1129implicitPi opts st syn =
1130 autoImplicit opts st syn
1131 <|> defaultImplicit opts st syn
1132 <|> normalImplicit opts st syn
1134unboundPi opts st syn = do
1136 (do binder <- bindsymbol opts st syn
1138 return (PPi binder (sUN "__pi_arg") NoFC x sc))
1141-- This is used when we need to disambiguate from a constraint list
1142unboundPiNoConstraint opts st syn = do
1144 (do binder <- bindsymbol opts st syn
1146 P.notFollowedBy $ reservedOp "=>"
1147 return (PPi binder (sUN "__pi_arg") NoFC x sc))
1148 <|> do P.notFollowedBy $ reservedOp "=>"
1152pi :: SyntaxInfo -> IdrisParser PTerm
1154 do opts <- piOpts syn
1156 explicitPi opts st syn
1157 <|> P.try (do lchar '{'; implicitPi opts st syn)
1158 <|> if constraintAllowed syn
1159 then P.try (unboundPiNoConstraint opts st syn)
1160 <|> constraintPi opts st syn
1161 else unboundPi opts st syn
1162 <?> "dependent type signature"
1164{- | Parses Possible Options for Pi Expressions
1169piOpts :: SyntaxInfo -> IdrisParser [ArgOpt]
1170piOpts syn | implicitAllowed syn =
1171 lchar '.' *> return [InaccessibleArg]
1173piOpts syn = return []
1175{- | Parses a type constraint list
1179 '(' Expr_List ')' '=>'
1184constraintList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1185constraintList syn = P.try (constraintList1 syn)
1188constraintList1 :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1189constraintList1 syn = P.try (do lchar '('
1190 tys <- P.sepBy1 nexpr (lchar ',')
1194 <|> P.try (do t <- opExpr (disallowImp syn)
1196 return [(RigW, defname, NoFC, t)])
1197 <?> "type constraint list"
1198 where nexpr = P.try (do (n, fc) <- name; lchar ':'
1199 e <- expr (disallowImp syn)
1200 return (RigW, n, fc, e))
1201 <|> do e <- expr (disallowImp syn)
1202 return (RigW, defname, NoFC, e)
1203 defname = sMN 0 "constraint"
1205{- | Parses a type declaration list
1208 FunctionSignatureList
1214FunctionSignatureList ::=
1216 | Name TypeSig ',' FunctionSignatureList
1220typeDeclList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1221typeDeclList syn = P.try (P.sepBy1 (do rig <- P.option RigW rigCount
1224 t <- typeExpr (disallowImp syn)
1225 return (rig, x, xfc, t))
1227 <|> do ns <- P.sepBy1 name (lchar ',')
1229 t <- typeExpr (disallowImp syn)
1230 return (map (\(x, xfc) -> (RigW, x, xfc, t)) ns)
1231 <?> "type declaration list"
1233 rigCount = do lchar '1'; return Rig1
1234 <|> do lchar '0'; return Rig0
1236{- | Parses a type declaration list with optional parameters
1239 NameOrPlaceholder TypeSig?
1240 | NameOrPlaceholder TypeSig? ',' TypeOptDeclList
1245NameOrPlaceHolder ::= Name | '_';
1248tyOptDeclList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1249tyOptDeclList syn = P.sepBy1 (do (x, fc) <- nameOrPlaceholder
1250 t <- P.option Placeholder (do lchar ':'
1252 return (RigW, x, fc, t))
1254 <?> "type declaration list"
1255 where nameOrPlaceholder :: IdrisParser (Name, FC)
1256 nameOrPlaceholder = fnName
1258 return (sMN 0 "underscore", NoFC)
1259 <?> "name or placeholder"
1261{- | Parses a list literal expression e.g. [1,2,3] or a comprehension [ (x, y) | x <- xs , y <- ys ]
1265 | '[' Expr '|' DoList ']'
1282listExpr :: SyntaxInfo -> IdrisParser PTerm
1283listExpr syn = do (FC f (l, c) _) <- getFC
1284 lchar '['; fc <- getFC;
1285 (P.try . token $ do (char ']' <?> "end of list expression")
1286 (FC _ _ (l', c')) <- getFC
1287 return (mkNil (FC f (l, c) (l', c'))))
1288 <|> (do x <- expr (syn { withAppAllowed = False }) <?> "expression"
1289 (do P.try (lchar '|') <?> "list comprehension"
1290 qs <- P.sepBy1 (do_ syn) (lchar ',')
1292 return (PDoBlock (map addGuard qs ++
1293 [DoExp fc (PApp fc (PRef fc [] (sUN "pure"))
1295 (do xs <- many (do (FC fn (sl, sc) _) <- getFC
1296 lchar ',' <?> "list element"
1297 let commaFC = FC fn (sl, sc) (sl, sc + 1)
1299 return (elt, commaFC))
1300 (FC fn (sl, sc) _) <- getFC
1301 lchar ']' <?> "end of list expression"
1302 let rbrackFC = FC fn (sl, sc) (sl, sc+1)
1303 return (mkList fc rbrackFC ((x, (FC f (l, c) (l, c+1))) : xs))))
1304 <?> "list expression"
1306 mkNil :: FC -> PTerm
1307 mkNil fc = PRef fc [fc] (sUN "Nil")
1308 mkList :: FC -> FC -> [(PTerm, FC)] -> PTerm
1309 mkList errFC nilFC [] = PRef nilFC [nilFC] (sUN "Nil")
1310 mkList errFC nilFC ((x, fc) : xs) = PApp errFC (PRef fc [fc] (sUN "::")) [pexp x, pexp (mkList errFC nilFC xs)]
1311 addGuard :: PDo -> PDo
1312 addGuard (DoExp fc e) = DoExp fc (PApp fc (PRef fc [] (sUN "guard"))
1316{- | Parses a do-block
1318Do' ::= Do KeepTerminator;
1323 'do' OpenBlock Do'+ CloseBlock
1327doBlock :: SyntaxInfo -> IdrisParser PTerm
1329 = do kw <- reservedFC "do"
1330 ds <- indentedBlock1 (do_ syn)
1331 highlightP kw AnnKeyword
1332 return (PDoBlock ds)
1335{- | Parses an expression inside a do block
1338 'let' Name TypeSig'? '=' Expr
1339 | 'let' Expr' '=' Expr
1347do_ :: SyntaxInfo -> IdrisParser PDo
1349 = P.try (do kw <- reservedFC "let"
1351 ty <- P.option Placeholder (do lchar ':'
1356 highlightP kw AnnKeyword
1357 return (DoLet fc RigW i ifc ty e))
1358 <|> P.try (do kw <- reservedFC "let"
1363 highlightP kw AnnKeyword
1364 return (DoLetP fc i sc))
1365 <|> P.try (do kw <- reservedFC "rewrite"
1368 highlightP kw AnnKeyword
1369 return (DoRewrite fc sc))
1370 <|> P.try (do (i, ifc) <- name
1373 e <- expr (syn { withAppAllowed = False });
1374 P.option (DoBind fc i ifc e)
1376 ts <- P.sepBy1 (do_alt (syn { withAppAllowed = False })) (lchar '|')
1377 return (DoBindP fc (PRef ifc [ifc] i) e ts)))
1378 <|> P.try (do i <- expr' syn
1381 e <- expr (syn { withAppAllowed = False });
1382 P.option (DoBindP fc i e [])
1384 ts <- P.sepBy1 (do_alt (syn { withAppAllowed = False })) (lchar '|')
1385 return (DoBindP fc i e ts)))
1386 <|> do e <- expr syn
1389 <?> "do block expression"
1391do_alt syn = do l <- expr' syn
1392 P.option (Placeholder, l)
1397{- | Parses an expression in idiom brackets
1399Idiom ::= '[|' Expr '|]';
1402idiom :: SyntaxInfo -> IdrisParser PTerm
1406 e <- expr (syn { withAppAllowed = False })
1408 return (PIdiom fc e)
1409 <?> "expression in idiom brackets"
1411{- |Parses a constant or literal expression
1433constants :: [(String, Idris.Core.TT.Const)]
1435 [ ("Integer", AType (ATInt ITBig))
1436 , ("Int", AType (ATInt ITNative))
1437 , ("Char", AType (ATInt ITChar))
1438 , ("Double", AType ATFloat)
1439 , ("String", StrType)
1440 , ("prim__WorldType", WorldType)
1441 , ("prim__TheWorld", TheWorld)
1442 , ("Bits8", AType (ATInt (ITFixed IT8)))
1443 , ("Bits16", AType (ATInt (ITFixed IT16)))
1444 , ("Bits32", AType (ATInt (ITFixed IT32)))
1445 , ("Bits64", AType (ATInt (ITFixed IT64)))
1448-- | Parse a constant and its source span
1449constant :: IdrisParser (Idris.Core.TT.Const, FC)
1450constant = P.choice [ do fc <- reservedFC name; return (ty, fc)
1451 | (name, ty) <- constants
1453 <|> do (f, fc) <- P.try float; return (Fl f, fc)
1454 <|> do (i, fc) <- natural; return (BI i, fc)
1455 <|> do (s, fc) <- verbatimStringLiteral; return (Str s, fc)
1456 <|> do (s, fc) <- stringLiteral; return (Str s, fc)
1457 <|> do (c, fc) <- P.try charLiteral; return (Ch c, fc) --Currently ambigous with symbols
1458 <?> "constant or literal"
1460{- | Parses a verbatim multi-line string literal (triple-quoted)
1464 '\"\"\"' ~'\"\"\"' '\"\"\"'
1468verbatimStringLiteral :: IdrisParser (String, FC)
1469verbatimStringLiteral = token $ do (FC f start _) <- getFC
1470 P.try $ string "\"\"\""
1471 str <- P.manyTill P.anyChar $ P.try (string "\"\"\"")
1472 (FC _ _ end) <- getFC
1473 return (str, FC f start end)
1475{- | Parses a static modifier
1483static :: IdrisParser Static
1484static = do reserved "%static"; return Static
1485 <|> do reserved "[static]"
1487 parserWarning fc Nothing (Msg "The use of [static] is deprecated, use %static instead.")
1490 <?> "static modifier"
1492{- | Parses a tactic script
1495Tactic ::= 'intro' NameList?
1497 | 'refine' Name Imp+
1502 | 'let' Name ':' Expr' '=' Expr
1503 | 'let' Name '=' Expr
1506 | 'applyTactic' Expr
1509 | 'try' Tactic '|' Tactic
1527 | Tactic ';' TacticSeq
1532-- | A specification of the arguments that tactics can take
1533data TacticArg = NameTArg -- ^ Names: n1, n2, n3, ... n
1538-- The FIXMEs are Issue #1766 in the issue tracker.
1539-- https://github.com/idris-lang/Idris-dev/issues/1766
1540-- | A list of available tactics and their argument requirements
1541tactics :: [([String], Maybe TacticArg, SyntaxInfo -> IdrisParser PTactic)]
1543 [ (["intro"], Nothing, const $ -- FIXME syntax for intro (fresh name)
1544 do ns <- P.sepBy (spaced (fst <$> name)) (lchar ','); return $ Intro ns)
1545 , noArgs ["intros"] Intros
1546 , noArgs ["unfocus"] Unfocus
1547 , (["refine"], Just ExprTArg, const $
1548 do n <- spaced (fst <$> fnName)
1550 return $ Refine n imps)
1551 , (["claim"], Nothing, \syn ->
1552 do n <- indentGt *> (fst <$> name)
1553 goal <- indentGt *> expr syn
1554 return $ Claim n goal)
1555 , (["mrefine"], Just ExprTArg, const $
1556 do n <- spaced (fst <$> fnName)
1557 return $ MatchRefine n)
1558 , expressionTactic ["rewrite"] Rewrite
1559 , expressionTactic ["case"] CaseTac
1560 , expressionTactic ["induction"] Induction
1561 , expressionTactic ["equiv"] Equiv
1562 , (["let"], Nothing, \syn -> -- FIXME syntax for let
1563 do n <- (indentGt *> (fst <$> name))
1564 (do indentGt *> lchar ':'
1565 ty <- indentGt *> expr' syn
1566 indentGt *> lchar '='
1567 t <- indentGt *> expr syn
1569 return $ LetTacTy n (desugar syn i ty) (desugar syn i t))
1570 <|> (do indentGt *> lchar '='
1571 t <- indentGt *> expr syn
1573 return $ LetTac n (desugar syn i t)))
1575 , (["focus"], Just ExprTArg, const $
1576 do n <- spaced (fst <$> name)
1578 , expressionTactic ["exact"] Exact
1579 , expressionTactic ["applyTactic"] ApplyTactic
1580 , expressionTactic ["byReflection"] ByReflection
1581 , expressionTactic ["reflect"] Reflect
1582 , expressionTactic ["fill"] Fill
1583 , (["try"], Just AltsTArg, \syn ->
1584 do t <- spaced (tactic syn)
1586 t1 <- spaced (tactic syn)
1588 , noArgs ["compute"] Compute
1589 , noArgs ["trivial"] Trivial
1590 , noArgs ["unify"] DoUnify
1591 , (["search"], Nothing, const $
1592 do depth <- P.option 10 $ fst <$> natural
1593 return (ProofSearch True True (fromInteger depth) Nothing [] []))
1594 , noArgs ["implementation"] TCImplementation
1595 , noArgs ["solve"] Solve
1596 , noArgs ["attack"] Attack
1597 , noArgs ["state", ":state"] ProofState
1598 , noArgs ["term", ":term"] ProofTerm
1599 , noArgs ["undo", ":undo"] Undo
1600 , noArgs ["qed", ":qed"] Qed
1601 , noArgs ["abandon", ":q"] Abandon
1602 , noArgs ["skip"] Skip
1603 , noArgs ["sourceLocation"] SourceFC
1604 , expressionTactic [":e", ":eval"] TEval
1605 , expressionTactic [":t", ":type"] TCheck
1606 , expressionTactic [":search"] TSearch
1607 , (["fail"], Just StringLitTArg, const $
1608 do msg <- fst <$> stringLiteral
1609 return $ TFail [Idris.Core.TT.TextPart msg])
1610 , ([":doc"], Just ExprTArg, const $
1612 doc <- (Right . fst <$> constant) <|> (Left . fst <$> fnName)
1614 return (TDocStr doc))
1617 expressionTactic names tactic = (names, Just ExprTArg, \syn ->
1618 do t <- spaced (expr syn)
1620 return $ tactic (desugar syn i t))
1621 noArgs names tactic = (names, Nothing, const (return tactic))
1622 spaced parser = indentGt *> parser
1623 imp :: IdrisParser Bool
1624 imp = do lchar '?'; return False
1625 <|> do lchar '_'; return True
1628tactic :: SyntaxInfo -> IdrisParser PTactic
1629tactic syn = P.choice [ do P.choice (map reserved names); parser syn
1630 | (names, _, parser) <- tactics ]
1634 ts <- P.sepBy1 (tactic syn) (lchar ';')
1636 return $ TSeq t (mergeSeq ts)
1637 <|> ((lchar ':' >> empty) <?> "prover command")
1640 mergeSeq :: [PTactic] -> PTactic
1642 mergeSeq (t:ts) = TSeq t (mergeSeq ts)
1644-- | Parses a tactic as a whole
1645fullTactic :: SyntaxInfo -> IdrisParser PTactic
1646fullTactic syn = do t <- tactic syn
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list