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.Arrow (left)
22import Control.Applicative
24import Control.Monad.State.Strict
25import Data.Function (on)
28import Text.Parser.Expression
29import Text.Trifecta ((<?>))
30import qualified Text.Trifecta 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 buildExpressionParser (table (idris_infixes i))
82{- | Parses either an internally defined expression or
85Expr' ::= "External (User-defined) Syntax"
89expr' :: SyntaxInfo -> IdrisParser PTerm
90expr' syn = P.try (externalExpr syn)
94{- | Parses a user-defined expression -}
95externalExpr :: SyntaxInfo -> IdrisParser PTerm
96externalExpr syn = do i <- get
97 (FC fn start _) <- getFC
98 expr <- extensions syn (syntaxRulesList $ syntax_rules i)
100 let outerFC = FC fn start end
101 return (mapPTermFC (fixFC outerFC) (fixFCH fn outerFC) expr)
102 <?> "user-defined expression"
103 where -- Fix non-highlighting FCs by approximating with the span of the syntax application
104 fixFC outer inner | inner `fcIn` outer = inner
106 -- Fix highlighting FCs by making them useless, to avoid spurious highlights
107 fixFCH fn outer inner | inner `fcIn` outer = inner
108 | otherwise = FileFC fn
110{- | Parses a simple user-defined expression -}
111simpleExternalExpr :: SyntaxInfo -> IdrisParser PTerm
112simpleExternalExpr syn = do i <- get
113 extensions syn (filter isSimple (syntaxRulesList $ syntax_rules i))
115 isSimple (Rule (Expr x:xs) _ _) = False
116 isSimple (Rule (SimpleExpr x:xs) _ _) = False
117 isSimple (Rule [Keyword _] _ _) = True
118 isSimple (Rule [Symbol _] _ _) = True
119 isSimple (Rule (_:xs) _ _) = case last xs of
125{- | Tries to parse a user-defined expression given a list of syntactic extensions -}
126extensions :: SyntaxInfo -> [Syntax] -> IdrisParser PTerm
127extensions syn rules = extension syn [] (filter isValid rules)
128 <?> "user-defined expression"
130 isValid :: Syntax -> Bool
131 isValid (Rule _ _ AnySyntax) = True
132 isValid (Rule _ _ PatternSyntax) = inPattern syn
133 isValid (Rule _ _ TermSyntax) = not (inPattern syn)
134 isValid (DeclRule _ _) = False
136data SynMatch = SynTm PTerm | SynBind FC Name -- ^ the FC is for highlighting information
139extension :: SyntaxInfo -> [Maybe (Name, SynMatch)] -> [Syntax] -> IdrisParser PTerm
140extension syn ns rules =
141 P.choice $ flip map (groupBy (ruleGroup `on` syntaxSymbols) rules) $ \rs ->
142 case head rs of -- can never be []
143 Rule (symb:_) _ _ -> P.try $ do
144 n <- extensionSymbol symb
145 extension syn (n : ns) [Rule ss t ctx | (Rule (_:ss) t ctx) <- rs]
146 -- If we have more than one Rule in this bucket, our grammar is
148 Rule [] ptm _ -> return (flatten (updateSynMatch (mapMaybe id ns) ptm))
150 ruleGroup [] [] = True
151 ruleGroup (s1:_) (s2:_) = s1 == s2
152 ruleGroup _ _ = False
154 extensionSymbol :: SSymbol -> IdrisParser (Maybe (Name, SynMatch))
155 extensionSymbol (Keyword n) = do fc <- reservedFC (show n)
156 highlightP fc AnnKeyword
158 extensionSymbol (Expr n) = do tm <- expr syn
159 return $ Just (n, SynTm tm)
160 extensionSymbol (SimpleExpr n) = do tm <- simpleExpr syn
161 return $ Just (n, SynTm tm)
162 extensionSymbol (Binding n) = do (b, fc) <- name
163 return $ Just (n, SynBind fc b)
164 extensionSymbol (Symbol s) = do fc <- symbolFC s
165 highlightP fc AnnKeyword
168 flatten :: PTerm -> PTerm -- flatten application
169 flatten (PApp fc (PApp _ f as) bs) = flatten (PApp fc f (as ++ bs))
172updateSynMatch = update
174 updateB :: [(Name, SynMatch)] -> (Name, FC) -> (Name, FC)
175 updateB ns (n, fc) = case lookup n ns of
176 Just (SynBind tfc t) -> (t, tfc)
179 update :: [(Name, SynMatch)] -> PTerm -> PTerm
180 update ns (PRef fc hls n) = case lookup n ns of
183 update ns (PPatvar fc n) = uncurry (flip PPatvar) $ updateB ns (n, fc)
184 update ns (PLam fc n nfc ty sc)
185 = let (n', nfc') = updateB ns (n, nfc)
186 in PLam fc n' nfc' (update ns ty) (update (dropn n ns) sc)
187 update ns (PPi p n fc ty sc)
188 = let (n', nfc') = updateB ns (n, fc)
189 in PPi (updTacImp ns p) n' nfc'
190 (update ns ty) (update (dropn n ns) sc)
191 update ns (PLet fc rc n nfc ty val sc)
192 = let (n', nfc') = updateB ns (n, nfc)
193 in PLet fc rc n' nfc' (update ns ty)
194 (update ns val) (update (dropn n ns) sc)
195 update ns (PApp fc t args)
196 = PApp fc (update ns t) (map (fmap (update ns)) args)
197 update ns (PAppBind fc t args)
198 = PAppBind fc (update ns t) (map (fmap (update ns)) args)
199 update ns (PMatchApp fc n) = let (n', nfc') = updateB ns (n, fc)
201 update ns (PIfThenElse fc c t f)
202 = PIfThenElse fc (update ns c) (update ns t) (update ns f)
203 update ns (PCase fc c opts)
204 = PCase fc (update ns c) (map (pmap (update ns)) opts)
205 update ns (PRewrite fc by eq tm mty)
206 = PRewrite fc by (update ns eq) (update ns tm) (fmap (update ns) mty)
207 update ns (PPair fc hls p l r) = PPair fc hls p (update ns l) (update ns r)
208 update ns (PDPair fc hls p l t r)
209 = PDPair fc hls p (update ns l) (update ns t) (update ns r)
210 update ns (PAs fc n t) = PAs fc (fst $ updateB ns (n, NoFC)) (update ns t)
211 update ns (PAlternative ms a as) = PAlternative ms a (map (update ns) as)
212 update ns (PHidden t) = PHidden (update ns t)
213 update ns (PGoal fc r n sc) = PGoal fc (update ns r) n (update ns sc)
214 update ns (PDoBlock ds) = PDoBlock $ map (upd ns) ds
215 where upd :: [(Name, SynMatch)] -> PDo -> PDo
216 upd ns (DoExp fc t) = DoExp fc (update ns t)
217 upd ns (DoBind fc n nfc t) = DoBind fc n nfc (update ns t)
218 upd ns (DoLet fc rc n nfc ty t) = DoLet fc rc n nfc (update ns ty) (update ns t)
219 upd ns (DoBindP fc i t ts)
220 = DoBindP fc (update ns i) (update ns t)
221 (map (\(l,r) -> (update ns l, update ns r)) ts)
222 upd ns (DoLetP fc i t) = DoLetP fc (update ns i) (update ns t)
223 upd ns (DoRewrite fc h) = DoRewrite fc (update ns h)
224 update ns (PIdiom fc t) = PIdiom fc $ update ns t
225 update ns (PMetavar fc n) = uncurry (flip PMetavar) $ updateB ns (n, fc)
226 update ns (PProof tacs) = PProof $ map (updTactic ns) tacs
227 update ns (PTactics tacs) = PTactics $ map (updTactic ns) tacs
228 update ns (PDisamb nsps t) = PDisamb nsps $ update ns t
229 update ns (PUnifyLog t) = PUnifyLog $ update ns t
230 update ns (PNoImplicits t) = PNoImplicits $ update ns t
231 update ns (PQuasiquote tm mty) = PQuasiquote (update ns tm) (fmap (update ns) mty)
232 update ns (PUnquote t) = PUnquote $ update ns t
233 update ns (PQuoteName n res fc) = let (n', fc') = (updateB ns (n, fc))
234 in PQuoteName n' res fc'
235 update ns (PRunElab fc t nsp) = PRunElab fc (update ns t) nsp
236 update ns (PConstSugar fc t) = PConstSugar fc $ update ns t
237 -- PConstSugar probably can't contain anything substitutable, but it's hard to track
240 updTactic :: [(Name, SynMatch)] -> PTactic -> PTactic
241 -- handle all the ones with Names explicitly, then use fmap for the rest with PTerms
242 updTactic ns (Intro ns') = Intro $ map (fst . updateB ns . (, NoFC)) ns'
243 updTactic ns (Focus n) = Focus . fst $ updateB ns (n, NoFC)
244 updTactic ns (Refine n bs) = Refine (fst $ updateB ns (n, NoFC)) bs
245 updTactic ns (Claim n t) = Claim (fst $ updateB ns (n, NoFC)) (update ns t)
246 updTactic ns (MatchRefine n) = MatchRefine (fst $ updateB ns (n, NoFC))
247 updTactic ns (LetTac n t) = LetTac (fst $ updateB ns (n, NoFC)) (update ns t)
248 updTactic ns (LetTacTy n ty tm) = LetTacTy (fst $ updateB ns (n, NoFC)) (update ns ty) (update ns tm)
249 updTactic ns (ProofSearch rec prover depth top psns hints) = ProofSearch rec prover depth
250 (fmap (fst . updateB ns . (, NoFC)) top) (map (fst . updateB ns . (, NoFC)) psns) (map (fst . updateB ns . (, NoFC)) hints)
251 updTactic ns (Try l r) = Try (updTactic ns l) (updTactic ns r)
252 updTactic ns (TSeq l r) = TSeq (updTactic ns l) (updTactic ns r)
253 updTactic ns (GoalType s tac) = GoalType s $ updTactic ns tac
254 updTactic ns (TDocStr (Left n)) = TDocStr . Left . fst $ updateB ns (n, NoFC)
255 updTactic ns t = fmap (update ns) t
257 updTacImp ns (TacImp o st scr r) = TacImp o st (update ns scr) r
260 dropn :: Name -> [(Name, a)] -> [(Name, a)]
262 dropn n ((x,t) : xs) | n == x = xs
263 | otherwise = (x,t):dropn n xs
266{- | Parses a (normal) built-in expression
283internalExpr :: SyntaxInfo -> IdrisParser PTerm
300{- | Parses the "impossible" keyword
302Impossible ::= 'impossible'
305impossible :: IdrisParser PTerm
306impossible = do fc <- reservedFC "impossible"
307 highlightP fc AnnKeyword
310{- | Parses a case expression
313 'case' Expr 'of' OpenBlock CaseOption+ CloseBlock;
316caseExpr :: SyntaxInfo -> IdrisParser PTerm
317caseExpr syn = do kw1 <- reservedFC "case"; fc <- getFC
318 scr <- expr syn; kw2 <- reservedFC "of";
319 opts <- indentedBlock1 (caseOption syn)
320 highlightP kw1 AnnKeyword
321 highlightP kw2 AnnKeyword
322 return (PCase fc scr opts)
323 <?> "case expression"
325{- | Parses a case in a case expression
328 Expr (Impossible | '=>' Expr) Terminator
332caseOption :: SyntaxInfo -> IdrisParser (PTerm, PTerm)
333caseOption syn = do lhs <- expr (disallowImp (syn { inPattern = True }))
334 r <- impossible <|> symbol "=>" *> expr syn
338warnTacticDeprecation :: FC -> IdrisParser ()
339warnTacticDeprecation fc =
340 parserWarning fc (Just NoOldTacticDeprecationWarnings) (Msg "This style of tactic proof is deprecated. See %runElab for the replacement.")
342{- | Parses a proof block
345 'proof' OpenBlock Tactic'* CloseBlock
349proofExpr :: SyntaxInfo -> IdrisParser PTerm
350proofExpr syn = do kw <- reservedFC "proof"
351 ts <- indentedBlock1 (tactic syn)
352 highlightP kw AnnKeyword
353 warnTacticDeprecation kw
357{- | Parses a tactics block
360 'tactics' OpenBlock Tactic'* CloseBlock
364tacticsExpr :: SyntaxInfo -> IdrisParser PTerm
365tacticsExpr syn = do kw <- reservedFC "tactics"
366 ts <- indentedBlock1 (tactic syn)
367 highlightP kw AnnKeyword
368 warnTacticDeprecation kw
372{- | Parses a simple expression
375 {- External (User-defined) Simple Expression -}
378 | 'Refl' ('{' Expr '}')?
396simpleExpr :: SyntaxInfo -> IdrisParser PTerm
398 P.try (simpleExternalExpr syn)
399 <|> do (x, FC f (l, c) end) <- P.try (lchar '?' *> name)
400 return (PMetavar (FC f (l, c-1) end) x)
401 <|> do lchar '%'; fc <- getFC; reserved "implementation"; return (PResolveTC fc)
402 <|> do lchar '%'; fc <- getFC; reserved "instance"
403 parserWarning fc Nothing $ Msg "The use of %instance is deprecated, use %implementation instead."
404 return (PResolveTC fc)
405 <|> do reserved "elim_for"; fc <- getFC; t <- fst <$> fnName; return (PRef fc [] (SN $ ElimN t))
408 <|> P.try (do fc <- reservedFC "Type*"; return $ PUniverse fc AllTypes)
409 <|> do fc <- reservedFC "AnyType"; return $ PUniverse fc AllTypes
410 <|> PType <$> reservedFC "Type"
411 <|> do fc <- reservedFC "UniqueType"; return $ PUniverse fc UniqueType
412 <|> do fc <- reservedFC "NullType"; return $ PUniverse fc NullType
413 <|> do (c, cfc) <- constant
415 return (modifyConst syn fc (PConstant cfc c))
416 <|> do symbol "'"; fc <- getFC; str <- fst <$> name
417 return (PApp fc (PRef fc [] (sUN "Symbol_"))
418 [pexp (PConstant NoFC (Str (show str)))])
419 <|> do (x, fc) <- fnName
421 then P.option (PRef fc [fc] x)
425 return (PAs fcIn x s))
426 else return (PRef fc [fc] x)
430 <|> do reservedOp "!"
433 return (PAppBind fc s [])
434 <|> bracketed (disallowImp syn)
438 <|> do lchar '_'; return Placeholder
441{- |Parses an expression in parentheses
443Bracketed ::= '(' Bracketed'
446bracketed :: SyntaxInfo -> IdrisParser PTerm
447bracketed syn = do (FC fn (sl, sc) _) <- getFC
448 lchar '(' <?> "parenthesized expression"
449 bracketed' (FC fn (sl, sc) (sl, sc+1)) (syn { withAppAllowed = True })
451{- |Parses the rest of an expression in braces
463bracketed' :: FC -> SyntaxInfo -> IdrisParser PTerm
465 do (FC f start (l, c)) <- getFC
467 return $ PTrue (spanFC open (FC f start (l, c+1))) TypeOrTerm
468 <|> P.try (dependentPair TypeOrTerm [] open syn)
469 <|> P.try (do (opName, fc) <- operatorName
470 guardNotPrefix opName
474 return $ PLam fc (sMN 1000 "ARG") NoFC Placeholder
475 (PApp fc (PRef fc [] opName) [pexp (PRef fc [] (sMN 1000 "ARG")),
477 <|> P.try (simpleExpr syn >>= \l ->
478 P.try (do (opName, _) <- operatorName
481 return $ PLam fc (sMN 1000 "ARG") NoFC Placeholder
482 (PApp fc (PRef fc [] opName) [pexp l,
483 pexp (PRef fc [] (sMN 1000 "ARG"))]))
484 <|> bracketedExpr syn open l)
485 <|> do l <- expr (allowConstr syn)
486 bracketedExpr (allowConstr syn) open l
488 justPrefix :: FixDecl -> Maybe Name
489 justPrefix (Fix (PrefixN _) opName) = Just (sUN opName)
490 justPrefix _ = Nothing
492 guardNotPrefix :: Name -> IdrisParser ()
493 guardNotPrefix opName = do
494 guard $ opName /= sUN "-"
495 guard $ opName /= sUN "!"
497 ops <- idris_infixes <$> get
498 guard . not . (opName `elem`) . mapMaybe justPrefix $ ops
500{-| Parses the rest of a dependent pair after '(' or '(Expr **' -}
501dependentPair :: PunInfo -> [(PTerm, Maybe (FC, PTerm), FC)] -> FC -> SyntaxInfo -> IdrisParser PTerm
502dependentPair pun prev openFC syn =
504 nametypePart <|> namePart
507 IsType -> nametypePart <|> namePart <|> exprPart True
508 IsTerm -> exprPart False
509 TypeOrTerm -> nametypePart <|> namePart <|> exprPart False
510 where nametypePart = do
511 (ln, lnfc, colonFC) <- P.try $ do
513 colonFC <- lcharFC ':'
514 return (ln, lnfc, colonFC)
516 starsFC <- reservedOpFC "**"
517 dependentPair IsType ((PRef lnfc [] ln, Just (colonFC, lty), starsFC):prev) openFC syn
518 namePart = P.try $ do
520 starsFC <- reservedOpFC "**"
521 dependentPair pun ((PRef lnfc [] ln, Nothing, starsFC):prev) openFC syn
525 let stars = (Left <$> reservedOpFC "**")
526 ending = (Right <$> lcharFC ')')
527 in if isEnd then ending else stars <|> ending
529 Left starsFC -> dependentPair IsTerm ((e, Nothing, starsFC):prev) openFC syn
531 return (mkPDPairs pun openFC closeFC (reverse prev) e)
532 mkPDPairs pun openFC closeFC ((e, cfclty, starsFC):bnds) r =
533 (PDPair openFC ([openFC] ++ maybe [] ((: []) . fst) cfclty ++ [starsFC, closeFC] ++ (=<<) (\(_,cfclty,sfc) -> maybe [] ((: []) . fst) cfclty ++ [sfc]) bnds)
534 pun e (maybe Placeholder snd cfclty) (mergePDPairs pun starsFC bnds r))
535 mergePDPairs pun starsFC' [] r = r
536 mergePDPairs pun starsFC' ((e, cfclty, starsFC):bnds) r =
537 PDPair starsFC' [] pun e (maybe Placeholder snd cfclty) (mergePDPairs pun starsFC bnds r)
539-- | Parse the contents of parentheses, after an expression has been parsed.
540bracketedExpr :: SyntaxInfo -> FC -> PTerm -> IdrisParser PTerm
541bracketedExpr syn openParenFC e =
542 do lchar ')'; return e
543 <|> do exprs <- some (do comma <- lcharFC ','
546 closeParenFC <- lcharFC ')'
547 let hilite = [openParenFC, closeParenFC] ++ map snd exprs
548 return $ PPair openParenFC hilite TypeOrTerm e (mergePairs exprs)
549 <|> do starsFC <- reservedOpFC "**"
550 dependentPair IsTerm [(e, Nothing, starsFC)] openParenFC syn
551 <?> "end of bracketed expression"
552 where mergePairs :: [(PTerm, FC)] -> PTerm
553 mergePairs [(t, fc)] = t
554 mergePairs ((t, fc):rs) = PPair fc [] TypeOrTerm t (mergePairs rs)
556-- bit of a hack here. If the integer doesn't fit in an Int, treat it as a
557-- big integer, otherwise try fromInteger and the constants as alternatives.
558-- a better solution would be to fix fromInteger to work with Integer, as the
559-- name suggests, rather than Int
560{-| Finds optimal type for integer constant -}
561modifyConst :: SyntaxInfo -> FC -> PTerm -> PTerm
562modifyConst syn fc (PConstant inFC (BI x))
563 | not (inPattern syn)
564 = PConstSugar inFC $ -- wrap in original location for highlighting
565 PAlternative [] FirstSuccess
566 (PApp fc (PRef fc [] (sUN "fromInteger")) [pexp (PConstant NoFC (BI (fromInteger x)))]
568 | otherwise = PConstSugar inFC $
569 PAlternative [] FirstSuccess consts
571 consts = [ PConstant inFC (BI x)
572 , PConstant inFC (I (fromInteger x))
573 , PConstant inFC (B8 (fromInteger x))
574 , PConstant inFC (B16 (fromInteger x))
575 , PConstant inFC (B32 (fromInteger x))
576 , PConstant inFC (B64 (fromInteger x))
578modifyConst syn fc x = x
580{- | Parses an alternative expression
582 Alt ::= '(|' Expr_List '|)';
586 | Expr' ',' Expr_List
590alt :: SyntaxInfo -> IdrisParser PTerm
591alt syn = do symbol "(|"; alts <- P.sepBy1 (expr' (syn { withAppAllowed = False })) (lchar ','); symbol "|)"
592 return (PAlternative [] FirstSuccess alts)
594{- | Parses a possibly hidden simple expression
602hsimpleExpr :: SyntaxInfo -> IdrisParser PTerm
610{- | Parses a unification log expression
612 '%' 'unifyLog' SimpleExpr
615unifyLog :: SyntaxInfo -> IdrisParser PTerm
616unifyLog syn = do (FC fn (sl, sc) kwEnd) <- P.try (lchar '%' *> reservedFC "unifyLog")
618 highlightP (FC fn (sl, sc-1) kwEnd) AnnKeyword
619 return (PUnifyLog tm)
620 <?> "unification log expression"
622{- | Parses a new-style tactics expression
624 '%' 'runElab' SimpleExpr
627runElab :: SyntaxInfo -> IdrisParser PTerm
628runElab syn = do (FC fn (sl, sc) kwEnd) <- P.try (lchar '%' *> reservedFC "runElab")
631 highlightP (FC fn (sl, sc-1) kwEnd) AnnKeyword
632 return $ PRunElab fc tm (syn_namespace syn)
633 <?> "new-style tactics expression"
635{- | Parses a disambiguation expression
640disamb :: SyntaxInfo -> IdrisParser PTerm
641disamb syn = do kw <- reservedFC "with"
642 ns <- P.sepBy1 (fst <$> name) (lchar ',')
644 highlightP kw AnnKeyword
645 return (PDisamb (map tons ns) tm)
646 <?> "namespace disambiguation expression"
647 where tons (NS n s) = txt (show n) : s
648 tons n = [txt (show n)]
649{- | Parses a no implicits expression
652 '%' 'noImplicits' SimpleExpr
656noImplicits :: SyntaxInfo -> IdrisParser PTerm
657noImplicits syn = do P.try (lchar '%' *> reserved "noImplicits")
659 return (PNoImplicits tm)
660 <?> "no implicits expression"
662{- | Parses a function application expression
670 SimpleExpr '<==' FnName
674app :: SyntaxInfo -> IdrisParser PTerm
675app syn = do f <- simpleExpr syn
676 (do P.try $ reservedOp "<=="
679 return (PLet fc RigW (sMN 0 "match") NoFC
682 (PRef fc [] (sMN 0 "match")))
683 <?> "matching application expression") <|>
686 args <- many (do notEndApp; arg syn)
687 wargs <- if withAppAllowed syn && not (inPattern syn)
688 then many (do notEndApp; reservedOp "|"; expr' syn)
692 _ -> return (withApp fc (flattenFromInt fc f args) wargs))
693 <?> "function application"
695 -- bit of a hack to deal with the situation where we're applying a
696 -- literal to an argument, which we may want for obscure applications
697 -- of fromInteger, and this will help disambiguate better.
698 -- We know, at least, it won't be one of the constants!
699 flattenFromInt fc (PAlternative _ x alts) args
700 | Just i <- getFromInt alts
701 = PApp fc (PRef fc [] (sUN "fromInteger")) (i : args)
702 flattenFromInt fc f args = PApp fc f args
704 withApp fc tm [] = tm
705 withApp fc tm (a : as) = withApp fc (PWithApp fc tm a) as
707 getFromInt ((PApp _ (PRef _ _ n) [a]) : _) | n == sUN "fromInteger" = Just a
708 getFromInt (_ : xs) = getFromInt xs
709 getFromInt _ = Nothing
711{-| Parses a function argument
720arg :: SyntaxInfo -> IdrisParser PArg
721arg syn = implicitArg syn
722 <|> constraintArg syn
723 <|> do e <- simpleExpr syn
725 <?> "function argument"
727{-| Parses an implicit function argument
730 '{' Name ('=' Expr)? '}'
734implicitArg :: SyntaxInfo -> IdrisParser PArg
735implicitArg syn = do lchar '{'
738 v <- P.option (PRef nfc [nfc] n) (do lchar '='
741 return (pimp n v True)
742 <?> "implicit function argument"
744{-| Parses a constraint argument (for selecting a named interface implementation)
751constraintArg :: SyntaxInfo -> IdrisParser PArg
752constraintArg syn = do symbol "@{"
756 <?> "constraint argument"
758{-| Parses a quasiquote expression (for building reflected terms using the elaborator)
760> Quasiquote ::= '`(' Expr ')'
763quasiquote :: SyntaxInfo -> IdrisParser PTerm
764quasiquote syn = do startFC <- symbolFC "`("
765 e <- expr syn { syn_in_quasiquote = (syn_in_quasiquote syn) + 1 ,
768 do fc <- symbolFC ":"
769 ty <- expr syn { inPattern = False } -- don't allow antiquotes
771 endFC <- symbolFC ")"
772 mapM_ (uncurry highlightP) [(startFC, AnnKeyword), (endFC, AnnKeyword), (spanFC startFC endFC, AnnQuasiquote)]
774 Just (_, fc) -> highlightP fc AnnKeyword
776 return $ PQuasiquote e (fst <$> g)
779{-| Parses an unquoting inside a quasiquotation (for building reflected terms using the elaborator)
781> Unquote ::= ',' Expr
784unquote :: SyntaxInfo -> IdrisParser PTerm
785unquote syn = do guard (syn_in_quasiquote syn > 0)
786 startFC <- symbolFC "~"
787 e <- simpleExpr syn { syn_in_quasiquote = syn_in_quasiquote syn - 1 }
789 highlightP startFC AnnKeyword
790 highlightP (spanFC startFC endFC) AnnAntiquote
794{-| Parses a quotation of a name (for using the elaborator to resolve boring details)
796> NameQuote ::= '`{' Name '}'
799namequote :: SyntaxInfo -> IdrisParser PTerm
800namequote syn = do (startFC, res) <-
801 P.try (do fc <- symbolFC "`{{"
802 return (fc, False)) <|>
803 (do fc <- symbolFC "`{"
806 endFC <- if res then symbolFC "}" else symbolFC "}}"
807 mapM_ (uncurry highlightP)
808 [ (startFC, AnnKeyword)
809 , (endFC, AnnKeyword)
810 , (spanFC startFC endFC, AnnQuasiquote)
812 return $ PQuoteName n res nfc
816{-| Parses a record field setter expression
819 'record' '{' FieldTypeList '}';
824 | FieldType ',' FieldTypeList
834data SetOrUpdate = FieldSet PTerm | FieldUpdate PTerm
836recordType :: SyntaxInfo -> IdrisParser PTerm
838 do kw <- reservedFC "record"
843 rec <- optional (do notEndApp; simpleExpr syn)
844 highlightP kw AnnKeyword
849 return (PLam fc (sMN 0 "fldx") NoFC Placeholder
850 (applyAll fc fields (PRef fc [] (sMN 0 "fldx"))))
851 Just v -> return (applyAll fc fields v)
855 return (PLam fc (sMN 0 "fldx") NoFC Placeholder
856 (getAll fc (reverse fields)
857 (PRef fc [] (sMN 0 "fldx"))))
858 Just v -> return (getAll fc (reverse fields) v)
860 <?> "record setting expression"
861 where fieldSet :: IdrisParser ([Name], SetOrUpdate)
862 fieldSet = do ns <- fieldGet
865 return (ns, FieldSet e))
868 return (ns, FieldUpdate e)
871 fieldGet :: IdrisParser [Name]
872 fieldGet = P.sepBy1 (fst <$> fnName) (symbol "->")
874 fieldGetOrSet :: IdrisParser (Either [([Name], SetOrUpdate)] [Name])
875 fieldGetOrSet = P.try (Left <$> P.sepBy1 fieldSet (lchar ','))
879 applyAll :: FC -> [([Name], SetOrUpdate)] -> PTerm -> PTerm
881 applyAll fc ((ns, e) : es) x
882 = applyAll fc es (doUpdate fc ns e x)
884 doUpdate fc ns (FieldUpdate e) get
885 = let get' = getAll fc (reverse ns) get in
886 doUpdate fc ns (FieldSet (PApp fc e [pexp get'])) get
887 doUpdate fc [n] (FieldSet e) get
888 = PApp fc (PRef fc [] (mkType n)) [pexp e, pexp get]
889 doUpdate fc (n : ns) e get
890 = PApp fc (PRef fc [] (mkType n))
891 [pexp (doUpdate fc ns e (PApp fc (PRef fc [] n) [pexp get])),
894 getAll :: FC -> [Name] -> PTerm -> PTerm
895 getAll fc [n] e = PApp fc (PRef fc [] n) [pexp e]
896 getAll fc (n:ns) e = PApp fc (PRef fc [] n) [pexp (getAll fc ns e)]
899-- | Creates setters for record types on necessary functions
900mkType :: Name -> Name
901mkType (UN n) = sUN ("set_" ++ str n)
902mkType (MN 0 n) = sMN 0 ("set_" ++ str n)
903mkType (NS n s) = NS (mkType n) s
905{- | Parses a type signature
912TypeExpr ::= ConstraintList? Expr;
915typeExpr :: SyntaxInfo -> IdrisParser PTerm
916typeExpr syn = do cs <- if implicitAllowed syn then constraintList syn else return []
917 sc <- expr (allowConstr syn)
918 return (bindList (\r -> PPi (constraint { pcount = r })) cs sc)
921{- | Parses a lambda expression
924 '\\' TypeOptDeclList LambdaTail
925 | '\\' SimpleExprList LambdaTail
931 | SimpleExpr ',' SimpleExprList
940lambda :: SyntaxInfo -> IdrisParser PTerm
941lambda syn = do lchar '\\' <?> "lambda expression"
942 ((do xt <- P.try $ tyOptDeclList (disallowImp syn)
945 return (bindList (\r -> PLam fc) xt sc))
947 (do ps <- P.sepBy (do fc <- getFC
948 e <- simpleExpr (disallowImp (syn { inPattern = True }))
952 return (pmList (zip [0..] ps) sc)))
953 <?> "lambda expression"
954 where pmList :: [(Int, (FC, PTerm))] -> PTerm -> PTerm
956 pmList ((i, (fc, x)) : xs) sc
957 = PLam fc (sMN i "lamp") NoFC Placeholder
958 (PCase fc (PRef fc [] (sMN i "lamp"))
960 lambdaTail :: IdrisParser PTerm
961 lambdaTail = impossible <|> symbol "=>" *> expr syn
963{- | Parses a term rewrite expression
966 'rewrite' Expr ('==>' Expr)? 'in' Expr
970rewriteTerm :: SyntaxInfo -> IdrisParser PTerm
971rewriteTerm syn = do kw <- reservedFC "rewrite"
974 giving <- optional (do symbol "==>"; expr' syn)
975 using <- optional (do reserved "using"
978 kw' <- reservedFC "in"; sc <- expr syn
979 highlightP kw AnnKeyword
980 highlightP kw' AnnKeyword
981 return (PRewrite fc using prf sc giving)
982 <?> "term rewrite expression"
984{- |Parses a let binding
987 'let' Name TypeSig'? '=' Expr 'in' Expr
988| 'let' Expr' '=' Expr' 'in' Expr
995let_ :: SyntaxInfo -> IdrisParser PTerm
996let_ syn = P.try (do kw <- reservedFC "let"
997 ls <- indentedBlock (let_binding syn)
998 kw' <- reservedFC "in"; sc <- expr syn
999 highlightP kw AnnKeyword; highlightP kw' AnnKeyword
1000 return (buildLets ls sc))
1002 where buildLets [] sc = sc
1003 buildLets ((fc, PRef nfc _ n, ty, v, []) : ls) sc
1004 = PLet fc RigW n nfc ty v (buildLets ls sc)
1005 buildLets ((fc, pat, ty, v, alts) : ls) sc
1006 = PCase fc v ((pat, buildLets ls sc) : alts)
1008let_binding syn = do fc <- getFC;
1009 pat <- expr' (syn { inPattern = True })
1010 ty <- P.option Placeholder (do lchar ':'; expr' syn)
1012 v <- expr (syn { withAppAllowed = isVar pat })
1013 ts <- P.option [] (do lchar '|'
1014 P.sepBy1 (do_alt syn) (lchar '|'))
1015 return (fc,pat,ty,v,ts)
1016 where isVar (PRef _ _ _) = True
1019{- | Parses a conditional expression
1021If ::= 'if' Expr 'then' Expr 'else' Expr
1025if_ :: SyntaxInfo -> IdrisParser PTerm
1026if_ syn = (do ifFC <- reservedFC "if"
1029 thenFC <- reservedFC "then"
1031 elseFC <- reservedFC "else"
1033 mapM_ (flip highlightP AnnKeyword) [ifFC, thenFC, elseFC]
1034 return (PIfThenElse fc c t f))
1035 <?> "conditional expression"
1038{- | Parses a quote goal
1042 'quoteGoal' Name 'by' Expr 'in' Expr
1046quoteGoal :: SyntaxInfo -> IdrisParser PTerm
1047quoteGoal syn = do kw1 <- reservedFC "quoteGoal"; n <- fst <$> name;
1048 kw2 <- reservedFC "by"
1050 kw3 <- reservedFC "in"
1053 mapM_ (flip highlightP AnnKeyword) [kw1, kw2, kw3]
1054 return (PGoal fc r n sc)
1055 <?> "quote goal expression"
1057{- | Parses a dependent type signature
1060Pi ::= PiOpts Static? Pi'
1066 | '(' TypeDeclList ')' '->' Pi
1067 | '{' TypeDeclList '}' '->' Pi
1068 | '{' 'auto' TypeDeclList '}' '->' Pi
1069 | '{' 'default' SimpleExpr TypeDeclList '}' '->' Pi
1074bindsymbol opts st syn
1076 return (Exp opts st False RigW)
1078explicitPi opts st syn
1079 = do xt <- P.try (lchar '(' *> typeDeclList syn <* lchar ')')
1080 binder <- bindsymbol opts st syn
1081 sc <- expr (allowConstr syn)
1082 return (bindList (\r -> PPi (binder { pcount = r })) xt sc)
1084autoImplicit opts st syn
1085 = do kw <- reservedFC "auto"
1086 when (st == Static) $ fail "auto implicits can not be static"
1087 xt <- typeDeclList syn
1090 sc <- expr (allowConstr syn)
1091 highlightP kw AnnKeyword
1092 return (bindList (\r -> PPi
1093 (TacImp [] Dynamic (PTactics [ProofSearch True True 100 Nothing [] []]) r)) xt sc)
1095defaultImplicit opts st syn = do
1096 kw <- reservedFC "default"
1097 when (st == Static) $ fail "default implicits can not be static"
1099 script' <- simpleExpr syn
1100 let script = debindApp syn . desugar syn ist $ script'
1101 xt <- typeDeclList syn
1104 sc <- expr (allowConstr syn)
1105 highlightP kw AnnKeyword
1106 return (bindList (\r -> PPi (TacImp [] Dynamic script r)) xt sc)
1108normalImplicit opts st syn = do
1109 xt <- typeDeclList syn <* lchar '}'
1111 cs <- constraintList syn
1114 = if implicitAllowed syn
1115 then (Imp opts st False (Just (Impl False True False)) True RigW,
1117 else (Imp opts st False (Just (Impl False False False)) True RigW,
1118 Imp opts st False (Just (Impl True False False)) True RigW)
1119 return (bindList (\r -> PPi (im { pcount = r })) xt
1120 (bindList (\r -> PPi (cl { pcount = r })) cs sc))
1122constraintPi opts st syn =
1123 do cs <- constraintList1 syn
1125 if implicitAllowed syn
1126 then return (bindList (\r -> PPi constraint { pcount = r }) cs sc)
1127 else return (bindList (\r -> PPi (Imp opts st False (Just (Impl True False False)) True r))
1130implicitPi opts st syn =
1131 autoImplicit opts st syn
1132 <|> defaultImplicit opts st syn
1133 <|> normalImplicit opts st syn
1135unboundPi opts st syn = do
1137 (do binder <- bindsymbol opts st syn
1139 return (PPi binder (sUN "__pi_arg") NoFC x sc))
1142-- This is used when we need to disambiguate from a constraint list
1143unboundPiNoConstraint opts st syn = do
1145 (do binder <- bindsymbol opts st syn
1147 P.notFollowedBy $ reservedOp "=>"
1148 return (PPi binder (sUN "__pi_arg") NoFC x sc))
1149 <|> do P.notFollowedBy $ reservedOp "=>"
1153pi :: SyntaxInfo -> IdrisParser PTerm
1155 do opts <- piOpts syn
1157 explicitPi opts st syn
1158 <|> P.try (do lchar '{'; implicitPi opts st syn)
1159 <|> if constraintAllowed syn
1160 then P.try (unboundPiNoConstraint opts st syn)
1161 <|> constraintPi opts st syn
1162 else unboundPi opts st syn
1163 <?> "dependent type signature"
1165{- | Parses Possible Options for Pi Expressions
1170piOpts :: SyntaxInfo -> IdrisParser [ArgOpt]
1171piOpts syn | implicitAllowed syn =
1172 lchar '.' *> return [InaccessibleArg]
1174piOpts syn = return []
1176{- | Parses a type constraint list
1180 '(' Expr_List ')' '=>'
1185constraintList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1186constraintList syn = P.try (constraintList1 syn)
1189constraintList1 :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1190constraintList1 syn = P.try (do lchar '('
1191 tys <- P.sepBy1 nexpr (lchar ',')
1195 <|> P.try (do t <- opExpr (disallowImp syn)
1197 return [(RigW, defname, NoFC, t)])
1198 <?> "type constraint list"
1199 where nexpr = P.try (do (n, fc) <- name; lchar ':'
1200 e <- expr (disallowImp syn)
1201 return (RigW, n, fc, e))
1202 <|> do e <- expr (disallowImp syn)
1203 return (RigW, defname, NoFC, e)
1204 defname = sMN 0 "constraint"
1206{- | Parses a type declaration list
1209 FunctionSignatureList
1215FunctionSignatureList ::=
1217 | Name TypeSig ',' FunctionSignatureList
1221typeDeclList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1222typeDeclList syn = P.try (P.sepBy1 (do rig <- P.option RigW rigCount
1225 t <- typeExpr (disallowImp syn)
1226 return (rig, x, xfc, t))
1228 <|> do ns <- P.sepBy1 name (lchar ',')
1230 t <- typeExpr (disallowImp syn)
1231 return (map (\(x, xfc) -> (RigW, x, xfc, t)) ns)
1232 <?> "type declaration list"
1234 rigCount = do lchar '1'; return Rig1
1235 <|> do lchar '0'; return Rig0
1237{- | Parses a type declaration list with optional parameters
1240 NameOrPlaceholder TypeSig?
1241 | NameOrPlaceholder TypeSig? ',' TypeOptDeclList
1246NameOrPlaceHolder ::= Name | '_';
1249tyOptDeclList :: SyntaxInfo -> IdrisParser [(RigCount, Name, FC, PTerm)]
1250tyOptDeclList syn = P.sepBy1 (do (x, fc) <- nameOrPlaceholder
1251 t <- P.option Placeholder (do lchar ':'
1253 return (RigW, x, fc, t))
1255 <?> "type declaration list"
1256 where nameOrPlaceholder :: IdrisParser (Name, FC)
1257 nameOrPlaceholder = fnName
1259 return (sMN 0 "underscore", NoFC)
1260 <?> "name or placeholder"
1262{- | Parses a list literal expression e.g. [1,2,3] or a comprehension [ (x, y) | x <- xs , y <- ys ]
1266 | '[' Expr '|' DoList ']'
1283listExpr :: SyntaxInfo -> IdrisParser PTerm
1284listExpr syn = do (FC f (l, c) _) <- getFC
1285 lchar '['; fc <- getFC;
1286 (P.try . P.token $ do (char ']' <?> "end of list expression")
1287 (FC _ _ (l', c')) <- getFC
1288 return (mkNil (FC f (l, c) (l', c'))))
1289 <|> (do x <- expr (syn { withAppAllowed = False }) <?> "expression"
1290 (do P.try (lchar '|') <?> "list comprehension"
1291 qs <- P.sepBy1 (do_ syn) (lchar ',')
1293 return (PDoBlock (map addGuard qs ++
1294 [DoExp fc (PApp fc (PRef fc [] (sUN "pure"))
1296 (do xs <- many (do (FC fn (sl, sc) _) <- getFC
1297 lchar ',' <?> "list element"
1298 let commaFC = FC fn (sl, sc) (sl, sc + 1)
1300 return (elt, commaFC))
1301 (FC fn (sl, sc) _) <- getFC
1302 lchar ']' <?> "end of list expression"
1303 let rbrackFC = FC fn (sl, sc) (sl, sc+1)
1304 return (mkList fc rbrackFC ((x, (FC f (l, c) (l, c+1))) : xs))))
1305 <?> "list expression"
1307 mkNil :: FC -> PTerm
1308 mkNil fc = PRef fc [fc] (sUN "Nil")
1309 mkList :: FC -> FC -> [(PTerm, FC)] -> PTerm
1310 mkList errFC nilFC [] = PRef nilFC [nilFC] (sUN "Nil")
1311 mkList errFC nilFC ((x, fc) : xs) = PApp errFC (PRef fc [fc] (sUN "::")) [pexp x, pexp (mkList errFC nilFC xs)]
1312 addGuard :: PDo -> PDo
1313 addGuard (DoExp fc e) = DoExp fc (PApp fc (PRef fc [] (sUN "guard"))
1317{- | Parses a do-block
1319Do' ::= Do KeepTerminator;
1324 'do' OpenBlock Do'+ CloseBlock
1328doBlock :: SyntaxInfo -> IdrisParser PTerm
1330 = do kw <- reservedFC "do"
1331 ds <- indentedBlock1 (do_ syn)
1332 highlightP kw AnnKeyword
1333 return (PDoBlock ds)
1336{- | Parses an expression inside a do block
1339 'let' Name TypeSig'? '=' Expr
1340 | 'let' Expr' '=' Expr
1348do_ :: SyntaxInfo -> IdrisParser PDo
1350 = P.try (do kw <- reservedFC "let"
1352 ty <- P.option Placeholder (do lchar ':'
1357 highlightP kw AnnKeyword
1358 return (DoLet fc RigW i ifc ty e))
1359 <|> P.try (do kw <- reservedFC "let"
1364 highlightP kw AnnKeyword
1365 return (DoLetP fc i sc))
1366 <|> P.try (do kw <- reservedFC "rewrite"
1369 highlightP kw AnnKeyword
1370 return (DoRewrite fc sc))
1371 <|> P.try (do (i, ifc) <- name
1374 e <- expr (syn { withAppAllowed = False });
1375 P.option (DoBind fc i ifc e)
1377 ts <- P.sepBy1 (do_alt (syn { withAppAllowed = False })) (lchar '|')
1378 return (DoBindP fc (PRef ifc [ifc] i) e ts)))
1379 <|> P.try (do i <- expr' syn
1382 e <- expr (syn { withAppAllowed = False });
1383 P.option (DoBindP fc i e [])
1385 ts <- P.sepBy1 (do_alt (syn { withAppAllowed = False })) (lchar '|')
1386 return (DoBindP fc i e ts)))
1387 <|> do e <- expr syn
1390 <?> "do block expression"
1392do_alt syn = do l <- expr' syn
1393 P.option (Placeholder, l)
1398{- | Parses an expression in idiom brackets
1400Idiom ::= '[|' Expr '|]';
1403idiom :: SyntaxInfo -> IdrisParser PTerm
1407 e <- expr (syn { withAppAllowed = False })
1409 return (PIdiom fc e)
1410 <?> "expression in idiom brackets"
1412{- |Parses a constant or literal expression
1434constants :: [(String, Idris.Core.TT.Const)]
1436 [ ("Integer", AType (ATInt ITBig))
1437 , ("Int", AType (ATInt ITNative))
1438 , ("Char", AType (ATInt ITChar))
1439 , ("Double", AType ATFloat)
1440 , ("String", StrType)
1441 , ("prim__WorldType", WorldType)
1442 , ("prim__TheWorld", TheWorld)
1443 , ("Bits8", AType (ATInt (ITFixed IT8)))
1444 , ("Bits16", AType (ATInt (ITFixed IT16)))
1445 , ("Bits32", AType (ATInt (ITFixed IT32)))
1446 , ("Bits64", AType (ATInt (ITFixed IT64)))
1449-- | Parse a constant and its source span
1450constant :: IdrisParser (Idris.Core.TT.Const, FC)
1451constant = P.choice [ do fc <- reservedFC name; return (ty, fc)
1452 | (name, ty) <- constants
1454 <|> do (f, fc) <- P.try float; return (Fl f, fc)
1455 <|> do (i, fc) <- natural; return (BI i, fc)
1456 <|> do (s, fc) <- verbatimStringLiteral; return (Str s, fc)
1457 <|> do (s, fc) <- stringLiteral; return (Str s, fc)
1458 <|> do (c, fc) <- P.try charLiteral; return (Ch c, fc) --Currently ambigous with symbols
1459 <?> "constant or literal"
1461{- | Parses a verbatim multi-line string literal (triple-quoted)
1465 '\"\"\"' ~'\"\"\"' '\"\"\"'
1469verbatimStringLiteral :: MonadicParsing m => m (String, FC)
1470verbatimStringLiteral = P.token $ do (FC f start _) <- getFC
1471 P.try $ string "\"\"\""
1472 str <- P.manyTill P.anyChar $ P.try (string "\"\"\"")
1473 (FC _ _ end) <- getFC
1474 return (str, FC f start end)
1476{- | Parses a static modifier
1484static :: IdrisParser Static
1485static = do reserved "%static"; return Static
1486 <|> do reserved "[static]"
1488 parserWarning fc Nothing (Msg "The use of [static] is deprecated, use %static instead.")
1491 <?> "static modifier"
1493{- | Parses a tactic script
1496Tactic ::= 'intro' NameList?
1498 | 'refine' Name Imp+
1503 | 'let' Name ':' Expr' '=' Expr
1504 | 'let' Name '=' Expr
1507 | 'applyTactic' Expr
1510 | 'try' Tactic '|' Tactic
1528 | Tactic ';' TacticSeq
1533-- | A specification of the arguments that tactics can take
1534data TacticArg = NameTArg -- ^ Names: n1, n2, n3, ... n
1539-- The FIXMEs are Issue #1766 in the issue tracker.
1540-- https://github.com/idris-lang/Idris-dev/issues/1766
1541-- | A list of available tactics and their argument requirements
1542tactics :: [([String], Maybe TacticArg, SyntaxInfo -> IdrisParser PTactic)]
1544 [ (["intro"], Nothing, const $ -- FIXME syntax for intro (fresh name)
1545 do ns <- P.sepBy (spaced (fst <$> name)) (lchar ','); return $ Intro ns)
1546 , noArgs ["intros"] Intros
1547 , noArgs ["unfocus"] Unfocus
1548 , (["refine"], Just ExprTArg, const $
1549 do n <- spaced (fst <$> fnName)
1551 return $ Refine n imps)
1552 , (["claim"], Nothing, \syn ->
1553 do n <- indentGt *> (fst <$> name)
1554 goal <- indentGt *> expr syn
1555 return $ Claim n goal)
1556 , (["mrefine"], Just ExprTArg, const $
1557 do n <- spaced (fst <$> fnName)
1558 return $ MatchRefine n)
1559 , expressionTactic ["rewrite"] Rewrite
1560 , expressionTactic ["case"] CaseTac
1561 , expressionTactic ["induction"] Induction
1562 , expressionTactic ["equiv"] Equiv
1563 , (["let"], Nothing, \syn -> -- FIXME syntax for let
1564 do n <- (indentGt *> (fst <$> name))
1565 (do indentGt *> lchar ':'
1566 ty <- indentGt *> expr' syn
1567 indentGt *> lchar '='
1568 t <- indentGt *> expr syn
1570 return $ LetTacTy n (desugar syn i ty) (desugar syn i t))
1571 <|> (do indentGt *> lchar '='
1572 t <- indentGt *> expr syn
1574 return $ LetTac n (desugar syn i t)))
1576 , (["focus"], Just ExprTArg, const $
1577 do n <- spaced (fst <$> name)
1579 , expressionTactic ["exact"] Exact
1580 , expressionTactic ["applyTactic"] ApplyTactic
1581 , expressionTactic ["byReflection"] ByReflection
1582 , expressionTactic ["reflect"] Reflect
1583 , expressionTactic ["fill"] Fill
1584 , (["try"], Just AltsTArg, \syn ->
1585 do t <- spaced (tactic syn)
1587 t1 <- spaced (tactic syn)
1589 , noArgs ["compute"] Compute
1590 , noArgs ["trivial"] Trivial
1591 , noArgs ["unify"] DoUnify
1592 , (["search"], Nothing, const $
1593 do depth <- P.option 10 $ fst <$> natural
1594 return (ProofSearch True True (fromInteger depth) Nothing [] []))
1595 , noArgs ["implementation"] TCImplementation
1596 , noArgs ["solve"] Solve
1597 , noArgs ["attack"] Attack
1598 , noArgs ["state", ":state"] ProofState
1599 , noArgs ["term", ":term"] ProofTerm
1600 , noArgs ["undo", ":undo"] Undo
1601 , noArgs ["qed", ":qed"] Qed
1602 , noArgs ["abandon", ":q"] Abandon
1603 , noArgs ["skip"] Skip
1604 , noArgs ["sourceLocation"] SourceFC
1605 , expressionTactic [":e", ":eval"] TEval
1606 , expressionTactic [":t", ":type"] TCheck
1607 , expressionTactic [":search"] TSearch
1608 , (["fail"], Just StringLitTArg, const $
1609 do msg <- fst <$> stringLiteral
1610 return $ TFail [Idris.Core.TT.TextPart msg])
1611 , ([":doc"], Just ExprTArg, const $
1613 doc <- (Right . fst <$> constant) <|> (Left . fst <$> fnName)
1615 return (TDocStr doc))
1618 expressionTactic names tactic = (names, Just ExprTArg, \syn ->
1619 do t <- spaced (expr syn)
1621 return $ tactic (desugar syn i t))
1622 noArgs names tactic = (names, Nothing, const (return tactic))
1623 spaced parser = indentGt *> parser
1624 imp :: IdrisParser Bool
1625 imp = do lchar '?'; return False
1626 <|> do lchar '_'; return True
1629tactic :: SyntaxInfo -> IdrisParser PTactic
1630tactic syn = P.choice [ do P.choice (map reserved names); parser syn
1631 | (names, _, parser) <- tactics ]
1635 ts <- P.sepBy1 (tactic syn) (lchar ';')
1637 return $ TSeq t (mergeSeq ts)
1638 <|> ((lchar ':' >> empty) <?> "prover command")
1641 mergeSeq :: [PTactic] -> PTactic
1643 mergeSeq (t:ts) = TSeq t (mergeSeq ts)
1645-- | Parses a tactic as a whole
1646fullTactic :: SyntaxInfo -> IdrisParser PTactic
1647fullTactic 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