1{-# LANGUAGE GeneralizedNewtypeDeriving, ConstraintKinds, PatternGuards #-}
3module Idris.Parser(module Idris.Parser,
4 module Idris.ParseExpr,
5 module Idris.ParseData,
6 module Idris.ParseHelpers,
7 module Idris.ParseOps) where
9import Prelude hiding (pi)
11import qualified System.Directory as Dir (makeAbsolute)
13import Text.Trifecta.Delta
14import Text.Trifecta hiding (span, stringLiteral, charLiteral, natural, symbol, char, string, whiteSpace, Err)
15import Text.Parser.LookAhead
16import Text.Parser.Expression
17import qualified Text.Parser.Token as Tok
18import qualified Text.Parser.Char as Chr
19import qualified Text.Parser.Token.Highlight as Hi
21import Text.PrettyPrint.ANSI.Leijen (Doc, plain)
22import qualified Text.PrettyPrint.ANSI.Leijen as ANSI
24import Idris.AbsSyntax hiding (namespace, params)
27import Idris.Delaborate
29import Idris.Elab.Value
38import Idris.ParseHelpers
43import Idris.Docstrings hiding (Unchecked)
47import Util.DynamicLinker
48import Util.System (readSource, writeSource)
49import qualified Util.Pretty as P
52import Idris.Core.Evaluate
54import Control.Applicative hiding (Const)
56import Control.Monad.State.Strict
60import qualified Data.List.Split as Spl
65import Data.Foldable (asum)
66import Data.Generics.Uniplate.Data (descendM)
67import qualified Data.Map as M
68import qualified Data.HashSet as HS
69import qualified Data.Text as T
70import qualified Data.ByteString.UTF8 as UTF8
71import qualified Data.Set as S
80 grammar shortcut notation:
81 ~CHARSEQ = complement of char sequence (i.e. any character except CHARSEQ)
82 RULE? = optional rule (i.e. RULE or nothing)
83 RULE* = repeated rule (i.e. RULE zero or more times)
84 RULE+ = repeated rule with at least one match (i.e. RULE one or more times)
85 RULE! = invalid rule (i.e. rule that is not valid in context, report meaningful error in case)
86 RULE{n} = rule repeated n times
92{- | Parses module definition
95 ModuleHeader ::= DocComment_t? 'module' Identifier_t ';'?;
98moduleHeader :: IdrisParser (Maybe (Docstring ()), [String], [(FC, OutputAnnotation)])
99moduleHeader = try (do docs <- optional docComment
102 (i, ifc) <- identifier
103 option ';' (lchar ';')
104 let modName = moduleName i
105 return (fmap fst docs,
107 [(ifc, AnnNamespace (map T.pack modName) Nothing)]))
108 <|> try (do lchar '%'; reserved "unqualified"
109 return (Nothing, [], []))
110 <|> return (Nothing, moduleName "Main", [])
111 where moduleName x = case span (/='.') x of
113 (x, '.':y) -> x : moduleName y
114 noArgs (Just (_, args)) | not (null args) = fail "Modules do not take arguments"
117data ImportInfo = ImportInfo { import_reexport :: Bool
118 , import_path :: FilePath
119 , import_rename :: Maybe (String, FC)
120 , import_namespace :: [T.Text]
121 , import_location :: FC
122 , import_modname_location :: FC
125{- | Parses an import statement
128 Import ::= 'import' Identifier_t ';'?;
131import_ :: IdrisParser ImportInfo
132import_ = do fc <- getFC
134 reexport <- option False (do reservedHL "public"
136 (id, idfc) <- identifier
137 newName <- optional (do reservedHL "as"
139 option ';' (lchar ';')
140 return $ ImportInfo reexport (toPath id)
141 (fmap (\(n, fc) -> (toPath n, fc)) newName)
142 (map T.pack $ ns id) fc idfc
143 <?> "import statement"
144 where ns = Spl.splitOn "."
145 toPath = foldl1' (</>) . ns
147{- | Parses program source
153prog :: SyntaxInfo -> IdrisParser [PDecl]
154prog syn = do whiteSpace
155 decls <- many (decl syn)
156 let c = (concat decls)
158 Nothing -> do notOpenBraces; eof
162 put ist { idris_parsedSpan = Just (FC (fc_fname fc) (0,0) (fc_end fc)),
163 ibc_write = IBCParsedRegion fc : ibc_write ist }
166{-| Parses a top-level declaration
186decl :: SyntaxInfo -> IdrisParser [PDecl]
187decl syn = try (externalDecl syn)
191internalDecl :: SyntaxInfo -> IdrisParser [PDecl]
194 -- if we're after maxline, stop here
195 let continue = case maxline syn of
197 Just l -> if fst (fc_end fc) > l
198 then mut_nesting syn /= 0
200 if continue then do notEndBlock
202 else fail "End of readable input"
203 where declBody :: IdrisParser [PDecl]
211 <|> do d <- dsl syn; return [d]
215 <|> do import_; fail "imports must be at top of file"
217 declBody' :: IdrisParser [PDecl]
218 declBody' = do d <- decl' syn
220 let d' = fmap (debindApp syn . (desugar syn i)) d
223{- | Parses a top-level declaration with possible syntax sugar
235decl' :: SyntaxInfo -> IdrisParser PDecl
244externalDecl :: SyntaxInfo -> IdrisParser [PDecl]
245externalDecl syn = do i <- get
247 FC fn start _ <- getFC
248 decls <- declExtensions syn (syntaxRulesList $ syntax_rules i)
250 let outerFC = FC fn start end
251 return $ map (mapPDeclFC (fixFC outerFC)
255 -- | Fix non-highlighting FCs to prevent spurious error location reports
256 fixFC :: FC -> FC -> FC
257 fixFC outer inner | inner `fcIn` outer = inner
259 -- | Fix highlighting FCs by obliterating them, to avoid spurious highlights
260 fixFCH fn outer inner | inner `fcIn` outer = inner
261 | otherwise = FileFC fn
263declExtensions :: SyntaxInfo -> [Syntax] -> IdrisParser [PDecl]
264declExtensions syn rules = declExtension syn [] (filter isDeclRule rules)
265 <?> "user-defined declaration"
267 isDeclRule (DeclRule _ _) = True
270declExtension :: SyntaxInfo -> [Maybe (Name, SynMatch)] -> [Syntax]
271 -> IdrisParser [PDecl]
272declExtension syn ns rules =
273 choice $ flip map (groupBy (ruleGroup `on` syntaxSymbols) rules) $ \rs ->
274 case head rs of -- can never be []
275 DeclRule (symb:_) _ -> try $ do
277 declExtension syn (n : ns) [DeclRule ss t | (DeclRule (_:ss) t) <- rs]
278 -- If we have more than one Rule in this bucket, our grammar is
280 DeclRule [] dec -> let r = map (update (mapMaybe id ns)) dec in
284 update :: [(Name, SynMatch)] -> PDecl -> PDecl
285 update ns = updateNs ns . fmap (updateRefs ns) . fmap (updateSynMatch ns)
287 updateRefs ns = mapPT newref
289 newref (PRef fc fcs n) = PRef fc fcs (updateB ns n)
292 -- Below is a lot of tedious boilerplate which updates any top level
293 -- names in the declaration. It will only change names which are bound in
294 -- the declaration (including method names in classes and field names in
295 -- record declarations, not including pattern variables)
296 updateB :: [(Name, SynMatch)] -> Name -> Name
297 updateB ns (NS n mods) = NS (updateB ns n) mods
298 updateB ns n = case lookup n ns of
299 Just (SynBind tfc t) -> t
302 updateNs :: [(Name, SynMatch)] -> PDecl -> PDecl
303 updateNs ns (PTy doc argdoc s fc o n fc' t)
304 = PTy doc argdoc s fc o (updateB ns n) fc' t
305 updateNs ns (PClauses fc o n cs)
306 = PClauses fc o (updateB ns n) (map (updateClause ns) cs)
307 updateNs ns (PCAF fc n t) = PCAF fc (updateB ns n) t
308 updateNs ns (PData ds cds s fc o dat)
309 = PData ds cds s fc o (updateData ns dat)
310 updateNs ns (PParams fc ps ds) = PParams fc ps (map (updateNs ns) ds)
311 updateNs ns (PNamespace s fc ds) = PNamespace s fc (map (updateNs ns) ds)
312 updateNs ns (PRecord doc syn fc o n fc' ps pdocs fields cname cdoc s)
313 = PRecord doc syn fc o (updateB ns n) fc' ps pdocs
314 (map (updateField ns) fields)
315 (updateRecCon ns cname)
318 updateNs ns (PClass docs s fc cs cn fc' ps pdocs pdets ds cname cdocs)
319 = PClass docs s fc cs (updateB ns cn) fc' ps pdocs pdets
320 (map (updateNs ns) ds)
321 (updateRecCon ns cname)
323 updateNs ns (PInstance docs pdocs s fc cs cn fc' ps ity ni ds)
324 = PInstance docs pdocs s fc cs (updateB ns cn) fc'
325 ps ity (fmap (updateB ns) ni)
326 (map (updateNs ns) ds)
327 updateNs ns (PMutual fc ds) = PMutual fc (map (updateNs ns) ds)
328 updateNs ns (PProvider docs s fc fc' pw n)
329 = PProvider docs s fc fc' pw (updateB ns n)
332 updateRecCon ns Nothing = Nothing
333 updateRecCon ns (Just (n, fc)) = Just (updateB ns n, fc)
335 updateField ns (m, p, t, doc) = (updateRecCon ns m, p, t, doc)
337 updateClause ns (PClause fc n t ts t' ds)
338 = PClause fc (updateB ns n) t ts t' (map (update ns) ds)
339 updateClause ns (PWith fc n t ts t' m ds)
340 = PWith fc (updateB ns n) t ts t' m (map (update ns) ds)
341 updateClause ns (PClauseR fc ts t ds)
342 = PClauseR fc ts t (map (update ns) ds)
343 updateClause ns (PWithR fc ts t m ds)
344 = PWithR fc ts t m (map (update ns) ds)
346 updateData ns (PDatadecl n fc t cs)
347 = PDatadecl (updateB ns n) fc t (map (updateCon ns) cs)
348 updateData ns (PLaterdecl n fc t)
349 = PLaterdecl (updateB ns n) fc t
351 updateCon ns (cd, ads, cn, fc, ty, fc', fns)
352 = (cd, ads, updateB ns cn, fc, ty, fc', fns)
354 ruleGroup [] [] = True
355 ruleGroup (s1:_) (s2:_) = s1 == s2
356 ruleGroup _ _ = False
358 extSymbol :: SSymbol -> IdrisParser (Maybe (Name, SynMatch))
359 extSymbol (Keyword n) = do fc <- reservedFC (show n)
360 highlightP fc AnnKeyword
362 extSymbol (Expr n) = do tm <- expr syn
363 return $ Just (n, SynTm tm)
364 extSymbol (SimpleExpr n) = do tm <- simpleExpr syn
365 return $ Just (n, SynTm tm)
366 extSymbol (Binding n) = do (b, fc) <- name
367 return $ Just (n, SynBind fc b)
368 extSymbol (Symbol s) = do fc <- symbolFC s
369 highlightP fc AnnKeyword
372{- | Parses a syntax extension declaration (and adds the rule to parser state)
375 SyntaxDecl ::= SyntaxRule;
378syntaxDecl :: SyntaxInfo -> IdrisParser PDecl
379syntaxDecl syn = do s <- syntaxRule syn
381 put (i `addSyntax` s)
383 return (PSyntax fc s)
385-- | Extend an 'IState' with a new syntax extension. See also 'addReplSyntax'.
386addSyntax :: IState -> Syntax -> IState
387addSyntax i s = i { syntax_rules = updateSyntaxRules [s] rs,
388 syntax_keywords = ks ++ ns,
389 ibc_write = IBCSyntax s : map IBCKeyword ks ++ ibc }
390 where rs = syntax_rules i
391 ns = syntax_keywords i
393 ks = map show (syntaxNames s)
395-- | Like 'addSyntax', but no effect on the IBC.
396addReplSyntax :: IState -> Syntax -> IState
397addReplSyntax i s = i { syntax_rules = updateSyntaxRules [s] rs,
398 syntax_keywords = ks ++ ns }
399 where rs = syntax_rules i
400 ns = syntax_keywords i
401 ks = map show (syntaxNames s)
403{- | Parses a syntax extension declaration
406SyntaxRuleOpts ::= 'term' | 'pattern';
411 SyntaxRuleOpts? 'syntax' SyntaxSym+ '=' TypeExpr Terminator;
415SyntaxSym ::= '[' Name_t ']'
422syntaxRule :: SyntaxInfo -> IdrisParser Syntax
426 sty <- option AnySyntax
427 (do reservedHL "term"; return TermSyntax
428 <|> do reservedHL "pattern"; return PatternSyntax)
431 syms <- some syntaxSym
432 when (all isExpr syms) $ unexpected "missing keywords in syntax rule"
433 let ns = mapMaybe getName syms
434 when (length ns /= length (nub ns))
435 $ unexpected "repeated variable in syntax rule"
437 tm <- typeExpr (allowImp syn) >>= uniquifyBinders [n | Binding n <- syms]
439 return (Rule (mkSimple syms) tm sty)
440 <|> do reservedHL "decl"; reservedHL "syntax"
441 syms <- some syntaxSym
442 when (all isExpr syms) $ unexpected "missing keywords in syntax rule"
443 let ns = mapMaybe getName syms
444 when (length ns /= length (nub ns))
445 $ unexpected "repeated variable in syntax rule"
448 dec <- some (decl syn)
450 return (DeclRule (mkSimple syms) (concat dec))
452 isExpr (Expr _) = True
454 getName (Expr n) = Just n
456 -- Can't parse two full expressions (i.e. expressions with application) in a row
457 -- so change them both to a simple expression
458 mkSimple (Expr e : es) = SimpleExpr e : mkSimple' es
459 mkSimple xs = mkSimple' xs
461 mkSimple' (Expr e : Expr e1 : es) = SimpleExpr e : SimpleExpr e1 :
463 -- Can't parse a full expression followed by operator like characters due to ambiguity
464 mkSimple' (Expr e : Symbol s : es)
465 | takeWhile (`elem` opChars) ts /= "" = SimpleExpr e : Symbol s : mkSimple' es
466 where ts = dropWhile isSpace . dropWhileEnd isSpace $ s
467 mkSimple' (e : es) = e : mkSimple' es
470 -- Prevent syntax variable capture by making all binders under syntax unique
471 -- (the ol' Common Lisp GENSYM approach)
472 uniquifyBinders :: [Name] -> PTerm -> IdrisParser PTerm
473 uniquifyBinders userNames = fixBind []
475 fixBind :: [(Name, Name)] -> PTerm -> IdrisParser PTerm
476 fixBind rens (PRef fc hls n) | Just n' <- lookup n rens =
477 return $ PRef fc hls n'
478 fixBind rens (PPatvar fc n) | Just n' <- lookup n rens =
479 return $ PPatvar fc n'
480 fixBind rens (PLam fc n nfc ty body)
481 | n `elem` userNames = liftM2 (PLam fc n nfc) (fixBind rens ty) (fixBind rens body)
483 do ty' <- fixBind rens ty
485 body' <- fixBind ((n,n'):rens) body
486 return $ PLam fc n' nfc ty' body'
487 fixBind rens (PPi plic n nfc argTy body)
488 | n `elem` userNames = liftM2 (PPi plic n nfc) (fixBind rens argTy) (fixBind rens body)
490 do ty' <- fixBind rens argTy
492 body' <- fixBind ((n,n'):rens) body
493 return $ (PPi plic n' nfc ty' body')
494 fixBind rens (PLet fc n nfc ty val body)
495 | n `elem` userNames = liftM3 (PLet fc n nfc)
500 do ty' <- fixBind rens ty
501 val' <- fixBind rens val
503 body' <- fixBind ((n,n'):rens) body
504 return $ PLet fc n' nfc ty' val' body'
505 fixBind rens (PMatchApp fc n) | Just n' <- lookup n rens =
506 return $ PMatchApp fc n'
507 fixBind rens x = descendM (fixBind rens) x
509 gensym :: Name -> IdrisParser Name
510 gensym n = do ist <- get
511 let idx = idris_name ist
512 put ist { idris_name = idx + 1 }
513 return $ sMN idx (show n)
515{- | Parses a syntax symbol (either binding variable, keyword or expression)
518SyntaxSym ::= '[' Name_t ']'
525syntaxSym :: IdrisParser SSymbol
526syntaxSym = try (do lchar '['; n <- fst <$> name; lchar ']'
528 <|> try (do lchar '{'; n <- fst <$> name; lchar '}'
530 <|> do n <- fst <$> iName []
532 <|> do sym <- fmap fst stringLiteral
536{- | Parses a function declaration with possible syntax sugar
539 FunDecl ::= FunDecl';
542fnDecl :: SyntaxInfo -> IdrisParser [PDecl]
543fnDecl syn = try (do notEndBlock
546 let d' = fmap (desugar syn i) d
547 return [d']) <?> "function declaration"
549{-| Parses a function declaration
553 DocComment_t? FnOpts* Accessibility? FnOpts* FnName TypeSig Terminator
560fnDecl' :: SyntaxInfo -> IdrisParser PDecl
561fnDecl' syn = checkFixity $
562 do (doc, argDocs, fc, opts', n, nfc, acc) <- try (do
564 (doc, argDocs) <- docstring syn
566 let initOpts = if default_total ist
569 opts <- fnOpts initOpts
570 acc <- optional accessibility
572 (n_in, nfc) <- fnName
573 let n = expandNS syn n_in
576 return (doc, argDocs, fc, opts', n, nfc, acc))
577 ty <- typeExpr (allowImp syn)
580 return (PTy doc argDocs syn fc opts' n nfc ty)
584 <?> "function declaration"
585 where checkFixity :: IdrisParser PDecl -> IdrisParser PDecl
586 checkFixity p = do decl <- p
588 Nothing -> return decl
589 Just n -> do fOk <- fixityOK n
591 "Missing fixity declaration for " ++ show n
593 getName (PTy _ _ _ _ _ n _ _) = Just n
595 fixityOK (NS n _) = fixityOK n
596 fixityOK (UN n) | all (flip elem opChars) (str n) =
597 do fixities <- fmap idris_infixes get
598 return . elem (str n) . map (\ (Fix _ op) -> op) $ fixities
599 | otherwise = return True
600 fixityOK _ = return True
602{-| Parses function options given initial options
611 | '%' 'error_handler'
613 | '%' 'specialise' '[' NameTimesList? ']'
618NameTimes ::= FnName Natural?;
624 | NameTimes ',' NameTimesList
628-- FIXME: Check compatability for function options (i.e. partal/total)
630-- Issue #1574 on the issue tracker.
631-- https://github.com/idris-lang/Idris-dev/issues/1574
632fnOpts :: [FnOpt] -> IdrisParser [FnOpt]
634 = do reservedHL "total"; fnOpts (TotalFn : opts)
635 <|> do reservedHL "partial"; fnOpts (PartialFn : (opts \\ [TotalFn]))
636 <|> do reservedHL "covering"; fnOpts (CoveringFn : (opts \\ [TotalFn]))
637 <|> do try (lchar '%' *> reserved "export"); c <- fmap fst stringLiteral;
638 fnOpts (CExport c : opts)
639 <|> do try (lchar '%' *> reserved "no_implicit");
640 fnOpts (NoImplicit : opts)
641 <|> do try (lchar '%' *> reserved "inline");
642 fnOpts (Inlinable : opts)
643 <|> do try (lchar '%' *> reserved "assert_total");
644 fnOpts (AssertTotal : opts)
645 <|> do try (lchar '%' *> reserved "error_handler");
646 fnOpts (ErrorHandler : opts)
647 <|> do try (lchar '%' *> reserved "error_reverse");
648 fnOpts (ErrorReverse : opts)
649 <|> do try (lchar '%' *> reserved "reflection");
650 fnOpts (Reflection : opts)
651 <|> do try (lchar '%' *> reserved "hint");
652 fnOpts (AutoHint : opts)
653 <|> do lchar '%'; reserved "specialise";
654 lchar '['; ns <- sepBy nameTimes (lchar ','); lchar ']'
655 fnOpts (Specialise ns : opts)
656 <|> do reservedHL "implicit"; fnOpts (Implicit : opts)
658 <?> "function modifier"
659 where nameTimes :: IdrisParser (Name, Maybe Int)
660 nameTimes = do n <- fst <$> fnName
661 t <- option Nothing (do reds <- fmap fst natural
662 return (Just (fromInteger reds)))
665{- | Parses a postulate
669 DocComment_t? 'postulate' FnOpts* Accesibility? FnOpts* FnName TypeSig Terminator
673postulate :: SyntaxInfo -> IdrisParser PDecl
674postulate syn = do (doc, ext)
675 <- try $ do (doc, _) <- docstring syn
680 let initOpts = if default_total ist
683 opts <- fnOpts initOpts
684 acc <- optional accessibility
686 (n_in, nfc) <- fnName
687 let n = expandNS syn n_in
689 ty <- typeExpr (allowImp syn)
693 return (PPostulate ext doc syn fc nfc opts' n ty)
695 where ppostDecl = do fc <- reservedHL "postulate"; return False
696 <|> do lchar '%'; reserved "extern"; return True
697{- | Parses a using declaration
701 'using' '(' UsingDeclList ')' OpenBlock Decl* CloseBlock
705using_ :: SyntaxInfo -> IdrisParser [PDecl]
707 do reservedHL "using"
708 lchar '('; ns <- usingDeclList syn; lchar ')'
710 let uvars = using syn
711 ds <- many (decl (syn { using = uvars ++ ns }))
714 <?> "using declaration"
716{- | Parses a parameters declaration
720 'parameters' '(' TypeDeclList ')' OpenBlock Decl* CloseBlock
724params :: SyntaxInfo -> IdrisParser [PDecl]
726 do reservedHL "parameters"; lchar '('; ns <- typeDeclList syn; lchar ')'
727 let ns' = [(n, ty) | (n, _, ty) <- ns]
729 let pvars = syn_params syn
730 ds <- many (decl syn { syn_params = pvars ++ ns' })
733 return [PParams fc ns' (concat ds)]
734 <?> "parameters declaration"
736{- | Parses a mutual declaration (for mutually recursive functions)
740 'mutual' OpenBlock Decl* CloseBlock
744mutual :: SyntaxInfo -> IdrisParser [PDecl]
746 do reservedHL "mutual"
748 let pvars = syn_params syn
749 ds <- many (decl (syn { mut_nesting = mut_nesting syn + 1 } ))
752 return [PMutual fc (concat ds)]
755{-| Parses a namespace declaration
759 'namespace' identifier OpenBlock Decl+ CloseBlock
763namespace :: SyntaxInfo -> IdrisParser [PDecl]
765 do reservedHL "namespace"
766 (n, nfc) <- identifier
768 ds <- some (decl syn { syn_namespace = n : syn_namespace syn })
770 return [PNamespace n nfc (concat ds)]
771 <?> "namespace declaration"
773{- | Parses a methods block (for instances)
776 InstanceBlock ::= 'where' OpenBlock FnDecl* CloseBlock
779instanceBlock :: SyntaxInfo -> IdrisParser [PDecl]
780instanceBlock syn = do reservedHL "where"
782 ds <- many (fnDecl syn)
787{- | Parses a methods and instances block (for type classes)
798 'where' OpenBlock Constructor? MethodOrInstance* CloseBlock
802classBlock :: SyntaxInfo -> IdrisParser (Maybe (Name, FC), Docstring (Either Err PTerm), [PDecl])
803classBlock syn = do reservedHL "where"
805 (cn, cd) <- option (Nothing, emptyDocstring) $
806 try (do (doc, _) <- option noDocs docComment
808 return (Just n, doc))
810 let cd' = annotate syn ist cd
812 ds <- many (notEndBlock >> instance_ syn <|> fnDecl syn)
814 return (cn, cd', concat ds)
818 constructor :: IdrisParser (Name, FC)
819 constructor = reservedHL "constructor" *> fnName
821 annotate :: SyntaxInfo -> IState -> Docstring () -> Docstring (Either Err PTerm)
822 annotate syn ist = annotCode $ tryFullExpr syn ist
824{-| Parses a type class declaration
829 | '(' Name ':' Expr ')'
835 DocComment_t? Accessibility? 'class' ConstraintList? Name ClassArgument* ClassBlock?
839class_ :: SyntaxInfo -> IdrisParser [PDecl]
840class_ syn = do (doc, argDocs, acc)
841 <- try (do (doc, argDocs) <- docstring syn
842 acc <- optional accessibility
844 return (doc, argDocs, acc))
846 cons <- constraintList syn
847 let cons' = [(c, ty) | (c, _, ty) <- cons]
848 (n_in, nfc) <- fnName
849 let n = expandNS syn n_in
851 fds <- option [(cn, NoFC) | (cn, _, _) <- cs] fundeps
852 (cn, cd, ds) <- option (Nothing, fst noDocs, []) (classBlock syn)
853 accData acc n (concatMap declared ds)
854 return [PClass doc syn fc cons' n nfc cs argDocs fds ds cn cd]
855 <?> "type-class declaration"
857 fundeps :: IdrisParser [(Name, FC)]
858 fundeps = do lchar '|'; sepBy name (lchar ',')
860 carg :: IdrisParser (Name, FC, PTerm)
861 carg = do lchar '('; (i, ifc) <- name; lchar ':'; ty <- expr syn; lchar ')'
863 <|> do (i, ifc) <- name
865 return (i, ifc, PType fc)
867{- | Parses a type class instance declaration
871 DocComment_t? 'instance' InstanceName? ConstraintList? Name SimpleExpr* InstanceBlock?
876InstanceName ::= '[' Name ']';
879instance_ :: SyntaxInfo -> IdrisParser [PDecl]
880instance_ syn = do (doc, argDocs)
881 <- try (docstring syn <* reservedHL "instance")
883 en <- optional instanceName
884 cs <- constraintList syn
885 let cs' = [(c, ty) | (c, _, ty) <- cs]
887 args <- many (simpleExpr syn)
888 let sc = PApp fc (PRef cnfc [cnfc] cn) (map pexp args)
889 let t = bindList (PPi constraint) cs sc
890 ds <- option [] (instanceBlock syn)
891 return [PInstance doc argDocs syn fc cs' cn cnfc args t en ds]
892 <?> "instance declaration"
893 where instanceName :: IdrisParser Name
894 instanceName = do lchar '['; n_in <- fst <$> fnName; lchar ']'
895 let n = expandNS syn n_in
900-- | Parse a docstring
901docstring :: SyntaxInfo
902 -> IdrisParser (Docstring (Either Err PTerm),
903 [(Name,Docstring (Either Err PTerm))])
904docstring syn = do (doc, argDocs) <- option noDocs docComment
906 let doc' = annotCode (tryFullExpr syn ist) doc
907 argDocs' = [ (n, annotCode (tryFullExpr syn ist) d)
908 | (n, d) <- argDocs ]
909 return (doc', argDocs')
912{- | Parses a using declaration list
924 | UsingDecl ',' UsingDeclList'
935usingDeclList :: SyntaxInfo -> IdrisParser [Using]
937 = try (sepBy1 (usingDecl syn) (lchar ','))
938 <|> do ns <- sepBy1 (fst <$> name) (lchar ',')
940 t <- typeExpr (disallowImp syn)
941 return (map (\x -> UImplicit x t) ns)
942 <?> "using declaration list"
944{- |Parses a using declaration
953usingDecl :: SyntaxInfo -> IdrisParser Using
954usingDecl syn = try (do x <- fst <$> fnName
956 t <- typeExpr (disallowImp syn)
957 return (UImplicit x t))
958 <|> do c <- fst <$> fnName
959 xs <- some (fst <$> fnName)
960 return (UConstraint c xs)
961 <?> "using declaration"
963{- | Parse a clause with patterns
969pattern :: SyntaxInfo -> IdrisParser PDecl
970pattern syn = do fc <- getFC
972 return (PClauses fc [] (sMN 2 "_") [clause]) -- collect together later
975{- | Parse a constant applicative form declaration
978CAF ::= 'let' FnName '=' Expr Terminator;
981caf :: SyntaxInfo -> IdrisParser PDecl
982caf syn = do reservedHL "let"
983 n_in <- fst <$> fnName; let n = expandNS syn n_in
986 t <- indented $ expr syn
990 <?> "constant applicative form declaration"
992{- | Parse an argument expression
995ArgExpr ::= HSimpleExpr | {- In Pattern External (User-defined) Expression -};
998argExpr :: SyntaxInfo -> IdrisParser PTerm
999argExpr syn = let syn' = syn { inPattern = True } in
1000 try (hsimpleExpr syn') <|> simpleExternalExpr syn'
1001 <?> "argument expression"
1003{- | Parse a right hand side of a function
1007 | '?=' RHSName? Expr
1013RHSName ::= '{' FnName '}';
1016rhs :: SyntaxInfo -> Name -> IdrisParser PTerm
1017rhs syn n = do lchar '='; expr syn
1020 name <- option n' (do symbol "{"; n <- fst <$> fnName; symbol "}";
1023 return (addLet fc name r)
1025 <?> "function right hand side"
1026 where mkN :: Name -> Name
1027 mkN (UN x) = if (tnull x || not (isAlpha (thead x)))
1028 then sUN "infix_op_lemma_1"
1029 else sUN (str x++"_lemma_1")
1030 mkN (NS x n) = NS (mkN x) n
1033 addLet :: FC -> Name -> PTerm -> PTerm
1034 addLet fc nm (PLet fc' n nfc ty val r) = PLet fc' n nfc ty val (addLet fc nm r)
1035 addLet fc nm (PCase fc' t cs) = PCase fc' t (map addLetC cs)
1036 where addLetC (l, r) = (l, addLet fc nm r)
1037 addLet fc nm r = (PLet fc (sUN "value") NoFC Placeholder r (PMetavar NoFC nm))
1039{- |Parses a function clause
1042RHSOrWithBlock ::= RHS WhereOrTerminator
1043 | 'with' SimpleExpr OpenBlock FnDecl+ CloseBlock
1048Clause ::= WExpr+ RHSOrWithBlock
1049 | SimpleExpr '<==' FnName RHS WhereOrTerminator
1050 | ArgExpr Operator ArgExpr WExpr* RHSOrWithBlock {- Except "=" and "?=" operators to avoid ambiguity -}
1051 | FnName ConstraintArg* ImplicitOrArgExpr* WExpr* RHSOrWithBlock
1056ImplicitOrArgExpr ::= ImplicitArg | ArgExpr;
1060WhereOrTerminator ::= WhereBlock | Terminator;
1063clause :: SyntaxInfo -> IdrisParser PClause
1065 = do wargs <- try (do pushIndent; some (wExpr syn))
1068 n <- case lastParse ist of
1070 Nothing -> fail "Invalid clause"
1072 let ctxt = tt_ctxt ist
1073 let wsyn = syn { syn_namespace = [] }
1074 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
1079 return $ PClauseR fc wargs r wheres) <|> (do
1082 wval <- simpleExpr syn
1085 ds <- some $ fnDecl syn
1086 let withs = concat ds
1088 return $ PWithR fc wargs wval pn withs)
1089 <|> do ty <- try (do pushIndent
1090 ty <- simpleExpr syn
1094 n_in <- fst <$> fnName; let n = expandNS syn n_in
1097 let ctxt = tt_ctxt ist
1098 let wsyn = syn { syn_namespace = [] }
1099 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
1104 let capp = PLet fc (sMN 0 "match") NoFC
1107 (PRef fc [] (sMN 0 "match"))
1109 put (ist { lastParse = Just n })
1110 return $ PClause fc n capp [] r wheres
1111 <|> do (l, op, nfc) <- try (do
1114 (op, nfc) <- operatorFC
1115 when (op == "=" || op == "?=" ) $
1116 fail "infix clause definition with \"=\" and \"?=\" not supported "
1117 return (l, op, nfc))
1118 let n = expandNS syn (sUN op)
1121 wargs <- many (wExpr syn)
1123 let wsyn = syn { syn_namespace = [] }
1124 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
1130 let capp = PApp fc (PRef nfc [nfc] n) [pexp l, pexp r]
1131 put (ist { lastParse = Just n })
1132 return $ PClause fc n capp wargs rs wheres) <|> (do
1135 wval <- bracketed syn
1138 ds <- some $ fnDecl syn
1141 let capp = PApp fc (PRef fc [] n) [pexp l, pexp r]
1142 let withs = map (fillLHSD n capp wargs) $ concat ds
1143 put (ist { lastParse = Just n })
1144 return $ PWith fc n capp wargs wval pn withs)
1146 (n_in, nfc) <- fnName; let n = expandNS syn n_in
1147 cargs <- many (constraintArg syn)
1149 args <- many (try (implicitArg (syn { inPattern = True } ))
1150 <|> (fmap pexp (argExpr syn)))
1151 wargs <- many (wExpr syn)
1152 let capp = PApp fc (PRef nfc [nfc] n)
1156 let ctxt = tt_ctxt ist
1157 let wsyn = syn { syn_namespace = [] }
1158 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
1164 put (ist { lastParse = Just n })
1165 return $ PClause fc n capp wargs r wheres) <|> (do
1168 put (ist { lastParse = Just n })
1169 wval <- bracketed syn
1172 ds <- some $ fnDecl syn
1173 let withs = map (fillLHSD n capp wargs) $ concat ds
1176 return $ PWith fc n capp wargs wval pn withs)
1177 <?> "function clause"
1179 optProof = option Nothing (do reservedHL "proof"
1183 fillLHS :: Name -> PTerm -> [PTerm] -> PClause -> PClause
1184 fillLHS n capp owargs (PClauseR fc wargs v ws)
1185 = PClause fc n capp (owargs ++ wargs) v ws
1186 fillLHS n capp owargs (PWithR fc wargs v pn ws)
1187 = PWith fc n capp (owargs ++ wargs) v pn
1188 (map (fillLHSD n capp (owargs ++ wargs)) ws)
1191 fillLHSD :: Name -> PTerm -> [PTerm] -> PDecl -> PDecl
1192 fillLHSD n c a (PClauses fc o fn cs) = PClauses fc o fn (map (fillLHS n c a) cs)
1193 fillLHSD n c a x = x
1195{-| Parses with pattern
1201wExpr :: SyntaxInfo -> IdrisParser PTerm
1202wExpr syn = do lchar '|'
1203 expr' (syn { inPattern = True })
1206{- | Parses a where block
1209WhereBlock ::= 'where' OpenBlock Decl+ CloseBlock;
1212whereBlock :: Name -> SyntaxInfo -> IdrisParser ([PDecl], [(Name, Name)])
1214 = do reservedHL "where"
1215 ds <- indentedBlock1 (decl syn)
1216 let dns = concatMap (concatMap declared) ds
1217 return (concat ds, map (\x -> (x, decoration syn x)) dns)
1220{- |Parses a code generation target language name
1232codegen_ :: IdrisParser Codegen
1233codegen_ = do n <- fst <$> identifier
1234 return (Via (map toLower n))
1235 <|> do reserved "Bytecode"; return Bytecode
1236 <?> "code generation language"
1238{- |Parses a compiler directive
1242 | String ',' StringList
1247Directive ::= '%' Directive';
1251Directive' ::= 'lib' CodeGen String_t
1252 | 'link' CodeGen String_t
1253 | 'flag' CodeGen String_t
1254 | 'include' CodeGen String_t
1257 | 'access' Accessibility
1258 | 'default' Totality
1260 | 'dynamic' StringList
1261 | 'name' Name NameList
1262 | 'error_handlers' Name NameList
1263 | 'language' 'TypeProviders'
1264 | 'language' 'ErrorReflection'
1268directive :: SyntaxInfo -> IdrisParser [PDecl]
1269directive syn = do try (lchar '%' *> reserved "lib")
1271 lib <- fmap fst stringLiteral
1272 return [PDirective (DLib cgn lib)]
1273 <|> do try (lchar '%' *> reserved "link")
1274 cgn <- codegen_; obj <- fst <$> stringLiteral
1275 return [PDirective (DLink cgn obj)]
1276 <|> do try (lchar '%' *> reserved "flag")
1277 cgn <- codegen_; flag <- fst <$> stringLiteral
1278 return [PDirective (DFlag cgn flag)]
1279 <|> do try (lchar '%' *> reserved "include")
1281 hdr <- fst <$> stringLiteral
1282 return [PDirective (DInclude cgn hdr)]
1283 <|> do try (lchar '%' *> reserved "hide"); n <- fst <$> fnName
1284 return [PDirective (DHide n)]
1285 <|> do try (lchar '%' *> reserved "freeze"); n <- fst <$> iName []
1286 return [PDirective (DFreeze n)]
1287 <|> do try (lchar '%' *> reserved "access"); acc <- accessibility
1288 return [PDirective (DAccess acc)]
1289 <|> do try (lchar '%' *> reserved "default"); tot <- totality
1291 put (i { default_total = tot } )
1292 return [PDirective (DDefault tot)]
1293 <|> do try (lchar '%' *> reserved "logging")
1294 i <- fst <$> natural
1295 return [PDirective (DLogging i)]
1296 <|> do try (lchar '%' *> reserved "dynamic")
1297 libs <- sepBy1 (fmap fst stringLiteral) (lchar ',')
1298 return [PDirective (DDynamicLibs libs)]
1299 <|> do try (lchar '%' *> reserved "name")
1300 (ty, tyFC) <- fnName
1301 ns <- sepBy1 name (lchar ',')
1302 return [PDirective (DNameHint ty tyFC ns)]
1303 <|> do try (lchar '%' *> reserved "error_handlers")
1305 (arg, afc) <- fnName
1306 ns <- sepBy1 name (lchar ',')
1307 return [PDirective (DErrorHandlers fn nfc arg afc ns) ]
1308 <|> do try (lchar '%' *> reserved "language"); ext <- pLangExt;
1309 return [PDirective (DLanguage ext)]
1311 try (lchar '%' *> reserved "used")
1312 fn <- fst <$> fnName
1313 arg <- fst <$> iName []
1314 return [PDirective (DUsed fc fn arg)]
1317pLangExt :: IdrisParser LanguageExt
1318pLangExt = (reserved "TypeProviders" >> return TypeProviders)
1319 <|> (reserved "ErrorReflection" >> return ErrorReflection)
1321{- | Parses a totality
1324Totality ::= 'partial' | 'total'
1328totality :: IdrisParser Bool
1330 = do reservedHL "total"; return True
1331 <|> do reservedHL "partial"; return False
1333{- | Parses a type provider
1336Provider ::= DocComment_t? '%' 'provide' Provider_What? '(' FnName TypeSig ')' 'with' Expr;
1337ProviderWhat ::= 'proof' | 'term' | 'type' | 'postulate'
1340provider :: SyntaxInfo -> IdrisParser [PDecl]
1341provider syn = do doc <- try (do (doc, _) <- docstring syn
1344 fc2 <- reservedFC "provide"
1345 highlightP (spanFC fc1 fc2) AnnKeyword
1347 provideTerm doc <|> providePostulate doc
1349 where provideTerm doc =
1350 do lchar '('; (n, nfc) <- fnName; lchar ':'; t <- typeExpr syn; lchar ')'
1353 e <- expr syn <?> "provider expression"
1354 return [PProvider doc syn fc nfc (ProvTerm t e) n]
1355 providePostulate doc =
1356 do reservedHL "postulate"
1360 e <- expr syn <?> "provider expression"
1361 return [PProvider doc syn fc nfc (ProvPostulate e) n]
1363{- | Parses a transform
1366Transform ::= '%' 'transform' Expr '==>' Expr
1369transform :: SyntaxInfo -> IdrisParser [PDecl]
1370transform syn = do try (lchar '%' *> reserved "transform")
1371 -- leave it unchecked, until we work out what this should
1373-- safety <- option True (do reserved "unsafe"
1379 return [PTransform fc False l r]
1382{- | Parses a top-level reflected elaborator script
1385RunElabDecl ::= '%' 'runElab' Expr
1388runElabDecl :: SyntaxInfo -> IdrisParser PDecl
1390 do kwFC <- try (do fc <- getFC
1392 fc' <- reservedFC "runElab"
1393 return (spanFC fc fc'))
1394 script <- expr syn <?> "elaborator script"
1395 highlightP kwFC AnnKeyword
1396 return $ PRunElabDecl kwFC script
1397 <?> "top-level elaborator script"
1399{- * Loading and parsing -}
1400{- | Parses an expression from input -}
1401parseExpr :: IState -> String -> Result PTerm
1402parseExpr st = runparser (fullExpr defaultSyntax) st "(input)"
1404{- | Parses a constant form input -}
1405parseConst :: IState -> String -> Result Const
1406parseConst st = runparser (fmap fst constant) st "(input)"
1408{- | Parses a tactic from input -}
1409parseTactic :: IState -> String -> Result PTactic
1410parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
1412{- | Parses a do-step from input (used in the elab shell) -}
1413parseElabShellStep :: IState -> String -> Result (Either ElabShellCmd PDo)
1414parseElabShellStep ist = runparser (fmap Right (do_ defaultSyntax) <|> fmap Left elabShellCmd) ist "(input)"
1415 where elabShellCmd = char ':' >>
1416 (reserved "qed" >> pure EQED ) <|>
1417 (reserved "abandon" >> pure EAbandon ) <|>
1418 (reserved "undo" >> pure EUndo ) <|>
1419 (reserved "state" >> pure EProofState) <|>
1420 (reserved "term" >> pure EProofTerm ) <|>
1421 (expressionTactic ["e", "eval"] EEval ) <|>
1422 (expressionTactic ["t", "type"] ECheck) <|>
1423 (expressionTactic ["search"] ESearch ) <|>
1425 doc <- (Right . fst <$> constant) <|> (Left . fst <$> fnName)
1427 return (EDocStr doc))
1429 expressionTactic cmds tactic =
1430 do asum (map reserved cmds)
1431 t <- spaced (expr defaultSyntax)
1433 return $ tactic (desugar defaultSyntax i t)
1434 spaced parser = indentPropHolds gtProp *> parser
1436-- | Parse module header and imports
1437parseImports :: FilePath -> String -> Idris (Maybe (Docstring ()), [String], [ImportInfo], Maybe Delta)
1438parseImports fname input
1440 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
1441 Failure err -> fail (show err)
1442 Success (x, annots, i) ->
1444 fname' <- runIO $ Dir.makeAbsolute fname
1445 sendHighlighting $ addPath annots fname'
1447 where imports :: IdrisParser ((Maybe (Docstring ()), [String],
1450 [(FC, OutputAnnotation)], IState)
1451 imports = do whiteSpace
1452 (mdoc, mname, annots) <- moduleHeader
1455 isEof <- lookAheadMatches eof
1460 return ((mdoc, mname, ps, mrk'), annots, i)
1461 addPath :: [(FC, OutputAnnotation)] -> FilePath -> [(FC, OutputAnnotation)]
1463 addPath ((fc, AnnNamespace ns Nothing) : annots) path =
1464 (fc, AnnNamespace ns (Just path)) : addPath annots path
1465 addPath (annot:annots) path = annot : addPath annots path
1467-- | There should be a better way of doing this...
1468findFC :: Doc -> (FC, String)
1469findFC x = let s = show (plain x) in findFC' s
1470 where findFC' s = case span (/= ':') s of
1471 -- Horrid kludge to prevent crashes on Windows
1472 (prefix, ':':'\\':rest) ->
1473 case findFC' rest of
1474 (NoFC, msg) -> (NoFC, msg)
1475 (FileFC f, msg) -> (FileFC (prefix ++ ":\\" ++ f), msg)
1476 (FC f start end, msg) -> (FC (prefix ++ ":\\" ++ f) start end, msg)
1477 (failname, ':':rest) -> case span isDigit rest of
1478 (line, ':':rest') -> case span isDigit rest' of
1479 (col, ':':msg) -> let pos = (read line, read col) in
1480 (FC failname pos pos, msg)
1482-- | Check if the coloring matches the options and corrects if necessary
1483fixColour :: Bool -> ANSI.Doc -> ANSI.Doc
1484fixColour False doc = ANSI.plain doc
1485fixColour True doc = doc
1487-- | A program is a list of declarations, possibly with associated
1488-- documentation strings.
1489parseProg :: SyntaxInfo -> FilePath -> String -> Maybe Delta ->
1491parseProg syn fname input mrk
1493 case runparser mainProg i fname input of
1494 Failure doc -> do -- FIXME: Get error location from trifecta
1495 -- this can't be the solution!
1496 -- Issue #1575 on the issue tracker.
1497 -- https://github.com/idris-lang/Idris-dev/issues/1575
1498 let (fc, msg) = findFC doc
1500 case idris_outputmode i of
1501 RawOutput h -> iputStrLn (show $ fixColour (idris_colourRepl i) doc)
1502 IdeMode n h -> iWarn fc (P.text msg)
1503 putIState (i { errSpan = Just fc })
1505 Success (x, i) -> do putIState i
1506 reportParserWarnings
1508 where mainProg :: IdrisParser ([PDecl], IState)
1509 mainProg = case mrk of
1510 Nothing -> do i <- get; return ([], i)
1517{- | Load idris module and show error if something wrong happens -}
1518loadModule :: FilePath -> Idris (Maybe String)
1520 = idrisCatch (loadModule' f)
1521 (\e -> do setErrSpan (getErrSpan e)
1523 iWarn (getErrSpan e) $ pprintErr ist e
1526{- | Load idris module -}
1527loadModule' :: FilePath -> Idris (Maybe String)
1530 let file = takeWhile (/= ' ') f
1531 ibcsd <- valIBCSubDir i
1532 ids <- allImportDirs
1533 fp <- findImport ids ibcsd file
1534 if file `elem` imported i
1535 then do logLvl 1 $ "Already read " ++ file
1537 else do putIState (i { imported = file : imported i })
1539 IDR fn -> loadSource False fn Nothing
1540 LIDR fn -> loadSource True fn Nothing
1542 idrisCatch (loadIBC True fn)
1543 (\c -> do logLvl 1 $ fn ++ " failed " ++ pshow i c
1545 IDR sfn -> loadSource False sfn Nothing
1546 LIDR sfn -> loadSource True sfn Nothing)
1549{- | Load idris code from file -}
1550loadFromIFile :: Bool -> IFileType -> Maybe Int -> Idris ()
1551loadFromIFile reexp i@(IBC fn src) maxline
1552 = do logLvl 1 $ "Skipping " ++ getSrcFile i
1553 idrisCatch (loadIBC reexp fn)
1554 (\err -> ierror $ LoadingFailed fn err)
1556 getSrcFile (IDR fn) = fn
1557 getSrcFile (LIDR fn) = fn
1558 getSrcFile (IBC f src) = getSrcFile src
1560loadFromIFile _ (IDR fn) maxline = loadSource' False fn maxline
1561loadFromIFile _ (LIDR fn) maxline = loadSource' True fn maxline
1563{-| Load idris source code and show error if something wrong happens -}
1564loadSource' :: Bool -> FilePath -> Maybe Int -> Idris ()
1565loadSource' lidr r maxline
1566 = idrisCatch (loadSource lidr r maxline)
1567 (\e -> do setErrSpan (getErrSpan e)
1570 At f e' -> iWarn f (pprintErr ist e')
1571 _ -> iWarn (getErrSpan e) (pprintErr ist e))
1573{- | Load Idris source code-}
1574loadSource :: Bool -> FilePath -> Maybe Int -> Idris ()
1575loadSource lidr f toline
1576 = do logLvl 1 ("Reading " ++ f)
1578 let def_total = default_total i
1579 file_in <- runIO $ readSource f
1580 file <- if lidr then tclift $ unlit f file_in else return file_in
1581 (mdocs, mname, imports_in, pos) <- parseImports f file
1582 ai <- getAutoImports
1583 let imports = map (\n -> ImportInfo True n Nothing [] NoFC NoFC) ai ++ imports_in
1584 ids <- allImportDirs
1585 ibcsd <- valIBCSubDir i
1586 mapM_ (\(re, f, ns, nfc) ->
1587 do fp <- findImport ids ibcsd f
1589 LIDR fn -> ifail $ "No ibc for " ++ f
1590 IDR fn -> ifail $ "No ibc for " ++ f
1593 let srcFn = case src of
1597 srcFnAbs <- case srcFn of
1598 Just fn -> fmap Just (runIO $ Dir.makeAbsolute fn)
1599 Nothing -> return Nothing
1600 sendHighlighting [(nfc, AnnNamespace ns srcFnAbs)])
1601 [(re, fn, ns, nfc) | ImportInfo re fn _ ns _ nfc <- imports]
1602 reportParserWarnings
1603 sendParserHighlighting
1605 -- process and check module aliases
1606 let modAliases = M.fromList
1607 [ (prep alias, prep realName)
1608 | ImportInfo { import_reexport = reexport
1609 , import_path = realName
1610 , import_rename = Just (alias, _)
1611 , import_location = fc } <- imports
1613 prep = map T.pack . reverse . Spl.splitOn [pathSeparator]
1614 aliasNames = [ (alias, fc)
1615 | ImportInfo { import_rename = Just (alias, _)
1616 , import_location = fc } <- imports
1618 histogram = groupBy ((==) `on` fst) . sortBy (comparing fst) $ aliasNames
1619 case map head . filter ((/= 1) . length) $ histogram of
1620 [] -> logLvl 3 $ "Module aliases: " ++ show (M.toList modAliases)
1621 (n,fc):_ -> throwError . At fc . Msg $ "import alias not unique: " ++ show n
1624 putIState (i { default_access = Hidden, module_aliases = modAliases })
1625 clearIBC -- start a new .ibc file
1626 -- record package info in .ibc
1627 imps <- allImportDirs
1628 mapM_ addIBC (map IBCImportDir imps)
1629 mapM_ (addIBC . IBCImport)
1630 [ (reexport, realName)
1631 | ImportInfo { import_reexport = reexport
1632 , import_path = realName
1635 let syntax = defaultSyntax{ syn_namespace = reverse mname,
1638 -- Save the span from parsing the module header, because
1639 -- an empty program parse might obliterate it.
1640 let oldSpan = idris_parsedSpan ist
1641 ds' <- parseProg syntax f file pos
1643 case (ds', oldSpan) of
1645 -- If no program elements were parsed, we dind't
1646 -- get a loaded region in the IBC file. That
1647 -- means we need to add it back.
1649 putIState ist { idris_parsedSpan = oldSpan
1650 , ibc_write = IBCParsedRegion fc :
1654 sendParserHighlighting
1656 -- Parsing done, now process declarations
1658 let ds = namespaces mname ds'
1659 logLvl 3 (show $ showDecls verbosePPOption ds)
1661 logLvl 10 (show (toAlist (idris_implicits i)))
1662 logLvl 3 (show (idris_infixes i))
1663 -- Now add all the declarations to the context
1665 when v $ iputStrLn $ "Type checking " ++ f
1666 -- we totality check after every Mutual block, so if
1667 -- anything is a single definition, wrap it in a
1668 -- mutual block on its own
1669 elabDecls toplevel (map toMutual ds)
1671 -- simplify every definition do give the totality checker
1673 mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
1675 do ctxt <- getContext
1676 tclift $ simplifyCasedef n (getErasureInfo i) ctxt
1678 (map snd (idris_totcheck i))
1679 -- build size change graph from simplified definitions
1680 logLvl 1 "Totality checking"
1682 mapM_ buildSCG (idris_totcheck i)
1683 mapM_ checkDeclTotality (idris_totcheck i)
1685 -- Redo totality check for deferred names
1686 let deftots = idris_defertotcheck i
1687 logLvl 1 $ "Totality checking " ++ show deftots
1688 mapM_ (\x -> do tot <- getTotality x
1690 Total _ -> setTotality x Unchecked
1691 _ -> return ()) (map snd deftots)
1692 mapM_ buildSCG deftots
1693 mapM_ checkDeclTotality deftots
1695 logLvl 1 ("Finished " ++ f)
1696 ibcsd <- valIBCSubDir i
1697 logLvl 1 "Universe checking"
1699 let ibc = ibcPathNoFallback ibcsd f
1701 addHides (hide_list i)
1703 -- Save module documentation if applicable
1706 Nothing -> return ()
1707 Just docs -> addModDoc syntax mname docs
1710 -- Finally, write an ibc and highlights if checking was successful
1713 do idrisCatch (do writeIBC f ibc; clearIBC)
1714 (\c -> return ()) -- failure is harmless
1715 hl <- getDumpHighlighting
1717 idrisCatch (writeHighlights f)
1718 (const $ return ()) -- failure is harmless
1721 putIState (i { default_total = def_total,
1725 namespaces :: [String] -> [PDecl] -> [PDecl]
1726 namespaces [] ds = ds
1727 namespaces (x:xs) ds = [PNamespace x NoFC (namespaces xs ds)]
1729 toMutual :: PDecl -> PDecl
1730 toMutual m@(PMutual _ d) = m
1731 toMutual (PNamespace x fc ds) = PNamespace x fc (map toMutual ds)
1732 toMutual x = let r = PMutual (fileFC "single mutual") [x] in
1740 addModDoc :: SyntaxInfo -> [String] -> Docstring () -> Idris ()
1741 addModDoc syn mname docs =
1743 docs' <- elabDocTerms recinfo (parsedDocs ist)
1744 let modDocs' = addDef docName docs' (idris_moduledocs ist)
1745 putIState ist { idris_moduledocs = modDocs' }
1746 addIBC (IBCModDocs docName)
1748 docName = NS modDocName (map T.pack (reverse mname))
1749 parsedDocs ist = annotCode (tryFullExpr syn ist) docs
1751{- | Adds names to hide list -}
1752addHides :: [(Name, Maybe Accessibility)] -> Idris ()
1753addHides xs = do i <- getIState
1754 let defh = default_access i
1755 let (hs, as) = partition isNothing xs
1758 (map (\ (n, _) -> (n, defh)) hs ++
1759 map (\ (n, Just a) -> (n, a)) as)
1760 where isNothing (_, Nothing) = True
1763 doHide (n, a) = do setAccessibility n a
1764 addIBC (IBCAccess n a)
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