2Module : Idris.Parser.Expr
3Description : Parse Expressions.
6Maintainer : The Idris Community.
8{-# LANGUAGE ConstraintKinds, GeneralizedNewtypeDeriving, PatternGuards,
10module Idris.Parser.Expr where
16import Idris.Parser.Helpers
17import Idris.Parser.Ops
19import Prelude hiding (pi)
21import Control.Applicative
23import Control.Monad.State.Strict
24import qualified Data.ByteString.UTF8 as UTF8
26import Data.Function (on)
27import qualified Data.HashSet as HS
29import qualified Data.List.Split as Spl
32import qualified Data.Text as T
34import qualified Text.Parser.Char as Chr
35import Text.Parser.Expression
36import Text.Parser.LookAhead
37import qualified Text.Parser.Token as Tok
38import qualified Text.Parser.Token.Highlight as Hi
39import Text.Trifecta hiding (Err, char, charLiteral, natural, span, string,
40 stringLiteral, symbol, whiteSpace)
41import Text.Trifecta.Delta
43-- | Allow implicit type declarations
44allowImp :: SyntaxInfo -> SyntaxInfo
45allowImp syn = syn { implicitAllowed = True,
46 constraintAllowed = False }
48-- | Disallow implicit type declarations
49disallowImp :: SyntaxInfo -> SyntaxInfo
50disallowImp = scopedImp
52-- | Implicits hare are scoped rather than top level
53scopedImp :: SyntaxInfo -> SyntaxInfo
54scopedImp syn = syn { implicitAllowed = False,
55 constraintAllowed = False }
57-- | Allow scoped constraint arguments
58allowConstr :: SyntaxInfo -> SyntaxInfo
59allowConstr syn = syn { constraintAllowed = True }
61{-| Parses an expression as a whole
63 FullExpr ::= Expr EOF_t;
66fullExpr :: SyntaxInfo -> IdrisParser PTerm
67fullExpr syn = do x <- expr syn
70 return $ debindApp syn (desugar syn i x)
72tryFullExpr :: SyntaxInfo -> IState -> String -> Either Err PTerm
73tryFullExpr syn st input =
74 case runparser (fullExpr syn) st "" input of
75 Success tm -> Right tm
76 Failure e -> Left (Msg (show e))
78{- | Parses an expression
83expr :: SyntaxInfo -> IdrisParser PTerm
86{- | Parses an expression with possible operator applied
88 OpExpr ::= {- Expression Parser with Operators based on Expr' -};
91opExpr :: SyntaxInfo -> IdrisParser PTerm
92opExpr syn = do i <- get
93 buildExpressionParser (table (idris_infixes i))
96{- | Parses either an internally defined expression or
99Expr' ::= "External (User-defined) Syntax"
103expr' :: SyntaxInfo -> IdrisParser PTerm
104expr' syn = try (externalExpr syn)
108{- | Parses a user-defined expression -}
109externalExpr :: SyntaxInfo -> IdrisParser PTerm
110externalExpr syn = do i <- get
111 (FC fn start _) <- getFC
112 expr <- extensions syn (syntaxRulesList $ syntax_rules i)
113 (FC _ _ end) <- getFC
114 let outerFC = FC fn start end
115 return (mapPTermFC (fixFC outerFC) (fixFCH fn outerFC) expr)
116 <?> "user-defined expression"
117 where -- Fix non-highlighting FCs by approximating with the span of the syntax application
118 fixFC outer inner | inner `fcIn` outer = inner
120 -- Fix highlighting FCs by making them useless, to avoid spurious highlights
121 fixFCH fn outer inner | inner `fcIn` outer = inner
122 | otherwise = FileFC fn
124{- | Parses a simple user-defined expression -}
125simpleExternalExpr :: SyntaxInfo -> IdrisParser PTerm
126simpleExternalExpr syn = do i <- get
127 extensions syn (filter isSimple (syntaxRulesList $ syntax_rules i))
129 isSimple (Rule (Expr x:xs) _ _) = False
130 isSimple (Rule (SimpleExpr x:xs) _ _) = False
131 isSimple (Rule [Keyword _] _ _) = True
132 isSimple (Rule [Symbol _] _ _) = True
133 isSimple (Rule (_:xs) _ _) = case last xs of
139{- | Tries to parse a user-defined expression given a list of syntactic extensions -}
140extensions :: SyntaxInfo -> [Syntax] -> IdrisParser PTerm
141extensions syn rules = extension syn [] (filter isValid rules)
142 <?> "user-defined expression"
144 isValid :: Syntax -> Bool
145 isValid (Rule _ _ AnySyntax) = True
146 isValid (Rule _ _ PatternSyntax) = inPattern syn
147 isValid (Rule _ _ TermSyntax) = not (inPattern syn)
148 isValid (DeclRule _ _) = False
150data SynMatch = SynTm PTerm | SynBind FC Name -- ^ the FC is for highlighting information
153extension :: SyntaxInfo -> [Maybe (Name, SynMatch)] -> [Syntax] -> IdrisParser PTerm
154extension syn ns rules =
155 choice $ flip map (groupBy (ruleGroup `on` syntaxSymbols) rules) $ \rs ->
156 case head rs of -- can never be []
157 Rule (symb:_) _ _ -> try $ do
158 n <- extensionSymbol symb
159 extension syn (n : ns) [Rule ss t ctx | (Rule (_:ss) t ctx) <- rs]
160 -- If we have more than one Rule in this bucket, our grammar is
162 Rule [] ptm _ -> return (flatten (updateSynMatch (mapMaybe id ns) ptm))
164 ruleGroup [] [] = True
165 ruleGroup (s1:_) (s2:_) = s1 == s2
166 ruleGroup _ _ = False
168 extensionSymbol :: SSymbol -> IdrisParser (Maybe (Name, SynMatch))
169 extensionSymbol (Keyword n) = do fc <- reservedFC (show n)
170 highlightP fc AnnKeyword
172 extensionSymbol (Expr n) = do tm <- expr syn
173 return $ Just (n, SynTm tm)
174 extensionSymbol (SimpleExpr n) = do tm <- simpleExpr syn
175 return $ Just (n, SynTm tm)
176 extensionSymbol (Binding n) = do (b, fc) <- name
177 return $ Just (n, SynBind fc b)
178 extensionSymbol (Symbol s) = do fc <- symbolFC s
179 highlightP fc AnnKeyword
182 flatten :: PTerm -> PTerm -- flatten application
183 flatten (PApp fc (PApp _ f as) bs) = flatten (PApp fc f (as ++ bs))
186updateSynMatch = update
188 updateB :: [(Name, SynMatch)] -> (Name, FC) -> (Name, FC)
189 updateB ns (n, fc) = case lookup n ns of
190 Just (SynBind tfc t) -> (t, tfc)
193 update :: [(Name, SynMatch)] -> PTerm -> PTerm
194 update ns (PRef fc hls n) = case lookup n ns of
197 update ns (PPatvar fc n) = uncurry (flip PPatvar) $ updateB ns (n, fc)
198 update ns (PLam fc n nfc ty sc)
199 = let (n', nfc') = updateB ns (n, nfc)
200 in PLam fc n' nfc' (update ns ty) (update (dropn n ns) sc)
201 update ns (PPi p n fc ty sc)
202 = let (n', nfc') = updateB ns (n, fc)
203 in PPi (updTacImp ns p) n' nfc'
204 (update ns ty) (update (dropn n ns) sc)
205 update ns (PLet fc n nfc ty val sc)
206 = let (n', nfc') = updateB ns (n, nfc)
207 in PLet fc n' nfc' (update ns ty)
208 (update ns val) (update (dropn n ns) sc)
209 update ns (PApp fc t args)
210 = PApp fc (update ns t) (map (fmap (update ns)) args)
211 update ns (PAppBind fc t args)
212 = PAppBind fc (update ns t) (map (fmap (update ns)) args)
213 update ns (PMatchApp fc n) = let (n', nfc') = updateB ns (n, fc)
215 update ns (PIfThenElse fc c t f)
216 = PIfThenElse fc (update ns c) (update ns t) (update ns f)
217 update ns (PCase fc c opts)
218 = PCase fc (update ns c) (map (pmap (update ns)) opts)
219 update ns (PRewrite fc by eq tm mty)
220 = PRewrite fc by (update ns eq) (update ns tm) (fmap (update ns) mty)
221 update ns (PPair fc hls p l r) = PPair fc hls p (update ns l) (update ns r)
222 update ns (PDPair fc hls p l t r)
223 = PDPair fc hls p (update ns l) (update ns t) (update ns r)
224 update ns (PAs fc n t) = PAs fc (fst $ updateB ns (n, NoFC)) (update ns t)
225 update ns (PAlternative ms a as) = PAlternative ms a (map (update ns) as)
226 update ns (PHidden t) = PHidden (update ns t)
227 update ns (PGoal fc r n sc) = PGoal fc (update ns r) n (update ns sc)
228 update ns (PDoBlock ds) = PDoBlock $ map (upd ns) ds
229 where upd :: [(Name, SynMatch)] -> PDo -> PDo
230 upd ns (DoExp fc t) = DoExp fc (update ns t)
231 upd ns (DoBind fc n nfc t) = DoBind fc n nfc (update ns t)
232 upd ns (DoLet fc n nfc ty t) = DoLet fc n nfc (update ns ty) (update ns t)
233 upd ns (DoBindP fc i t ts)
234 = DoBindP fc (update ns i) (update ns t)
235 (map (\(l,r) -> (update ns l, update ns r)) ts)
236 upd ns (DoLetP fc i t) = DoLetP fc (update ns i) (update ns t)
237 upd ns (DoRewrite fc h) = DoRewrite fc (update ns h)
238 update ns (PIdiom fc t) = PIdiom fc $ update ns t
239 update ns (PMetavar fc n) = uncurry (flip PMetavar) $ updateB ns (n, fc)
240 update ns (PProof tacs) = PProof $ map (updTactic ns) tacs
241 update ns (PTactics tacs) = PTactics $ map (updTactic ns) tacs
242 update ns (PDisamb nsps t) = PDisamb nsps $ update ns t
243 update ns (PUnifyLog t) = PUnifyLog $ update ns t
244 update ns (PNoImplicits t) = PNoImplicits $ update ns t
245 update ns (PQuasiquote tm mty) = PQuasiquote (update ns tm) (fmap (update ns) mty)
246 update ns (PUnquote t) = PUnquote $ update ns t
247 update ns (PQuoteName n res fc) = let (n', fc') = (updateB ns (n, fc))
248 in PQuoteName n' res fc'
249 update ns (PRunElab fc t nsp) = PRunElab fc (update ns t) nsp
250 update ns (PConstSugar fc t) = PConstSugar fc $ update ns t
251 -- PConstSugar probably can't contain anything substitutable, but it's hard to track
254 updTactic :: [(Name, SynMatch)] -> PTactic -> PTactic
255 -- handle all the ones with Names explicitly, then use fmap for the rest with PTerms
256 updTactic ns (Intro ns') = Intro $ map (fst . updateB ns . (, NoFC)) ns'
257 updTactic ns (Focus n) = Focus . fst $ updateB ns (n, NoFC)
258 updTactic ns (Refine n bs) = Refine (fst $ updateB ns (n, NoFC)) bs
259 updTactic ns (Claim n t) = Claim (fst $ updateB ns (n, NoFC)) (update ns t)
260 updTactic ns (MatchRefine n) = MatchRefine (fst $ updateB ns (n, NoFC))
261 updTactic ns (LetTac n t) = LetTac (fst $ updateB ns (n, NoFC)) (update ns t)
262 updTactic ns (LetTacTy n ty tm) = LetTacTy (fst $ updateB ns (n, NoFC)) (update ns ty) (update ns tm)
263 updTactic ns (ProofSearch rec prover depth top psns hints) = ProofSearch rec prover depth
264 (fmap (fst . updateB ns . (, NoFC)) top) (map (fst . updateB ns . (, NoFC)) psns) (map (fst . updateB ns . (, NoFC)) hints)
265 updTactic ns (Try l r) = Try (updTactic ns l) (updTactic ns r)
266 updTactic ns (TSeq l r) = TSeq (updTactic ns l) (updTactic ns r)
267 updTactic ns (GoalType s tac) = GoalType s $ updTactic ns tac
268 updTactic ns (TDocStr (Left n)) = TDocStr . Left . fst $ updateB ns (n, NoFC)
269 updTactic ns t = fmap (update ns) t
271 updTacImp ns (TacImp o st scr r) = TacImp o st (update ns scr) r
274 dropn :: Name -> [(Name, a)] -> [(Name, a)]
276 dropn n ((x,t) : xs) | n == x = xs
277 | otherwise = (x,t):dropn n xs
280{- | Parses a (normal) built-in expression
297internalExpr :: SyntaxInfo -> IdrisParser PTerm
314{- | Parses the "impossible" keyword
316Impossible ::= 'impossible'
319impossible :: IdrisParser PTerm
320impossible = do fc <- reservedFC "impossible"
321 highlightP fc AnnKeyword
324{- | Parses a case expression
327 'case' Expr 'of' OpenBlock CaseOption+ CloseBlock;
330caseExpr :: SyntaxInfo -> IdrisParser PTerm
331caseExpr syn = do kw1 <- reservedFC "case"; fc <- getFC
332 scr <- expr syn; kw2 <- reservedFC "of";
333 opts <- indentedBlock1 (caseOption syn)
334 highlightP kw1 AnnKeyword
335 highlightP kw2 AnnKeyword
336 return (PCase fc scr opts)
337 <?> "case expression"
339{- | Parses a case in a case expression
342 Expr (Impossible | '=>' Expr) Terminator
346caseOption :: SyntaxInfo -> IdrisParser (PTerm, PTerm)
347caseOption syn = do lhs <- expr (disallowImp (syn { inPattern = True }))
348 r <- impossible <|> symbol "=>" *> expr syn
352warnTacticDeprecation :: FC -> IdrisParser ()
353warnTacticDeprecation fc =
354 parserWarning fc (Just NoOldTacticDeprecationWarnings) (Msg "This style of tactic proof is deprecated. See %runElab for the replacement.")
356{- | Parses a proof block
359 'proof' OpenBlock Tactic'* CloseBlock
363proofExpr :: SyntaxInfo -> IdrisParser PTerm
364proofExpr syn = do kw <- reservedFC "proof"
365 ts <- indentedBlock1 (tactic syn)
366 highlightP kw AnnKeyword
367 warnTacticDeprecation kw
371{- | Parses a tactics block
374 'tactics' OpenBlock Tactic'* CloseBlock
378tacticsExpr :: SyntaxInfo -> IdrisParser PTerm
379tacticsExpr syn = do kw <- reservedFC "tactics"
380 ts <- indentedBlock1 (tactic syn)
381 highlightP kw AnnKeyword
382 warnTacticDeprecation kw
386{- | Parses a simple expression
389 {- External (User-defined) Simple Expression -}
392 | 'Refl' ('{' Expr '}')?
410simpleExpr :: SyntaxInfo -> IdrisParser PTerm
412 try (simpleExternalExpr syn)
413 <|> do (x, FC f (l, c) end) <- try (lchar '?' *> name)
414 return (PMetavar (FC f (l, c-1) end) x)
415 <|> do lchar '%'; fc <- getFC; reserved "implementation"; return (PResolveTC fc)
416 <|> do lchar '%'; fc <- getFC; reserved "instance"
417 parserWarning fc Nothing $ Msg "The use of %instance is deprecated, use %implementation instead."
418 return (PResolveTC fc)
419 <|> do reserved "elim_for"; fc <- getFC; t <- fst <$> fnName; return (PRef fc [] (SN $ ElimN t))
422 <|> try (do fc <- reservedFC "Type*"; return $ PUniverse fc AllTypes)
423 <|> do fc <- reservedFC "AnyType"; return $ PUniverse fc AllTypes
424 <|> PType <$> reservedFC "Type"
425 <|> do fc <- reservedFC "UniqueType"; return $ PUniverse fc UniqueType
426 <|> do fc <- reservedFC "NullType"; return $ PUniverse fc NullType
427 <|> do (c, cfc) <- constant
429 return (modifyConst syn fc (PConstant cfc c))
430 <|> do symbol "'"; fc <- getFC; str <- fst <$> name
431 return (PApp fc (PRef fc [] (sUN "Symbol_"))
432 [pexp (PConstant NoFC (Str (show str)))])
433 <|> do (x, fc) <- fnName
435 then option (PRef fc [fc] x)
439 return (PAs fcIn x s))
440 else return (PRef fc [fc] x)
444 <|> do reservedOp "!"
447 return (PAppBind fc s [])
448 <|> bracketed (disallowImp syn)
452 <|> do lchar '_'; return Placeholder
455{- |Parses an expression in parentheses
457Bracketed ::= '(' Bracketed'
460bracketed :: SyntaxInfo -> IdrisParser PTerm
461bracketed syn = do (FC fn (sl, sc) _) <- getFC
462 lchar '(' <?> "parenthesized expression"
463 bracketed' (FC fn (sl, sc) (sl, sc+1)) (syn { withAppAllowed = True })
465{- |Parses the rest of an expression in braces
477bracketed' :: FC -> SyntaxInfo -> IdrisParser PTerm
479 do (FC f start (l, c)) <- getFC
481 return $ PTrue (spanFC open (FC f start (l, c+1))) TypeOrTerm
482 <|> try (dependentPair TypeOrTerm [] open syn)
483 <|> try (do fc <- getFC; o <- operator; e <- expr syn; lchar ')'
484 -- No prefix operators! (bit of a hack here...)
485 if (o == "-" || o == "!")
486 then fail "minus not allowed in section"
487 else return $ PLam fc (sMN 1000 "ARG") NoFC Placeholder
488 (PApp fc (PRef fc [] (sUN o)) [pexp (PRef fc [] (sMN 1000 "ARG")),
490 <|> try (do l <- simpleExpr syn
491 op <- option Nothing (do o <- operator
496 Nothing -> bracketedExpr syn open l
497 Just o -> return $ PLam fc0 (sMN 1000 "ARG") NoFC Placeholder
498 (PApp fc0 (PRef fc0 [] (sUN o)) [pexp l,
499 pexp (PRef fc0 [] (sMN 1000 "ARG"))]))
500 <|> do l <- expr (allowConstr syn)
501 bracketedExpr (allowConstr syn) open l
505{-| Parses the rest of a dependent pair after '(' or '(Expr **' -}
506dependentPair :: PunInfo -> [(PTerm, Maybe (FC, PTerm), FC)] -> FC -> SyntaxInfo -> IdrisParser PTerm
507dependentPair pun prev openFC syn =
509 nametypePart <|> namePart
512 IsType -> nametypePart <|> namePart <|> exprPart True
513 IsTerm -> exprPart False
514 TypeOrTerm -> nametypePart <|> namePart <|> exprPart False
515 where nametypePart = do
516 (ln, lnfc, colonFC) <- try $ do
518 colonFC <- lcharFC ':'
519 return (ln, lnfc, colonFC)
521 starsFC <- reservedOpFC "**"
522 dependentPair IsType ((PRef lnfc [] ln, Just (colonFC, lty), starsFC):prev) openFC syn
525 starsFC <- reservedOpFC "**"
526 dependentPair pun ((PRef lnfc [] ln, Nothing, starsFC):prev) openFC syn
530 let stars = (Left <$> reservedOpFC "**")
531 ending = (Right <$> lcharFC ')')
532 in if isEnd then ending else stars <|> ending
534 Left starsFC -> dependentPair IsTerm ((e, Nothing, starsFC):prev) openFC syn
536 return (mkPDPairs pun openFC closeFC (reverse prev) e)
537 mkPDPairs pun openFC closeFC ((e, cfclty, starsFC):bnds) r =
538 (PDPair openFC ([openFC] ++ maybe [] ((: []) . fst) cfclty ++ [starsFC, closeFC] ++ (=<<) (\(_,cfclty,sfc) -> maybe [] ((: []) . fst) cfclty ++ [sfc]) bnds)
539 pun e (maybe Placeholder snd cfclty) (mergePDPairs pun starsFC bnds r))
540 mergePDPairs pun starsFC' [] r = r
541 mergePDPairs pun starsFC' ((e, cfclty, starsFC):bnds) r =
542 PDPair starsFC' [] pun e (maybe Placeholder snd cfclty) (mergePDPairs pun starsFC bnds r)
544-- | Parse the contents of parentheses, after an expression has been parsed.
545bracketedExpr :: SyntaxInfo -> FC -> PTerm -> IdrisParser PTerm
546bracketedExpr syn openParenFC e =
547 do lchar ')'; return e
548 <|> do exprs <- some (do comma <- lcharFC ','
551 closeParenFC <- lcharFC ')'
552 let hilite = [openParenFC, closeParenFC] ++ map snd exprs
553 return $ PPair openParenFC hilite TypeOrTerm e (mergePairs exprs)
554 <|> do starsFC <- reservedOpFC "**"
555 dependentPair IsTerm [(e, Nothing, starsFC)] openParenFC syn
556 <?> "end of bracketed expression"
557 where mergePairs :: [(PTerm, FC)] -> PTerm
558 mergePairs [(t, fc)] = t
559 mergePairs ((t, fc):rs) = PPair fc [] TypeOrTerm t (mergePairs rs)
561-- bit of a hack here. If the integer doesn't fit in an Int, treat it as a
562-- big integer, otherwise try fromInteger and the constants as alternatives.
563-- a better solution would be to fix fromInteger to work with Integer, as the
564-- name suggests, rather than Int
565{-| Finds optimal type for integer constant -}
566modifyConst :: SyntaxInfo -> FC -> PTerm -> PTerm
567modifyConst syn fc (PConstant inFC (BI x))
568 | not (inPattern syn)
569 = PConstSugar inFC $ -- wrap in original location for highlighting
570 PAlternative [] FirstSuccess
571 (PApp fc (PRef fc [] (sUN "fromInteger")) [pexp (PConstant NoFC (BI (fromInteger x)))]
573 | otherwise = PConstSugar inFC $
574 PAlternative [] FirstSuccess consts
576 consts = [ PConstant inFC (BI x)
577 , PConstant inFC (I (fromInteger x))
578 , PConstant inFC (B8 (fromInteger x))
579 , PConstant inFC (B16 (fromInteger x))
580 , PConstant inFC (B32 (fromInteger x))
581 , PConstant inFC (B64 (fromInteger x))
583modifyConst syn fc x = x
585{- | Parses an alternative expression
587 Alt ::= '(|' Expr_List '|)';
591 | Expr' ',' Expr_List
595alt :: SyntaxInfo -> IdrisParser PTerm
596alt syn = do symbol "(|"; alts <- sepBy1 (expr' (syn { withAppAllowed = False })) (lchar ','); symbol "|)"
597 return (PAlternative [] FirstSuccess alts)
599{- | Parses a possibly hidden simple expression
607hsimpleExpr :: SyntaxInfo -> IdrisParser PTerm
615{- | Parses a unification log expression
617 '%' 'unifyLog' SimpleExpr
620unifyLog :: SyntaxInfo -> IdrisParser PTerm
621unifyLog syn = do (FC fn (sl, sc) kwEnd) <- try (lchar '%' *> reservedFC "unifyLog")
623 highlightP (FC fn (sl, sc-1) kwEnd) AnnKeyword
624 return (PUnifyLog tm)
625 <?> "unification log expression"
627{- | Parses a new-style tactics expression
629 '%' 'runElab' SimpleExpr
632runElab :: SyntaxInfo -> IdrisParser PTerm
633runElab syn = do (FC fn (sl, sc) kwEnd) <- try (lchar '%' *> reservedFC "runElab")
636 highlightP (FC fn (sl, sc-1) kwEnd) AnnKeyword
637 return $ PRunElab fc tm (syn_namespace syn)
638 <?> "new-style tactics expression"
640{- | Parses a disambiguation expression
645disamb :: SyntaxInfo -> IdrisParser PTerm
646disamb syn = do kw <- reservedFC "with"
647 ns <- sepBy1 (fst <$> name) (lchar ',')
649 highlightP kw AnnKeyword
650 return (PDisamb (map tons ns) tm)
651 <?> "namespace disambiguation expression"
652 where tons (NS n s) = txt (show n) : s
653 tons n = [txt (show n)]
654{- | Parses a no implicits expression
657 '%' 'noImplicits' SimpleExpr
661noImplicits :: SyntaxInfo -> IdrisParser PTerm
662noImplicits syn = do try (lchar '%' *> reserved "noImplicits")
664 return (PNoImplicits tm)
665 <?> "no implicits expression"
667{- | Parses a function application expression
675 SimpleExpr '<==' FnName
679app :: SyntaxInfo -> IdrisParser PTerm
680app syn = do f <- simpleExpr syn
681 (do try $ reservedOp "<=="
684 return (PLet fc (sMN 0 "match") NoFC
687 (PRef fc [] (sMN 0 "match")))
688 <?> "matching application expression") <|>
691 args <- many (do notEndApp; arg syn)
692 wargs <- if withAppAllowed syn && not (inPattern syn)
693 then many (do notEndApp; reservedOp "|"; expr' syn)
697 _ -> return (withApp fc (flattenFromInt fc f args) wargs))
698 <?> "function application"
700 -- bit of a hack to deal with the situation where we're applying a
701 -- literal to an argument, which we may want for obscure applications
702 -- of fromInteger, and this will help disambiguate better.
703 -- We know, at least, it won't be one of the constants!
704 flattenFromInt fc (PAlternative _ x alts) args
705 | Just i <- getFromInt alts
706 = PApp fc (PRef fc [] (sUN "fromInteger")) (i : args)
707 flattenFromInt fc f args = PApp fc f args
709 withApp fc tm [] = tm
710 withApp fc tm (a : as) = withApp fc (PWithApp fc tm a) as
712 getFromInt ((PApp _ (PRef _ _ n) [a]) : _) | n == sUN "fromInteger" = Just a
713 getFromInt (_ : xs) = getFromInt xs
714 getFromInt _ = Nothing
716{-| Parses a function argument
725arg :: SyntaxInfo -> IdrisParser PArg
726arg syn = implicitArg syn
727 <|> constraintArg syn
728 <|> do e <- simpleExpr syn
730 <?> "function argument"
732{-| Parses an implicit function argument
735 '{' Name ('=' Expr)? '}'
739implicitArg :: SyntaxInfo -> IdrisParser PArg
740implicitArg syn = do lchar '{'
743 v <- option (PRef nfc [nfc] n) (do lchar '='
746 return (pimp n v True)
747 <?> "implicit function argument"
749{-| Parses a constraint argument (for selecting a named interface implementation)
756constraintArg :: SyntaxInfo -> IdrisParser PArg
757constraintArg syn = do symbol "@{"
761 <?> "constraint argument"
763{-| Parses a quasiquote expression (for building reflected terms using the elaborator)
765> Quasiquote ::= '`(' Expr ')'
768quasiquote :: SyntaxInfo -> IdrisParser PTerm
769quasiquote syn = do startFC <- symbolFC "`("
770 e <- expr syn { syn_in_quasiquote = (syn_in_quasiquote syn) + 1 ,
773 do fc <- symbolFC ":"
774 ty <- expr syn { inPattern = False } -- don't allow antiquotes
776 endFC <- symbolFC ")"
777 mapM_ (uncurry highlightP) [(startFC, AnnKeyword), (endFC, AnnKeyword), (spanFC startFC endFC, AnnQuasiquote)]
779 Just (_, fc) -> highlightP fc AnnKeyword
781 return $ PQuasiquote e (fst <$> g)
784{-| Parses an unquoting inside a quasiquotation (for building reflected terms using the elaborator)
786> Unquote ::= ',' Expr
789unquote :: SyntaxInfo -> IdrisParser PTerm
790unquote syn = do guard (syn_in_quasiquote syn > 0)
791 startFC <- symbolFC "~"
792 e <- simpleExpr syn { syn_in_quasiquote = syn_in_quasiquote syn - 1 }
794 highlightP startFC AnnKeyword
795 highlightP (spanFC startFC endFC) AnnAntiquote
799{-| Parses a quotation of a name (for using the elaborator to resolve boring details)
801> NameQuote ::= '`{' Name '}'
804namequote :: SyntaxInfo -> IdrisParser PTerm
805namequote syn = do (startFC, res) <-
806 try (do fc <- symbolFC "`{{"
807 return (fc, False)) <|>
808 (do fc <- symbolFC "`{"
811 endFC <- if res then symbolFC "}" else symbolFC "}}"
812 mapM_ (uncurry highlightP)
813 [ (startFC, AnnKeyword)
814 , (endFC, AnnKeyword)
815 , (spanFC startFC endFC, AnnQuasiquote)
817 return $ PQuoteName n res nfc
821{-| Parses a record field setter expression
824 'record' '{' FieldTypeList '}';
829 | FieldType ',' FieldTypeList
839data SetOrUpdate = FieldSet PTerm | FieldUpdate PTerm
841recordType :: SyntaxInfo -> IdrisParser PTerm
843 do kw <- reservedFC "record"
848 rec <- optional (do notEndApp; simpleExpr syn)
849 highlightP kw AnnKeyword
854 return (PLam fc (sMN 0 "fldx") NoFC Placeholder
855 (applyAll fc fields (PRef fc [] (sMN 0 "fldx"))))
856 Just v -> return (applyAll fc fields v)
860 return (PLam fc (sMN 0 "fldx") NoFC Placeholder
861 (getAll fc (reverse fields)
862 (PRef fc [] (sMN 0 "fldx"))))
863 Just v -> return (getAll fc (reverse fields) v)
865 <?> "record setting expression"
866 where fieldSet :: IdrisParser ([Name], SetOrUpdate)
867 fieldSet = do ns <- fieldGet
870 return (ns, FieldSet e))
873 return (ns, FieldUpdate e)
876 fieldGet :: IdrisParser [Name]
877 fieldGet = sepBy1 (fst <$> fnName) (symbol "->")
879 fieldGetOrSet :: IdrisParser (Either [([Name], SetOrUpdate)] [Name])
880 fieldGetOrSet = try (do fs <- sepBy1 fieldSet (lchar ',')
885 applyAll :: FC -> [([Name], SetOrUpdate)] -> PTerm -> PTerm
887 applyAll fc ((ns, e) : es) x
888 = applyAll fc es (doUpdate fc ns e x)
890 doUpdate fc ns (FieldUpdate e) get
891 = let get' = getAll fc (reverse ns) get in
892 doUpdate fc ns (FieldSet (PApp fc e [pexp get'])) get
893 doUpdate fc [n] (FieldSet e) get
894 = PApp fc (PRef fc [] (mkType n)) [pexp e, pexp get]
895 doUpdate fc (n : ns) e get
896 = PApp fc (PRef fc [] (mkType n))
897 [pexp (doUpdate fc ns e (PApp fc (PRef fc [] n) [pexp get])),
900 getAll :: FC -> [Name] -> PTerm -> PTerm
901 getAll fc [n] e = PApp fc (PRef fc [] n) [pexp e]
902 getAll fc (n:ns) e = PApp fc (PRef fc [] n) [pexp (getAll fc ns e)]
905-- | Creates setters for record types on necessary functions
906mkType :: Name -> Name
907mkType (UN n) = sUN ("set_" ++ str n)
908mkType (MN 0 n) = sMN 0 ("set_" ++ str n)
909mkType (NS n s) = NS (mkType n) s
911{- | Parses a type signature
918TypeExpr ::= ConstraintList? Expr;
921typeExpr :: SyntaxInfo -> IdrisParser PTerm
922typeExpr syn = do cs <- if implicitAllowed syn then constraintList syn else return []
923 sc <- expr (allowConstr syn)
924 return (bindList (\r -> PPi (constraint { pcount = r })) cs sc)
927{- | Parses a lambda expression
930 '\\' TypeOptDeclList LambdaTail
931 | '\\' SimpleExprList LambdaTail
937 | SimpleExpr ',' SimpleExprList
946lambda :: SyntaxInfo -> IdrisParser PTerm
947lambda syn = do lchar '\\' <?> "lambda expression"
948 ((do xt <- try $ tyOptDeclList (disallowImp syn)
951 return (bindList (\r -> PLam fc) xt sc))
953 (do ps <- sepBy (do fc <- getFC
954 e <- simpleExpr (disallowImp (syn { inPattern = True }))
958 return (pmList (zip [0..] ps) sc)))
959 <?> "lambda expression"
960 where pmList :: [(Int, (FC, PTerm))] -> PTerm -> PTerm
962 pmList ((i, (fc, x)) : xs) sc
963 = PLam fc (sMN i "lamp") NoFC Placeholder
964 (PCase fc (PRef fc [] (sMN i "lamp"))
966 lambdaTail :: IdrisParser PTerm
967 lambdaTail = impossible <|> symbol "=>" *> expr syn
969{- | Parses a term rewrite expression
972 'rewrite' Expr ('==>' Expr)? 'in' Expr
976rewriteTerm :: SyntaxInfo -> IdrisParser PTerm
977rewriteTerm syn = do kw <- reservedFC "rewrite"
980 giving <- optional (do symbol "==>"; expr' syn)
981 using <- optional (do reserved "using"
984 kw' <- reservedFC "in"; sc <- expr syn
985 highlightP kw AnnKeyword
986 highlightP kw' AnnKeyword
987 return (PRewrite fc using prf sc giving)
988 <?> "term rewrite expression"
990{- |Parses a let binding
993 'let' Name TypeSig'? '=' Expr 'in' Expr
994| 'let' Expr' '=' Expr' 'in' Expr
1001let_ :: SyntaxInfo -> IdrisParser PTerm
1002let_ syn = try (do kw <- reservedFC "let"
1003 ls <- indentedBlock (let_binding syn)
1004 kw' <- reservedFC "in"; sc <- expr syn
1005 highlightP kw AnnKeyword; highlightP kw' AnnKeyword
1006 return (buildLets ls sc))
1008 where buildLets [] sc = sc
1009 buildLets ((fc, PRef nfc _ n, ty, v, []) : ls) sc
1010 = PLet fc n nfc ty v (buildLets ls sc)
1011 buildLets ((fc, pat, ty, v, alts) : ls) sc
1012 = PCase fc v ((pat, buildLets ls sc) : alts)
1014let_binding syn = do fc <- getFC;
1015 pat <- expr' (syn { inPattern = True })
1016 ty <- option Placeholder (do lchar ':'; expr' syn)
1018 v <- expr (syn { withAppAllowed = isVar pat })
1019 ts <- option [] (do lchar '|'
1020 sepBy1 (do_alt syn) (lchar '|'))
1021 return (fc,pat,ty,v,ts)
1022 where isVar (PRef _ _ _) = True
1025{- | Parses a conditional expression
1027If ::= 'if' Expr 'then' Expr 'else' Expr
1031if_ :: SyntaxInfo -> IdrisParser PTerm
1032if_ syn = (do ifFC <- reservedFC "if"
1035 thenFC <- reservedFC "then"
1037 elseFC <- reservedFC "else"
1039 mapM_ (flip highlightP AnnKeyword) [ifFC, thenFC, elseFC]
1040 return (PIfThenElse fc c t f))
1041 <?> "conditional expression"
1044{- | Parses a quote goal
1048 'quoteGoal' Name 'by' Expr 'in' Expr
1052quoteGoal :: SyntaxInfo -> IdrisParser PTerm
1053quoteGoal syn = do kw1 <- reservedFC "quoteGoal"; n <- fst <$> name;
1054 kw2 <- reservedFC "by"
1056 kw3 <- reservedFC "in"
1059 mapM_ (flip highlightP AnnKeyword) [kw1, kw2, kw3]
1060 return (PGoal fc r n sc)
1061 <?> "quote goal expression"
1063{- | Parses a dependent type signature
1066Pi ::= PiOpts Static? Pi'
1072 | '(' TypeDeclList ')' '->' Pi
1073 | '{' TypeDeclList '}' '->' Pi
1074 | '{' 'auto' TypeDeclList '}' '->' Pi
1075 | '{' 'default' SimpleExpr TypeDeclList '}' '->' Pi
1080bindsymbol opts st syn
1082 return (Exp opts st False RigW)
1084explicitPi opts st syn
1085 = do xt <- try (lchar '(' *> typeDeclList syn <* lchar ')')
1086 binder <- bindsymbol opts st syn
1087 sc <- expr (allowConstr syn)
1088 return (bindList (\r -> PPi (binder { pcount = r })) xt sc)
1090autoImplicit opts st syn
1091 = do kw <- reservedFC "auto"
1092 when (st == Static) $ fail "auto implicits can not be static"
1093 xt <- typeDeclList syn
1096 sc <- expr (allowConstr syn)
1097 highlightP kw AnnKeyword
1098 return (bindList (\r -> PPi
1099 (TacImp [] Dynamic (PTactics [ProofSearch True True 100 Nothing [] []]) r)) xt sc)
1101defaultImplicit opts st syn = do
1102 kw <- reservedFC "default"
1103 when (st == Static) $ fail "default implicits can not be static"
1105 script' <- simpleExpr syn
1106 let script = debindApp syn . desugar syn ist $ script'
1107 xt <- typeDeclList syn
1110 sc <- expr (allowConstr syn)
1111 highlightP kw AnnKeyword
1112 return (bindList (\r -> PPi (TacImp [] Dynamic script r)) xt sc)
1114normalImplicit opts st syn = do
1115 xt <- typeDeclList syn <* lchar '}'
1117 cs <- constraintList syn
1120 = if implicitAllowed syn
1121 then (Imp opts st False (Just (Impl False True False)) True RigW,
1123 else (Imp opts st False (Just (Impl False False False)) True RigW,
1124 Imp opts st False (Just (Impl True False False)) True RigW)
1125 return (bindList (\r -> PPi (im { pcount = r })) xt
1126 (bindList (\r -> PPi (cl { pcount = r })) cs sc))
1128constraintPi opts st syn =
1129 do cs <- constraintList1 syn
1131 if implicitAllowed syn
1132 then return (bindList (\r -> PPi constraint { pcount = r }) cs sc)
1133 else return (bindList (\r -> PPi (Imp opts st False (Just (Impl True False False)) True r))
1136implicitPi opts st syn =
1137 autoImplicit opts st syn
1138 <|> defaultImplicit opts st syn
1139 <|> normalImplicit opts st syn
1141unboundPi opts st syn = do
1143 (do binder <- bindsymbol opts st syn
1145 return (PPi binder (sUN "__pi_arg") NoFC x sc))
1148-- This is used when we need to disambiguate from a constraint list
1149unboundPiNoConstraint opts st syn = do
1151 (do binder <- bindsymbol opts st syn
1153 notFollowedBy $ reservedOp "=>"
1154 return (PPi binder (sUN "__pi_arg") NoFC x sc))
1155 <|> do notFollowedBy $ reservedOp "=>"
1159pi :: SyntaxInfo -> IdrisParser PTerm
1161 do opts <- piOpts syn
1163 explicitPi opts st syn
1164 <|> try (do lchar '{'; implicitPi opts st syn)
1165 <|> if constraintAllowed syn
1166 then try (unboundPiNoConstraint opts st syn)
1167 <|> constraintPi opts st syn
1168 else unboundPi opts st syn
1169 <?> "dependent type signature"
1171{- | Parses Possible Options for Pi Expressions
1176piOpts :: SyntaxInfo -> IdrisParser [ArgOpt]
1177piOpts syn | implicitAllowed syn =
1178 lchar '.' *> return [InaccessibleArg]
1180piOpts syn = return []
1182{- | Parses a type constraint list
1186 '(' Expr_List ')' '=>'
1191constraintList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1192constraintList syn = try (constraintList1 syn)
1195constraintList1 :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1196constraintList1 syn = try (do lchar '('
1197 tys <- sepBy1 nexpr (lchar ',')
1201 <|> try (do t <- opExpr (disallowImp syn)
1203 return [(RigW, defname, NoFC, t)])
1204 <?> "type constraint list"
1205 where nexpr = try (do (n, fc) <- name; lchar ':'
1206 e <- expr (disallowImp syn)
1207 return (RigW, n, fc, e))
1208 <|> do e <- expr (disallowImp syn)
1209 return (RigW, defname, NoFC, e)
1210 defname = sMN 0 "constraint"
1212{- | Parses a type declaration list
1215 FunctionSignatureList
1221FunctionSignatureList ::=
1223 | Name TypeSig ',' FunctionSignatureList
1227typeDeclList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1228typeDeclList syn = try (sepBy1 (do rig <- option RigW rigCount
1231 t <- typeExpr (disallowImp syn)
1232 return (rig, x, xfc, t))
1234 <|> do ns <- sepBy1 name (lchar ',')
1236 t <- typeExpr (disallowImp syn)
1237 return (map (\(x, xfc) -> (RigW, x, xfc, t)) ns)
1238 <?> "type declaration list"
1240 rigCount = do lchar '1'; return Rig1
1241 <|> do lchar '0'; return Rig0
1243{- | Parses a type declaration list with optional parameters
1246 NameOrPlaceholder TypeSig?
1247 | NameOrPlaceholder TypeSig? ',' TypeOptDeclList
1252NameOrPlaceHolder ::= Name | '_';
1255tyOptDeclList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1256tyOptDeclList syn = sepBy1 (do (x, fc) <- nameOrPlaceholder
1257 t <- option Placeholder (do lchar ':'
1259 return (RigW, x, fc, t))
1261 <?> "type declaration list"
1262 where nameOrPlaceholder :: IdrisParser (Name, FC)
1263 nameOrPlaceholder = fnName
1265 return (sMN 0 "underscore", NoFC)
1266 <?> "name or placeholder"
1268{- | Parses a list literal expression e.g. [1,2,3] or a comprehension [ (x, y) | x <- xs , y <- ys ]
1272 | '[' Expr '|' DoList ']'
1289listExpr :: SyntaxInfo -> IdrisParser PTerm
1290listExpr syn = do (FC f (l, c) _) <- getFC
1291 lchar '['; fc <- getFC;
1292 (try . token $ do (char ']' <?> "end of list expression")
1293 (FC _ _ (l', c')) <- getFC
1294 return (mkNil (FC f (l, c) (l', c'))))
1295 <|> (do x <- expr (syn { withAppAllowed = False }) <?> "expression"
1296 (do try (lchar '|') <?> "list comprehension"
1297 qs <- sepBy1 (do_ syn) (lchar ',')
1299 return (PDoBlock (map addGuard qs ++
1300 [DoExp fc (PApp fc (PRef fc [] (sUN "pure"))
1302 (do xs <- many (do (FC fn (sl, sc) _) <- getFC
1303 lchar ',' <?> "list element"
1304 let commaFC = FC fn (sl, sc) (sl, sc + 1)
1306 return (elt, commaFC))
1307 (FC fn (sl, sc) _) <- getFC
1308 lchar ']' <?> "end of list expression"
1309 let rbrackFC = FC fn (sl, sc) (sl, sc+1)
1310 return (mkList fc rbrackFC ((x, (FC f (l, c) (l, c+1))) : xs))))
1311 <?> "list expression"
1313 mkNil :: FC -> PTerm
1314 mkNil fc = PRef fc [fc] (sUN "Nil")
1315 mkList :: FC -> FC -> [(PTerm, FC)] -> PTerm
1316 mkList errFC nilFC [] = PRef nilFC [nilFC] (sUN "Nil")
1317 mkList errFC nilFC ((x, fc) : xs) = PApp errFC (PRef fc [fc] (sUN "::")) [pexp x, pexp (mkList errFC nilFC xs)]
1318 addGuard :: PDo -> PDo
1319 addGuard (DoExp fc e) = DoExp fc (PApp fc (PRef fc [] (sUN "guard"))
1323{- | Parses a do-block
1325Do' ::= Do KeepTerminator;
1330 'do' OpenBlock Do'+ CloseBlock
1334doBlock :: SyntaxInfo -> IdrisParser PTerm
1336 = do kw <- reservedFC "do"
1337 ds <- indentedBlock1 (do_ syn)
1338 highlightP kw AnnKeyword
1339 return (PDoBlock ds)
1342{- | Parses an expression inside a do block
1345 'let' Name TypeSig'? '=' Expr
1346 | 'let' Expr' '=' Expr
1354do_ :: SyntaxInfo -> IdrisParser PDo
1356 = try (do kw <- reservedFC "let"
1358 ty <- option Placeholder (do lchar ':'
1363 highlightP kw AnnKeyword
1364 return (DoLet fc i ifc ty e))
1365 <|> try (do kw <- reservedFC "let"
1370 highlightP kw AnnKeyword
1371 return (DoLetP fc i sc))
1372 <|> try (do kw <- reservedFC "rewrite"
1375 highlightP kw AnnKeyword
1376 return (DoRewrite fc sc))
1377 <|> try (do (i, ifc) <- name
1380 e <- expr (syn { withAppAllowed = False });
1381 option (DoBind fc i ifc e)
1383 ts <- sepBy1 (do_alt (syn { withAppAllowed = False })) (lchar '|')
1384 return (DoBindP fc (PRef ifc [ifc] i) e ts)))
1385 <|> try (do i <- expr' syn
1388 e <- expr (syn { withAppAllowed = False });
1389 option (DoBindP fc i e [])
1391 ts <- sepBy1 (do_alt (syn { withAppAllowed = False })) (lchar '|')
1392 return (DoBindP fc i e ts)))
1393 <|> do e <- expr syn
1396 <?> "do block expression"
1398do_alt syn = do l <- expr' syn
1399 option (Placeholder, l)
1404{- | Parses an expression in idiom brackets
1406Idiom ::= '[|' Expr '|]';
1409idiom :: SyntaxInfo -> IdrisParser PTerm
1413 e <- expr (syn { withAppAllowed = False })
1415 return (PIdiom fc e)
1416 <?> "expression in idiom brackets"
1418{- |Parses a constant or literal expression
1440constants :: [(String, Idris.Core.TT.Const)]
1442 [ ("Integer", AType (ATInt ITBig))
1443 , ("Int", AType (ATInt ITNative))
1444 , ("Char", AType (ATInt ITChar))
1445 , ("Double", AType ATFloat)
1446 , ("String", StrType)
1447 , ("prim__WorldType", WorldType)
1448 , ("prim__TheWorld", TheWorld)
1449 , ("Bits8", AType (ATInt (ITFixed IT8)))
1450 , ("Bits16", AType (ATInt (ITFixed IT16)))
1451 , ("Bits32", AType (ATInt (ITFixed IT32)))
1452 , ("Bits64", AType (ATInt (ITFixed IT64)))
1455-- | Parse a constant and its source span
1456constant :: IdrisParser (Idris.Core.TT.Const, FC)
1457constant = choice [ do fc <- reservedFC name; return (ty, fc)
1458 | (name, ty) <- constants
1460 <|> do (f, fc) <- try float; return (Fl f, fc)
1461 <|> do (i, fc) <- natural; return (BI i, fc)
1462 <|> do (s, fc) <- verbatimStringLiteral; return (Str s, fc)
1463 <|> do (s, fc) <- stringLiteral; return (Str s, fc)
1464 <|> do (c, fc) <- try charLiteral; return (Ch c, fc) --Currently ambigous with symbols
1465 <?> "constant or literal"
1467{- | Parses a verbatim multi-line string literal (triple-quoted)
1471 '\"\"\"' ~'\"\"\"' '\"\"\"'
1475verbatimStringLiteral :: MonadicParsing m => m (String, FC)
1476verbatimStringLiteral = token $ do (FC f start _) <- getFC
1477 try $ string "\"\"\""
1478 str <- manyTill anyChar $ try (string "\"\"\"")
1479 (FC _ _ end) <- getFC
1480 return (str, FC f start end)
1482{- | Parses a static modifier
1490static :: IdrisParser Static
1491static = do reserved "%static"; return Static
1492 <|> do reserved "[static]"
1494 parserWarning fc Nothing (Msg "The use of [static] is deprecated, use %static instead.")
1497 <?> "static modifier"
1499{- | Parses a tactic script
1502Tactic ::= 'intro' NameList?
1504 | 'refine' Name Imp+
1509 | 'let' Name ':' Expr' '=' Expr
1510 | 'let' Name '=' Expr
1513 | 'applyTactic' Expr
1516 | 'try' Tactic '|' Tactic
1534 | Tactic ';' TacticSeq
1539-- | A specification of the arguments that tactics can take
1540data TacticArg = NameTArg -- ^ Names: n1, n2, n3, ... n
1545-- The FIXMEs are Issue #1766 in the issue tracker.
1546-- https://github.com/idris-lang/Idris-dev/issues/1766
1547-- | A list of available tactics and their argument requirements
1548tactics :: [([String], Maybe TacticArg, SyntaxInfo -> IdrisParser PTactic)]
1550 [ (["intro"], Nothing, const $ -- FIXME syntax for intro (fresh name)
1551 do ns <- sepBy (spaced (fst <$> name)) (lchar ','); return $ Intro ns)
1552 , noArgs ["intros"] Intros
1553 , noArgs ["unfocus"] Unfocus
1554 , (["refine"], Just ExprTArg, const $
1555 do n <- spaced (fst <$> fnName)
1557 return $ Refine n imps)
1558 , (["claim"], Nothing, \syn ->
1559 do n <- indentPropHolds gtProp *> (fst <$> name)
1560 goal <- indentPropHolds gtProp *> expr syn
1561 return $ Claim n goal)
1562 , (["mrefine"], Just ExprTArg, const $
1563 do n <- spaced (fst <$> fnName)
1564 return $ MatchRefine n)
1565 , expressionTactic ["rewrite"] Rewrite
1566 , expressionTactic ["case"] CaseTac
1567 , expressionTactic ["induction"] Induction
1568 , expressionTactic ["equiv"] Equiv
1569 , (["let"], Nothing, \syn -> -- FIXME syntax for let
1570 do n <- (indentPropHolds gtProp *> (fst <$> name))
1571 (do indentPropHolds gtProp *> lchar ':'
1572 ty <- indentPropHolds gtProp *> expr' syn
1573 indentPropHolds gtProp *> lchar '='
1574 t <- indentPropHolds gtProp *> expr syn
1576 return $ LetTacTy n (desugar syn i ty) (desugar syn i t))
1577 <|> (do indentPropHolds gtProp *> lchar '='
1578 t <- indentPropHolds gtProp *> expr syn
1580 return $ LetTac n (desugar syn i t)))
1582 , (["focus"], Just ExprTArg, const $
1583 do n <- spaced (fst <$> name)
1585 , expressionTactic ["exact"] Exact
1586 , expressionTactic ["applyTactic"] ApplyTactic
1587 , expressionTactic ["byReflection"] ByReflection
1588 , expressionTactic ["reflect"] Reflect
1589 , expressionTactic ["fill"] Fill
1590 , (["try"], Just AltsTArg, \syn ->
1591 do t <- spaced (tactic syn)
1593 t1 <- spaced (tactic syn)
1595 , noArgs ["compute"] Compute
1596 , noArgs ["trivial"] Trivial
1597 , noArgs ["unify"] DoUnify
1598 , (["search"], Nothing, const $
1599 do depth <- option 10 $ fst <$> natural
1600 return (ProofSearch True True (fromInteger depth) Nothing [] []))
1601 , noArgs ["implementation"] TCImplementation
1602 , noArgs ["solve"] Solve
1603 , noArgs ["attack"] Attack
1604 , noArgs ["state", ":state"] ProofState
1605 , noArgs ["term", ":term"] ProofTerm
1606 , noArgs ["undo", ":undo"] Undo
1607 , noArgs ["qed", ":qed"] Qed
1608 , noArgs ["abandon", ":q"] Abandon
1609 , noArgs ["skip"] Skip
1610 , noArgs ["sourceLocation"] SourceFC
1611 , expressionTactic [":e", ":eval"] TEval
1612 , expressionTactic [":t", ":type"] TCheck
1613 , expressionTactic [":search"] TSearch
1614 , (["fail"], Just StringLitTArg, const $
1615 do msg <- fst <$> stringLiteral
1616 return $ TFail [Idris.Core.TT.TextPart msg])
1617 , ([":doc"], Just ExprTArg, const $
1619 doc <- (Right . fst <$> constant) <|> (Left . fst <$> fnName)
1621 return (TDocStr doc))
1624 expressionTactic names tactic = (names, Just ExprTArg, \syn ->
1625 do t <- spaced (expr syn)
1627 return $ tactic (desugar syn i t))
1628 noArgs names tactic = (names, Nothing, const (return tactic))
1629 spaced parser = indentPropHolds gtProp *> parser
1630 imp :: IdrisParser Bool
1631 imp = do lchar '?'; return False
1632 <|> do lchar '_'; return True
1635tactic :: SyntaxInfo -> IdrisParser PTactic
1636tactic syn = choice [ do choice (map reserved names); parser syn
1637 | (names, _, parser) <- tactics ]
1641 ts <- sepBy1 (tactic syn) (lchar ';')
1643 return $ TSeq t (mergeSeq ts)
1644 <|> ((lchar ':' >> empty) <?> "prover command")
1647 mergeSeq :: [PTactic] -> PTactic
1649 mergeSeq (t:ts) = TSeq t (mergeSeq ts)
1651-- | Parses a tactic as a whole
1652fullTactic :: SyntaxInfo -> IdrisParser PTactic
1653fullTactic 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