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)
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 at the next type declaration
195 -- (so we get all cases of a definition to preserve totality
196 -- results, in particular).
197 let continue = case maxline syn of
199 Just l -> if fst (fc_end fc) > l
200 then mut_nesting syn /= 0
202 -- What I'd really like to do here is explicitly save the
203 -- current state, then if reading ahead finds we've passed
204 -- the end of the definition, reset the state. But I've lost
205 -- patience with trying to find out how to do that from the
206 -- trifecta docs, so this does the job instead.
210 else try (do notEndBlock
212 <|> fail "End of readable input"
213 where declBody :: Bool -> IdrisParser [PDecl]
214 declBody b = declBody' b
221 <|> do d <- dsl syn; return [d]
225 <|> do import_; fail "imports must be at top of file"
227 declBody' :: Bool -> IdrisParser [PDecl]
228 declBody' cont = do d <- decl' syn
230 let d' = fmap (debindApp syn . (desugar syn i)) d
233 else fail "End of readable input"
235 -- Keep going while we're still parsing clauses
236 continue False (PClauses _ _ _ _) = True
239{- | Parses a top-level declaration with possible syntax sugar
251decl' :: SyntaxInfo -> IdrisParser PDecl
260externalDecl :: SyntaxInfo -> IdrisParser [PDecl]
261externalDecl syn = do i <- get
263 FC fn start _ <- getFC
264 decls <- declExtensions syn (syntaxRulesList $ syntax_rules i)
266 let outerFC = FC fn start end
267 return $ map (mapPDeclFC (fixFC outerFC)
271 -- | Fix non-highlighting FCs to prevent spurious error location reports
272 fixFC :: FC -> FC -> FC
273 fixFC outer inner | inner `fcIn` outer = inner
275 -- | Fix highlighting FCs by obliterating them, to avoid spurious highlights
276 fixFCH fn outer inner | inner `fcIn` outer = inner
277 | otherwise = FileFC fn
279declExtensions :: SyntaxInfo -> [Syntax] -> IdrisParser [PDecl]
280declExtensions syn rules = declExtension syn [] (filter isDeclRule rules)
281 <?> "user-defined declaration"
283 isDeclRule (DeclRule _ _) = True
286declExtension :: SyntaxInfo -> [Maybe (Name, SynMatch)] -> [Syntax]
287 -> IdrisParser [PDecl]
288declExtension syn ns rules =
289 choice $ flip map (groupBy (ruleGroup `on` syntaxSymbols) rules) $ \rs ->
290 case head rs of -- can never be []
291 DeclRule (symb:_) _ -> try $ do
293 declExtension syn (n : ns) [DeclRule ss t | (DeclRule (_:ss) t) <- rs]
294 -- If we have more than one Rule in this bucket, our grammar is
296 DeclRule [] dec -> let r = map (update (mapMaybe id ns)) dec in
300 update :: [(Name, SynMatch)] -> PDecl -> PDecl
301 update ns = updateNs ns . fmap (updateRefs ns) . fmap (updateSynMatch ns)
303 updateRefs ns = mapPT newref
305 newref (PRef fc fcs n) = PRef fc fcs (updateB ns n)
308 -- Below is a lot of tedious boilerplate which updates any top level
309 -- names in the declaration. It will only change names which are bound in
310 -- the declaration (including method names in classes and field names in
311 -- record declarations, not including pattern variables)
312 updateB :: [(Name, SynMatch)] -> Name -> Name
313 updateB ns (NS n mods) = NS (updateB ns n) mods
314 updateB ns n = case lookup n ns of
315 Just (SynBind tfc t) -> t
318 updateNs :: [(Name, SynMatch)] -> PDecl -> PDecl
319 updateNs ns (PTy doc argdoc s fc o n fc' t)
320 = PTy doc argdoc s fc o (updateB ns n) fc' t
321 updateNs ns (PClauses fc o n cs)
322 = PClauses fc o (updateB ns n) (map (updateClause ns) cs)
323 updateNs ns (PCAF fc n t) = PCAF fc (updateB ns n) t
324 updateNs ns (PData ds cds s fc o dat)
325 = PData ds cds s fc o (updateData ns dat)
326 updateNs ns (PParams fc ps ds) = PParams fc ps (map (updateNs ns) ds)
327 updateNs ns (PNamespace s fc ds) = PNamespace s fc (map (updateNs ns) ds)
328 updateNs ns (PRecord doc syn fc o n fc' ps pdocs fields cname cdoc s)
329 = PRecord doc syn fc o (updateB ns n) fc' ps pdocs
330 (map (updateField ns) fields)
331 (updateRecCon ns cname)
334 updateNs ns (PClass docs s fc cs cn fc' ps pdocs pdets ds cname cdocs)
335 = PClass docs s fc cs (updateB ns cn) fc' ps pdocs pdets
336 (map (updateNs ns) ds)
337 (updateRecCon ns cname)
339 updateNs ns (PInstance docs pdocs s fc cs cn fc' ps ity ni ds)
340 = PInstance docs pdocs s fc cs (updateB ns cn) fc'
341 ps ity (fmap (updateB ns) ni)
342 (map (updateNs ns) ds)
343 updateNs ns (PMutual fc ds) = PMutual fc (map (updateNs ns) ds)
344 updateNs ns (PProvider docs s fc fc' pw n)
345 = PProvider docs s fc fc' pw (updateB ns n)
348 updateRecCon ns Nothing = Nothing
349 updateRecCon ns (Just (n, fc)) = Just (updateB ns n, fc)
351 updateField ns (m, p, t, doc) = (updateRecCon ns m, p, t, doc)
353 updateClause ns (PClause fc n t ts t' ds)
354 = PClause fc (updateB ns n) t ts t' (map (update ns) ds)
355 updateClause ns (PWith fc n t ts t' m ds)
356 = PWith fc (updateB ns n) t ts t' m (map (update ns) ds)
357 updateClause ns (PClauseR fc ts t ds)
358 = PClauseR fc ts t (map (update ns) ds)
359 updateClause ns (PWithR fc ts t m ds)
360 = PWithR fc ts t m (map (update ns) ds)
362 updateData ns (PDatadecl n fc t cs)
363 = PDatadecl (updateB ns n) fc t (map (updateCon ns) cs)
364 updateData ns (PLaterdecl n fc t)
365 = PLaterdecl (updateB ns n) fc t
367 updateCon ns (cd, ads, cn, fc, ty, fc', fns)
368 = (cd, ads, updateB ns cn, fc, ty, fc', fns)
370 ruleGroup [] [] = True
371 ruleGroup (s1:_) (s2:_) = s1 == s2
372 ruleGroup _ _ = False
374 extSymbol :: SSymbol -> IdrisParser (Maybe (Name, SynMatch))
375 extSymbol (Keyword n) = do fc <- reservedFC (show n)
376 highlightP fc AnnKeyword
378 extSymbol (Expr n) = do tm <- expr syn
379 return $ Just (n, SynTm tm)
380 extSymbol (SimpleExpr n) = do tm <- simpleExpr syn
381 return $ Just (n, SynTm tm)
382 extSymbol (Binding n) = do (b, fc) <- name
383 return $ Just (n, SynBind fc b)
384 extSymbol (Symbol s) = do fc <- symbolFC s
385 highlightP fc AnnKeyword
388{- | Parses a syntax extension declaration (and adds the rule to parser state)
391 SyntaxDecl ::= SyntaxRule;
394syntaxDecl :: SyntaxInfo -> IdrisParser PDecl
395syntaxDecl syn = do s <- syntaxRule syn
397 put (i `addSyntax` s)
399 return (PSyntax fc s)
401-- | Extend an 'IState' with a new syntax extension. See also 'addReplSyntax'.
402addSyntax :: IState -> Syntax -> IState
403addSyntax i s = i { syntax_rules = updateSyntaxRules [s] rs,
404 syntax_keywords = ks ++ ns,
405 ibc_write = IBCSyntax s : map IBCKeyword ks ++ ibc }
406 where rs = syntax_rules i
407 ns = syntax_keywords i
409 ks = map show (syntaxNames s)
411-- | Like 'addSyntax', but no effect on the IBC.
412addReplSyntax :: IState -> Syntax -> IState
413addReplSyntax i s = i { syntax_rules = updateSyntaxRules [s] rs,
414 syntax_keywords = ks ++ ns }
415 where rs = syntax_rules i
416 ns = syntax_keywords i
417 ks = map show (syntaxNames s)
419{- | Parses a syntax extension declaration
422SyntaxRuleOpts ::= 'term' | 'pattern';
427 SyntaxRuleOpts? 'syntax' SyntaxSym+ '=' TypeExpr Terminator;
431SyntaxSym ::= '[' Name_t ']'
438syntaxRule :: SyntaxInfo -> IdrisParser Syntax
442 sty <- option AnySyntax
443 (do reservedHL "term"; return TermSyntax
444 <|> do reservedHL "pattern"; return PatternSyntax)
447 syms <- some syntaxSym
448 when (all isExpr syms) $ unexpected "missing keywords in syntax rule"
449 let ns = mapMaybe getName syms
450 when (length ns /= length (nub ns))
451 $ unexpected "repeated variable in syntax rule"
453 tm <- typeExpr (allowImp syn) >>= uniquifyBinders [n | Binding n <- syms]
455 return (Rule (mkSimple syms) tm sty)
456 <|> do reservedHL "decl"; reservedHL "syntax"
457 syms <- some syntaxSym
458 when (all isExpr syms) $ unexpected "missing keywords in syntax rule"
459 let ns = mapMaybe getName syms
460 when (length ns /= length (nub ns))
461 $ unexpected "repeated variable in syntax rule"
464 dec <- some (decl syn)
466 return (DeclRule (mkSimple syms) (concat dec))
468 isExpr (Expr _) = True
470 getName (Expr n) = Just n
472 -- Can't parse two full expressions (i.e. expressions with application) in a row
473 -- so change them both to a simple expression
474 mkSimple (Expr e : es) = SimpleExpr e : mkSimple' es
475 mkSimple xs = mkSimple' xs
477 mkSimple' (Expr e : Expr e1 : es) = SimpleExpr e : SimpleExpr e1 :
479 -- Can't parse a full expression followed by operator like characters due to ambiguity
480 mkSimple' (Expr e : Symbol s : es)
481 | takeWhile (`elem` opChars) ts /= "" = SimpleExpr e : Symbol s : mkSimple' es
482 where ts = dropWhile isSpace . dropWhileEnd isSpace $ s
483 mkSimple' (e : es) = e : mkSimple' es
486 -- Prevent syntax variable capture by making all binders under syntax unique
487 -- (the ol' Common Lisp GENSYM approach)
488 uniquifyBinders :: [Name] -> PTerm -> IdrisParser PTerm
489 uniquifyBinders userNames = fixBind []
491 fixBind :: [(Name, Name)] -> PTerm -> IdrisParser PTerm
492 fixBind rens (PRef fc hls n) | Just n' <- lookup n rens =
493 return $ PRef fc hls n'
494 fixBind rens (PPatvar fc n) | Just n' <- lookup n rens =
495 return $ PPatvar fc n'
496 fixBind rens (PLam fc n nfc ty body)
497 | n `elem` userNames = liftM2 (PLam fc n nfc) (fixBind rens ty) (fixBind rens body)
499 do ty' <- fixBind rens ty
501 body' <- fixBind ((n,n'):rens) body
502 return $ PLam fc n' nfc ty' body'
503 fixBind rens (PPi plic n nfc argTy body)
504 | n `elem` userNames = liftM2 (PPi plic n nfc) (fixBind rens argTy) (fixBind rens body)
506 do ty' <- fixBind rens argTy
508 body' <- fixBind ((n,n'):rens) body
509 return $ (PPi plic n' nfc ty' body')
510 fixBind rens (PLet fc n nfc ty val body)
511 | n `elem` userNames = liftM3 (PLet fc n nfc)
516 do ty' <- fixBind rens ty
517 val' <- fixBind rens val
519 body' <- fixBind ((n,n'):rens) body
520 return $ PLet fc n' nfc ty' val' body'
521 fixBind rens (PMatchApp fc n) | Just n' <- lookup n rens =
522 return $ PMatchApp fc n'
523 fixBind rens x = descendM (fixBind rens) x
525 gensym :: Name -> IdrisParser Name
526 gensym n = do ist <- get
527 let idx = idris_name ist
528 put ist { idris_name = idx + 1 }
529 return $ sMN idx (show n)
531{- | Parses a syntax symbol (either binding variable, keyword or expression)
534SyntaxSym ::= '[' Name_t ']'
541syntaxSym :: IdrisParser SSymbol
542syntaxSym = try (do lchar '['; n <- fst <$> name; lchar ']'
544 <|> try (do lchar '{'; n <- fst <$> name; lchar '}'
546 <|> do n <- fst <$> iName []
548 <|> do sym <- fmap fst stringLiteral
552{- | Parses a function declaration with possible syntax sugar
555 FunDecl ::= FunDecl';
558fnDecl :: SyntaxInfo -> IdrisParser [PDecl]
559fnDecl syn = try (do notEndBlock
562 let d' = fmap (desugar syn i) d
563 return [d']) <?> "function declaration"
565{-| Parses a function declaration
569 DocComment_t? FnOpts* Accessibility? FnOpts* FnName TypeSig Terminator
576fnDecl' :: SyntaxInfo -> IdrisParser PDecl
577fnDecl' syn = checkFixity $
578 do (doc, argDocs, fc, opts', n, nfc, acc) <- try (do
580 (doc, argDocs) <- docstring syn
582 let initOpts = if default_total ist
585 opts <- fnOpts initOpts
586 acc <- optional accessibility
588 (n_in, nfc) <- fnName
589 let n = expandNS syn n_in
592 return (doc, argDocs, fc, opts', n, nfc, acc))
593 ty <- typeExpr (allowImp syn)
596 return (PTy doc argDocs syn fc opts' n nfc ty)
600 <?> "function declaration"
601 where checkFixity :: IdrisParser PDecl -> IdrisParser PDecl
602 checkFixity p = do decl <- p
604 Nothing -> return decl
605 Just n -> do fOk <- fixityOK n
607 "Missing fixity declaration for " ++ show n
609 getName (PTy _ _ _ _ _ n _ _) = Just n
611 fixityOK (NS n _) = fixityOK n
612 fixityOK (UN n) | all (flip elem opChars) (str n) =
613 do fixities <- fmap idris_infixes get
614 return . elem (str n) . map (\ (Fix _ op) -> op) $ fixities
615 | otherwise = return True
616 fixityOK _ = return True
618{-| Parses function options given initial options
627 | '%' 'error_handler'
629 | '%' 'specialise' '[' NameTimesList? ']'
634NameTimes ::= FnName Natural?;
640 | NameTimes ',' NameTimesList
644-- FIXME: Check compatability for function options (i.e. partal/total)
646-- Issue #1574 on the issue tracker.
647-- https://github.com/idris-lang/Idris-dev/issues/1574
648fnOpts :: [FnOpt] -> IdrisParser [FnOpt]
650 = do reservedHL "total"; fnOpts (TotalFn : opts)
651 <|> do reservedHL "partial"; fnOpts (PartialFn : (opts \\ [TotalFn]))
652 <|> do reservedHL "covering"; fnOpts (CoveringFn : (opts \\ [TotalFn]))
653 <|> do try (lchar '%' *> reserved "export"); c <- fmap fst stringLiteral;
654 fnOpts (CExport c : opts)
655 <|> do try (lchar '%' *> reserved "no_implicit");
656 fnOpts (NoImplicit : opts)
657 <|> do try (lchar '%' *> reserved "inline");
658 fnOpts (Inlinable : opts)
659 <|> do try (lchar '%' *> reserved "assert_total");
660 fnOpts (AssertTotal : opts)
661 <|> do try (lchar '%' *> reserved "error_handler");
662 fnOpts (ErrorHandler : opts)
663 <|> do try (lchar '%' *> reserved "error_reverse");
664 fnOpts (ErrorReverse : opts)
665 <|> do try (lchar '%' *> reserved "reflection");
666 fnOpts (Reflection : opts)
667 <|> do try (lchar '%' *> reserved "hint");
668 fnOpts (AutoHint : opts)
669 <|> do lchar '%'; reserved "specialise";
670 lchar '['; ns <- sepBy nameTimes (lchar ','); lchar ']'
671 fnOpts (Specialise ns : opts)
672 <|> do reservedHL "implicit"; fnOpts (Implicit : opts)
674 <?> "function modifier"
675 where nameTimes :: IdrisParser (Name, Maybe Int)
676 nameTimes = do n <- fst <$> fnName
677 t <- option Nothing (do reds <- fmap fst natural
678 return (Just (fromInteger reds)))
681{- | Parses a postulate
685 DocComment_t? 'postulate' FnOpts* Accesibility? FnOpts* FnName TypeSig Terminator
689postulate :: SyntaxInfo -> IdrisParser PDecl
690postulate syn = do (doc, ext)
691 <- try $ do (doc, _) <- docstring syn
696 let initOpts = if default_total ist
699 opts <- fnOpts initOpts
700 acc <- optional accessibility
702 (n_in, nfc) <- fnName
703 let n = expandNS syn n_in
705 ty <- typeExpr (allowImp syn)
709 return (PPostulate ext doc syn fc nfc opts' n ty)
711 where ppostDecl = do fc <- reservedHL "postulate"; return False
712 <|> do lchar '%'; reserved "extern"; return True
713{- | Parses a using declaration
717 'using' '(' UsingDeclList ')' OpenBlock Decl* CloseBlock
721using_ :: SyntaxInfo -> IdrisParser [PDecl]
723 do reservedHL "using"
724 lchar '('; ns <- usingDeclList syn; lchar ')'
726 let uvars = using syn
727 ds <- many (decl (syn { using = uvars ++ ns }))
730 <?> "using declaration"
732{- | Parses a parameters declaration
736 'parameters' '(' TypeDeclList ')' OpenBlock Decl* CloseBlock
740params :: SyntaxInfo -> IdrisParser [PDecl]
742 do reservedHL "parameters"; lchar '('; ns <- typeDeclList syn; lchar ')'
743 let ns' = [(n, ty) | (n, _, ty) <- ns]
745 let pvars = syn_params syn
746 ds <- many (decl syn { syn_params = pvars ++ ns' })
749 return [PParams fc ns' (concat ds)]
750 <?> "parameters declaration"
752{- | Parses a mutual declaration (for mutually recursive functions)
756 'mutual' OpenBlock Decl* CloseBlock
760mutual :: SyntaxInfo -> IdrisParser [PDecl]
762 do reservedHL "mutual"
764 let pvars = syn_params syn
765 ds <- many (decl (syn { mut_nesting = mut_nesting syn + 1 } ))
768 return [PMutual fc (concat ds)]
771{-| Parses a namespace declaration
775 'namespace' identifier OpenBlock Decl+ CloseBlock
779namespace :: SyntaxInfo -> IdrisParser [PDecl]
781 do reservedHL "namespace"
782 (n, nfc) <- identifier
784 ds <- some (decl syn { syn_namespace = n : syn_namespace syn })
786 return [PNamespace n nfc (concat ds)]
787 <?> "namespace declaration"
789{- | Parses a methods block (for instances)
792 InstanceBlock ::= 'where' OpenBlock FnDecl* CloseBlock
795instanceBlock :: SyntaxInfo -> IdrisParser [PDecl]
796instanceBlock syn = do reservedHL "where"
798 ds <- many (fnDecl syn)
803{- | Parses a methods and instances block (for type classes)
814 'where' OpenBlock Constructor? MethodOrInstance* CloseBlock
818classBlock :: SyntaxInfo -> IdrisParser (Maybe (Name, FC), Docstring (Either Err PTerm), [PDecl])
819classBlock syn = do reservedHL "where"
821 (cn, cd) <- option (Nothing, emptyDocstring) $
822 try (do (doc, _) <- option noDocs docComment
824 return (Just n, doc))
826 let cd' = annotate syn ist cd
828 ds <- many (notEndBlock >> instance_ syn <|> fnDecl syn)
830 return (cn, cd', concat ds)
834 constructor :: IdrisParser (Name, FC)
835 constructor = reservedHL "constructor" *> fnName
837 annotate :: SyntaxInfo -> IState -> Docstring () -> Docstring (Either Err PTerm)
838 annotate syn ist = annotCode $ tryFullExpr syn ist
840{-| Parses a type class declaration
845 | '(' Name ':' Expr ')'
851 DocComment_t? Accessibility? 'class' ConstraintList? Name ClassArgument* ClassBlock?
855class_ :: SyntaxInfo -> IdrisParser [PDecl]
856class_ syn = do (doc, argDocs, acc)
857 <- try (do (doc, argDocs) <- docstring syn
858 acc <- optional accessibility
860 return (doc, argDocs, acc))
862 cons <- constraintList syn
863 let cons' = [(c, ty) | (c, _, ty) <- cons]
864 (n_in, nfc) <- fnName
865 let n = expandNS syn n_in
867 fds <- option [(cn, NoFC) | (cn, _, _) <- cs] fundeps
868 (cn, cd, ds) <- option (Nothing, fst noDocs, []) (classBlock syn)
869 accData acc n (concatMap declared ds)
870 return [PClass doc syn fc cons' n nfc cs argDocs fds ds cn cd]
871 <?> "type-class declaration"
873 fundeps :: IdrisParser [(Name, FC)]
874 fundeps = do lchar '|'; sepBy name (lchar ',')
876 carg :: IdrisParser (Name, FC, PTerm)
877 carg = do lchar '('; (i, ifc) <- name; lchar ':'; ty <- expr syn; lchar ')'
879 <|> do (i, ifc) <- name
881 return (i, ifc, PType fc)
883{- | Parses a type class instance declaration
887 DocComment_t? 'instance' InstanceName? ConstraintList? Name SimpleExpr* InstanceBlock?
892InstanceName ::= '[' Name ']';
895instance_ :: SyntaxInfo -> IdrisParser [PDecl]
896instance_ syn = do (doc, argDocs)
897 <- try (docstring syn <* reservedHL "instance")
899 en <- optional instanceName
900 cs <- constraintList syn
901 let cs' = [(c, ty) | (c, _, ty) <- cs]
903 args <- many (simpleExpr syn)
904 let sc = PApp fc (PRef cnfc [cnfc] cn) (map pexp args)
905 let t = bindList (PPi constraint) cs sc
906 ds <- option [] (instanceBlock syn)
907 return [PInstance doc argDocs syn fc cs' cn cnfc args t en ds]
908 <?> "instance declaration"
909 where instanceName :: IdrisParser Name
910 instanceName = do lchar '['; n_in <- fst <$> fnName; lchar ']'
911 let n = expandNS syn n_in
916-- | Parse a docstring
917docstring :: SyntaxInfo
918 -> IdrisParser (Docstring (Either Err PTerm),
919 [(Name,Docstring (Either Err PTerm))])
920docstring syn = do (doc, argDocs) <- option noDocs docComment
922 let doc' = annotCode (tryFullExpr syn ist) doc
923 argDocs' = [ (n, annotCode (tryFullExpr syn ist) d)
924 | (n, d) <- argDocs ]
925 return (doc', argDocs')
928{- | Parses a using declaration list
940 | UsingDecl ',' UsingDeclList'
951usingDeclList :: SyntaxInfo -> IdrisParser [Using]
953 = try (sepBy1 (usingDecl syn) (lchar ','))
954 <|> do ns <- sepBy1 (fst <$> name) (lchar ',')
956 t <- typeExpr (disallowImp syn)
957 return (map (\x -> UImplicit x t) ns)
958 <?> "using declaration list"
960{- |Parses a using declaration
969usingDecl :: SyntaxInfo -> IdrisParser Using
970usingDecl syn = try (do x <- fst <$> fnName
972 t <- typeExpr (disallowImp syn)
973 return (UImplicit x t))
974 <|> do c <- fst <$> fnName
975 xs <- some (fst <$> fnName)
976 return (UConstraint c xs)
977 <?> "using declaration"
979{- | Parse a clause with patterns
985pattern :: SyntaxInfo -> IdrisParser PDecl
986pattern syn = do fc <- getFC
988 return (PClauses fc [] (sMN 2 "_") [clause]) -- collect together later
991{- | Parse a constant applicative form declaration
994CAF ::= 'let' FnName '=' Expr Terminator;
997caf :: SyntaxInfo -> IdrisParser PDecl
998caf syn = do reservedHL "let"
999 n_in <- fst <$> fnName; let n = expandNS syn n_in
1002 t <- indented $ expr syn
1005 return (PCAF fc n t)
1006 <?> "constant applicative form declaration"
1008{- | Parse an argument expression
1011ArgExpr ::= HSimpleExpr | {- In Pattern External (User-defined) Expression -};
1014argExpr :: SyntaxInfo -> IdrisParser PTerm
1015argExpr syn = let syn' = syn { inPattern = True } in
1016 try (hsimpleExpr syn') <|> simpleExternalExpr syn'
1017 <?> "argument expression"
1019{- | Parse a right hand side of a function
1023 | '?=' RHSName? Expr
1029RHSName ::= '{' FnName '}';
1032rhs :: SyntaxInfo -> Name -> IdrisParser PTerm
1033rhs syn n = do lchar '='; expr syn
1036 name <- option n' (do symbol "{"; n <- fst <$> fnName; symbol "}";
1039 return (addLet fc name r)
1041 <?> "function right hand side"
1042 where mkN :: Name -> Name
1043 mkN (UN x) = if (tnull x || not (isAlpha (thead x)))
1044 then sUN "infix_op_lemma_1"
1045 else sUN (str x++"_lemma_1")
1046 mkN (NS x n) = NS (mkN x) n
1049 addLet :: FC -> Name -> PTerm -> PTerm
1050 addLet fc nm (PLet fc' n nfc ty val r) = PLet fc' n nfc ty val (addLet fc nm r)
1051 addLet fc nm (PCase fc' t cs) = PCase fc' t (map addLetC cs)
1052 where addLetC (l, r) = (l, addLet fc nm r)
1053 addLet fc nm r = (PLet fc (sUN "value") NoFC Placeholder r (PMetavar NoFC nm))
1055{- |Parses a function clause
1058RHSOrWithBlock ::= RHS WhereOrTerminator
1059 | 'with' SimpleExpr OpenBlock FnDecl+ CloseBlock
1064Clause ::= WExpr+ RHSOrWithBlock
1065 | SimpleExpr '<==' FnName RHS WhereOrTerminator
1066 | ArgExpr Operator ArgExpr WExpr* RHSOrWithBlock {- Except "=" and "?=" operators to avoid ambiguity -}
1067 | FnName ConstraintArg* ImplicitOrArgExpr* WExpr* RHSOrWithBlock
1072ImplicitOrArgExpr ::= ImplicitArg | ArgExpr;
1076WhereOrTerminator ::= WhereBlock | Terminator;
1079clause :: SyntaxInfo -> IdrisParser PClause
1081 = do wargs <- try (do pushIndent; some (wExpr syn))
1084 n <- case lastParse ist of
1086 Nothing -> fail "Invalid clause"
1088 let ctxt = tt_ctxt ist
1089 let wsyn = syn { syn_namespace = [] }
1090 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
1095 return $ PClauseR fc wargs r wheres) <|> (do
1098 wval <- simpleExpr syn
1101 ds <- some $ fnDecl syn
1102 let withs = concat ds
1104 return $ PWithR fc wargs wval pn withs)
1105 <|> do ty <- try (do pushIndent
1106 ty <- simpleExpr syn
1110 n_in <- fst <$> fnName; let n = expandNS syn n_in
1113 let ctxt = tt_ctxt ist
1114 let wsyn = syn { syn_namespace = [] }
1115 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
1120 let capp = PLet fc (sMN 0 "match") NoFC
1123 (PRef fc [] (sMN 0 "match"))
1125 put (ist { lastParse = Just n })
1126 return $ PClause fc n capp [] r wheres
1127 <|> do (l, op, nfc) <- try (do
1130 (op, nfc) <- operatorFC
1131 when (op == "=" || op == "?=" ) $
1132 fail "infix clause definition with \"=\" and \"?=\" not supported "
1133 return (l, op, nfc))
1134 let n = expandNS syn (sUN op)
1137 wargs <- many (wExpr syn)
1139 let wsyn = syn { syn_namespace = [] }
1140 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
1146 let capp = PApp fc (PRef nfc [nfc] n) [pexp l, pexp r]
1147 put (ist { lastParse = Just n })
1148 return $ PClause fc n capp wargs rs wheres) <|> (do
1151 wval <- bracketed syn
1154 ds <- some $ fnDecl syn
1157 let capp = PApp fc (PRef fc [] n) [pexp l, pexp r]
1158 let withs = map (fillLHSD n capp wargs) $ concat ds
1159 put (ist { lastParse = Just n })
1160 return $ PWith fc n capp wargs wval pn withs)
1162 (n_in, nfc) <- fnName; let n = expandNS syn n_in
1163 cargs <- many (constraintArg syn)
1165 args <- many (try (implicitArg (syn { inPattern = True } ))
1166 <|> (fmap pexp (argExpr syn)))
1167 wargs <- many (wExpr syn)
1168 let capp = PApp fc (PRef nfc [nfc] n)
1172 let ctxt = tt_ctxt ist
1173 let wsyn = syn { syn_namespace = [] }
1174 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
1180 put (ist { lastParse = Just n })
1181 return $ PClause fc n capp wargs r wheres) <|> (do
1184 put (ist { lastParse = Just n })
1185 wval <- bracketed syn
1188 ds <- some $ fnDecl syn
1189 let withs = map (fillLHSD n capp wargs) $ concat ds
1192 return $ PWith fc n capp wargs wval pn withs)
1193 <?> "function clause"
1195 optProof = option Nothing (do reservedHL "proof"
1199 fillLHS :: Name -> PTerm -> [PTerm] -> PClause -> PClause
1200 fillLHS n capp owargs (PClauseR fc wargs v ws)
1201 = PClause fc n capp (owargs ++ wargs) v ws
1202 fillLHS n capp owargs (PWithR fc wargs v pn ws)
1203 = PWith fc n capp (owargs ++ wargs) v pn
1204 (map (fillLHSD n capp (owargs ++ wargs)) ws)
1207 fillLHSD :: Name -> PTerm -> [PTerm] -> PDecl -> PDecl
1208 fillLHSD n c a (PClauses fc o fn cs) = PClauses fc o fn (map (fillLHS n c a) cs)
1209 fillLHSD n c a x = x
1211{-| Parses with pattern
1217wExpr :: SyntaxInfo -> IdrisParser PTerm
1218wExpr syn = do lchar '|'
1219 expr' (syn { inPattern = True })
1222{- | Parses a where block
1225WhereBlock ::= 'where' OpenBlock Decl+ CloseBlock;
1228whereBlock :: Name -> SyntaxInfo -> IdrisParser ([PDecl], [(Name, Name)])
1230 = do reservedHL "where"
1231 ds <- indentedBlock1 (decl syn)
1232 let dns = concatMap (concatMap declared) ds
1233 return (concat ds, map (\x -> (x, decoration syn x)) dns)
1236{- |Parses a code generation target language name
1248codegen_ :: IdrisParser Codegen
1249codegen_ = do n <- fst <$> identifier
1250 return (Via (map toLower n))
1251 <|> do reserved "Bytecode"; return Bytecode
1252 <?> "code generation language"
1254{- |Parses a compiler directive
1258 | String ',' StringList
1263Directive ::= '%' Directive';
1267Directive' ::= 'lib' CodeGen String_t
1268 | 'link' CodeGen String_t
1269 | 'flag' CodeGen String_t
1270 | 'include' CodeGen String_t
1273 | 'access' Accessibility
1274 | 'default' Totality
1276 | 'dynamic' StringList
1277 | 'name' Name NameList
1278 | 'error_handlers' Name NameList
1279 | 'language' 'TypeProviders'
1280 | 'language' 'ErrorReflection'
1284directive :: SyntaxInfo -> IdrisParser [PDecl]
1285directive syn = do try (lchar '%' *> reserved "lib")
1287 lib <- fmap fst stringLiteral
1288 return [PDirective (DLib cgn lib)]
1289 <|> do try (lchar '%' *> reserved "link")
1290 cgn <- codegen_; obj <- fst <$> stringLiteral
1291 return [PDirective (DLink cgn obj)]
1292 <|> do try (lchar '%' *> reserved "flag")
1293 cgn <- codegen_; flag <- fst <$> stringLiteral
1294 return [PDirective (DFlag cgn flag)]
1295 <|> do try (lchar '%' *> reserved "include")
1297 hdr <- fst <$> stringLiteral
1298 return [PDirective (DInclude cgn hdr)]
1299 <|> do try (lchar '%' *> reserved "hide"); n <- fst <$> fnName
1300 return [PDirective (DHide n)]
1301 <|> do try (lchar '%' *> reserved "freeze"); n <- fst <$> iName []
1302 return [PDirective (DFreeze n)]
1303 <|> do try (lchar '%' *> reserved "access"); acc <- accessibility
1304 return [PDirective (DAccess acc)]
1305 <|> do try (lchar '%' *> reserved "default"); tot <- totality
1307 put (i { default_total = tot } )
1308 return [PDirective (DDefault tot)]
1309 <|> do try (lchar '%' *> reserved "logging")
1310 i <- fst <$> natural
1311 return [PDirective (DLogging i)]
1312 <|> do try (lchar '%' *> reserved "dynamic")
1313 libs <- sepBy1 (fmap fst stringLiteral) (lchar ',')
1314 return [PDirective (DDynamicLibs libs)]
1315 <|> do try (lchar '%' *> reserved "name")
1316 (ty, tyFC) <- fnName
1317 ns <- sepBy1 name (lchar ',')
1318 return [PDirective (DNameHint ty tyFC ns)]
1319 <|> do try (lchar '%' *> reserved "error_handlers")
1321 (arg, afc) <- fnName
1322 ns <- sepBy1 name (lchar ',')
1323 return [PDirective (DErrorHandlers fn nfc arg afc ns) ]
1324 <|> do try (lchar '%' *> reserved "language"); ext <- pLangExt;
1325 return [PDirective (DLanguage ext)]
1326 <|> do try (lchar '%' *> reserved "deprecate")
1328 alt <- option "" (fst <$> stringLiteral)
1329 return [PDirective (DDeprecate n alt)]
1331 try (lchar '%' *> reserved "used")
1332 fn <- fst <$> fnName
1333 arg <- fst <$> iName []
1334 return [PDirective (DUsed fc fn arg)]
1337pLangExt :: IdrisParser LanguageExt
1338pLangExt = (reserved "TypeProviders" >> return TypeProviders)
1339 <|> (reserved "ErrorReflection" >> return ErrorReflection)
1341{- | Parses a totality
1344Totality ::= 'partial' | 'total'
1348totality :: IdrisParser Bool
1350 = do reservedHL "total"; return True
1351 <|> do reservedHL "partial"; return False
1353{- | Parses a type provider
1356Provider ::= DocComment_t? '%' 'provide' Provider_What? '(' FnName TypeSig ')' 'with' Expr;
1357ProviderWhat ::= 'proof' | 'term' | 'type' | 'postulate'
1360provider :: SyntaxInfo -> IdrisParser [PDecl]
1361provider syn = do doc <- try (do (doc, _) <- docstring syn
1364 fc2 <- reservedFC "provide"
1365 highlightP (spanFC fc1 fc2) AnnKeyword
1367 provideTerm doc <|> providePostulate doc
1369 where provideTerm doc =
1370 do lchar '('; (n, nfc) <- fnName; lchar ':'; t <- typeExpr syn; lchar ')'
1373 e <- expr syn <?> "provider expression"
1374 return [PProvider doc syn fc nfc (ProvTerm t e) n]
1375 providePostulate doc =
1376 do reservedHL "postulate"
1380 e <- expr syn <?> "provider expression"
1381 return [PProvider doc syn fc nfc (ProvPostulate e) n]
1383{- | Parses a transform
1386Transform ::= '%' 'transform' Expr '==>' Expr
1389transform :: SyntaxInfo -> IdrisParser [PDecl]
1390transform syn = do try (lchar '%' *> reserved "transform")
1391 -- leave it unchecked, until we work out what this should
1393-- safety <- option True (do reserved "unsafe"
1399 return [PTransform fc False l r]
1402{- | Parses a top-level reflected elaborator script
1405RunElabDecl ::= '%' 'runElab' Expr
1408runElabDecl :: SyntaxInfo -> IdrisParser PDecl
1410 do kwFC <- try (do fc <- getFC
1412 fc' <- reservedFC "runElab"
1413 return (spanFC fc fc'))
1414 script <- expr syn <?> "elaborator script"
1415 highlightP kwFC AnnKeyword
1416 return $ PRunElabDecl kwFC script (syn_namespace syn)
1417 <?> "top-level elaborator script"
1419{- * Loading and parsing -}
1420{- | Parses an expression from input -}
1421parseExpr :: IState -> String -> Result PTerm
1422parseExpr st = runparser (fullExpr defaultSyntax) st "(input)"
1424{- | Parses a constant form input -}
1425parseConst :: IState -> String -> Result Const
1426parseConst st = runparser (fmap fst constant) st "(input)"
1428{- | Parses a tactic from input -}
1429parseTactic :: IState -> String -> Result PTactic
1430parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
1432{- | Parses a do-step from input (used in the elab shell) -}
1433parseElabShellStep :: IState -> String -> Result (Either ElabShellCmd PDo)
1434parseElabShellStep ist = runparser (fmap Right (do_ defaultSyntax) <|> fmap Left elabShellCmd) ist "(input)"
1435 where elabShellCmd = char ':' >>
1436 (reserved "qed" >> pure EQED ) <|>
1437 (reserved "abandon" >> pure EAbandon ) <|>
1438 (reserved "undo" >> pure EUndo ) <|>
1439 (reserved "state" >> pure EProofState) <|>
1440 (reserved "term" >> pure EProofTerm ) <|>
1441 (expressionTactic ["e", "eval"] EEval ) <|>
1442 (expressionTactic ["t", "type"] ECheck) <|>
1443 (expressionTactic ["search"] ESearch ) <|>
1445 doc <- (Right . fst <$> constant) <|> (Left . fst <$> fnName)
1447 return (EDocStr doc))
1449 expressionTactic cmds tactic =
1450 do asum (map reserved cmds)
1451 t <- spaced (expr defaultSyntax)
1453 return $ tactic (desugar defaultSyntax i t)
1454 spaced parser = indentPropHolds gtProp *> parser
1456-- | Parse module header and imports
1457parseImports :: FilePath -> String -> Idris (Maybe (Docstring ()), [String], [ImportInfo], Maybe Delta)
1458parseImports fname input
1460 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
1461 Failure err -> fail (show err)
1462 Success (x, annots, i) ->
1464 fname' <- runIO $ Dir.makeAbsolute fname
1465 sendHighlighting $ addPath annots fname'
1467 where imports :: IdrisParser ((Maybe (Docstring ()), [String],
1470 [(FC, OutputAnnotation)], IState)
1471 imports = do whiteSpace
1472 (mdoc, mname, annots) <- moduleHeader
1475 isEof <- lookAheadMatches eof
1480 return ((mdoc, mname, ps, mrk'), annots, i)
1481 addPath :: [(FC, OutputAnnotation)] -> FilePath -> [(FC, OutputAnnotation)]
1483 addPath ((fc, AnnNamespace ns Nothing) : annots) path =
1484 (fc, AnnNamespace ns (Just path)) : addPath annots path
1485 addPath (annot:annots) path = annot : addPath annots path
1487-- | There should be a better way of doing this...
1488findFC :: Doc -> (FC, String)
1489findFC x = let s = show (plain x) in findFC' s
1490 where findFC' s = case span (/= ':') s of
1491 -- Horrid kludge to prevent crashes on Windows
1492 (prefix, ':':'\\':rest) ->
1493 case findFC' rest of
1494 (NoFC, msg) -> (NoFC, msg)
1495 (FileFC f, msg) -> (FileFC (prefix ++ ":\\" ++ f), msg)
1496 (FC f start end, msg) -> (FC (prefix ++ ":\\" ++ f) start end, msg)
1497 (failname, ':':rest) -> case span isDigit rest of
1498 (line, ':':rest') -> case span isDigit rest' of
1499 (col, ':':msg) -> let pos = (read line, read col) in
1500 (FC failname pos pos, msg)
1502-- | Check if the coloring matches the options and corrects if necessary
1503fixColour :: Bool -> ANSI.Doc -> ANSI.Doc
1504fixColour False doc = ANSI.plain doc
1505fixColour True doc = doc
1507-- | A program is a list of declarations, possibly with associated
1508-- documentation strings.
1509parseProg :: SyntaxInfo -> FilePath -> String -> Maybe Delta ->
1511parseProg syn fname input mrk
1513 case runparser mainProg i fname input of
1514 Failure doc -> do -- FIXME: Get error location from trifecta
1515 -- this can't be the solution!
1516 -- Issue #1575 on the issue tracker.
1517 -- https://github.com/idris-lang/Idris-dev/issues/1575
1518 let (fc, msg) = findFC doc
1520 case idris_outputmode i of
1521 RawOutput h -> iputStrLn (show $ fixColour (idris_colourRepl i) doc)
1522 IdeMode n h -> iWarn fc (P.text msg)
1523 putIState (i { errSpan = Just fc })
1525 Success (x, i) -> do putIState i
1526 reportParserWarnings
1528 where mainProg :: IdrisParser ([PDecl], IState)
1529 mainProg = case mrk of
1530 Nothing -> do i <- get; return ([], i)
1537{- | Load idris module and show error if something wrong happens -}
1538loadModule :: FilePath -> Idris (Maybe String)
1540 = idrisCatch (loadModule' f)
1541 (\e -> do setErrSpan (getErrSpan e)
1543 iWarn (getErrSpan e) $ pprintErr ist e
1546{- | Load idris module -}
1547loadModule' :: FilePath -> Idris (Maybe String)
1550 let file = takeWhile (/= ' ') f
1551 ibcsd <- valIBCSubDir i
1552 ids <- allImportDirs
1553 fp <- findImport ids ibcsd file
1554 if file `elem` imported i
1555 then do logLvl 1 $ "Already read " ++ file
1557 else do putIState (i { imported = file : imported i })
1559 IDR fn -> loadSource False fn Nothing
1560 LIDR fn -> loadSource True fn Nothing
1562 idrisCatch (loadIBC True fn)
1563 (\c -> do logLvl 1 $ fn ++ " failed " ++ pshow i c
1565 IDR sfn -> loadSource False sfn Nothing
1566 LIDR sfn -> loadSource True sfn Nothing)
1569{- | Load idris code from file -}
1570loadFromIFile :: Bool -> IFileType -> Maybe Int -> Idris ()
1571loadFromIFile reexp i@(IBC fn src) maxline
1572 = do logLvl 1 $ "Skipping " ++ getSrcFile i
1573 idrisCatch (loadIBC reexp fn)
1574 (\err -> ierror $ LoadingFailed fn err)
1576 getSrcFile (IDR fn) = fn
1577 getSrcFile (LIDR fn) = fn
1578 getSrcFile (IBC f src) = getSrcFile src
1580loadFromIFile _ (IDR fn) maxline = loadSource' False fn maxline
1581loadFromIFile _ (LIDR fn) maxline = loadSource' True fn maxline
1583{-| Load idris source code and show error if something wrong happens -}
1584loadSource' :: Bool -> FilePath -> Maybe Int -> Idris ()
1585loadSource' lidr r maxline
1586 = idrisCatch (loadSource lidr r maxline)
1587 (\e -> do setErrSpan (getErrSpan e)
1590 At f e' -> iWarn f (pprintErr ist e')
1591 _ -> iWarn (getErrSpan e) (pprintErr ist e))
1593{- | Load Idris source code-}
1594loadSource :: Bool -> FilePath -> Maybe Int -> Idris ()
1595loadSource lidr f toline
1596 = do logLvl 1 ("Reading " ++ f)
1598 let def_total = default_total i
1599 file_in <- runIO $ readSource f
1600 file <- if lidr then tclift $ unlit f file_in else return file_in
1601 (mdocs, mname, imports_in, pos) <- parseImports f file
1602 ai <- getAutoImports
1603 let imports = map (\n -> ImportInfo True n Nothing [] NoFC NoFC) ai ++ imports_in
1604 ids <- allImportDirs
1605 ibcsd <- valIBCSubDir i
1606 mapM_ (\(re, f, ns, nfc) ->
1607 do fp <- findImport ids ibcsd f
1609 LIDR fn -> ifail $ "No ibc for " ++ f
1610 IDR fn -> ifail $ "No ibc for " ++ f
1613 let srcFn = case src of
1617 srcFnAbs <- case srcFn of
1618 Just fn -> fmap Just (runIO $ Dir.makeAbsolute fn)
1619 Nothing -> return Nothing
1620 sendHighlighting [(nfc, AnnNamespace ns srcFnAbs)])
1621 [(re, fn, ns, nfc) | ImportInfo re fn _ ns _ nfc <- imports]
1622 reportParserWarnings
1623 sendParserHighlighting
1625 -- process and check module aliases
1626 let modAliases = M.fromList
1627 [ (prep alias, prep realName)
1628 | ImportInfo { import_reexport = reexport
1629 , import_path = realName
1630 , import_rename = Just (alias, _)
1631 , import_location = fc } <- imports
1633 prep = map T.pack . reverse . Spl.splitOn [pathSeparator]
1634 aliasNames = [ (alias, fc)
1635 | ImportInfo { import_rename = Just (alias, _)
1636 , import_location = fc } <- imports
1638 histogram = groupBy ((==) `on` fst) . sortBy (comparing fst) $ aliasNames
1639 case map head . filter ((/= 1) . length) $ histogram of
1640 [] -> logLvl 3 $ "Module aliases: " ++ show (M.toList modAliases)
1641 (n,fc):_ -> throwError . At fc . Msg $ "import alias not unique: " ++ show n
1644 putIState (i { default_access = Hidden, module_aliases = modAliases })
1645 clearIBC -- start a new .ibc file
1646 -- record package info in .ibc
1647 imps <- allImportDirs
1648 mapM_ addIBC (map IBCImportDir imps)
1649 mapM_ (addIBC . IBCImport)
1650 [ (reexport, realName)
1651 | ImportInfo { import_reexport = reexport
1652 , import_path = realName
1655 let syntax = defaultSyntax{ syn_namespace = reverse mname,
1658 -- Save the span from parsing the module header, because
1659 -- an empty program parse might obliterate it.
1660 let oldSpan = idris_parsedSpan ist
1661 ds' <- parseProg syntax f file pos
1663 case (ds', oldSpan) of
1665 -- If no program elements were parsed, we dind't
1666 -- get a loaded region in the IBC file. That
1667 -- means we need to add it back.
1669 putIState ist { idris_parsedSpan = oldSpan
1670 , ibc_write = IBCParsedRegion fc :
1674 sendParserHighlighting
1676 -- Parsing done, now process declarations
1678 let ds = namespaces mname ds'
1679 logLvl 3 (show $ showDecls verbosePPOption ds)
1681 logLvl 10 (show (toAlist (idris_implicits i)))
1682 logLvl 3 (show (idris_infixes i))
1683 -- Now add all the declarations to the context
1685 when v $ iputStrLn $ "Type checking " ++ f
1686 -- we totality check after every Mutual block, so if
1687 -- anything is a single definition, wrap it in a
1688 -- mutual block on its own
1689 elabDecls toplevel (map toMutual ds)
1691 -- simplify every definition do give the totality checker
1693 mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
1695 do ctxt <- getContext
1696 tclift $ simplifyCasedef n (getErasureInfo i) ctxt
1698 (map snd (idris_totcheck i))
1699 -- build size change graph from simplified definitions
1700 logLvl 1 "Totality checking"
1702 mapM_ buildSCG (idris_totcheck i)
1703 mapM_ checkDeclTotality (idris_totcheck i)
1705 -- Redo totality check for deferred names
1706 let deftots = idris_defertotcheck i
1707 logLvl 1 $ "Totality checking " ++ show deftots
1708 mapM_ (\x -> do tot <- getTotality x
1710 Total _ -> setTotality x Unchecked
1711 _ -> return ()) (map snd deftots)
1712 mapM_ buildSCG deftots
1713 mapM_ checkDeclTotality deftots
1715 logLvl 1 ("Finished " ++ f)
1716 ibcsd <- valIBCSubDir i
1717 logLvl 1 "Universe checking"
1719 let ibc = ibcPathNoFallback ibcsd f
1721 addHides (hide_list i)
1723 -- Save module documentation if applicable
1726 Nothing -> return ()
1727 Just docs -> addModDoc syntax mname docs
1730 -- Finally, write an ibc and highlights if checking was successful
1733 do idrisCatch (do writeIBC f ibc; clearIBC)
1734 (\c -> return ()) -- failure is harmless
1735 hl <- getDumpHighlighting
1737 idrisCatch (writeHighlights f)
1738 (const $ return ()) -- failure is harmless
1741 putIState (i { default_total = def_total,
1745 namespaces :: [String] -> [PDecl] -> [PDecl]
1746 namespaces [] ds = ds
1747 namespaces (x:xs) ds = [PNamespace x NoFC (namespaces xs ds)]
1749 toMutual :: PDecl -> PDecl
1750 toMutual m@(PMutual _ d) = m
1751 toMutual (PNamespace x fc ds) = PNamespace x fc (map toMutual ds)
1752 toMutual x = let r = PMutual (fileFC "single mutual") [x] in
1760 addModDoc :: SyntaxInfo -> [String] -> Docstring () -> Idris ()
1761 addModDoc syn mname docs =
1763 docs' <- elabDocTerms recinfo (parsedDocs ist)
1764 let modDocs' = addDef docName docs' (idris_moduledocs ist)
1765 putIState ist { idris_moduledocs = modDocs' }
1766 addIBC (IBCModDocs docName)
1768 docName = NS modDocName (map T.pack (reverse mname))
1769 parsedDocs ist = annotCode (tryFullExpr syn ist) docs
1771{- | Adds names to hide list -}
1772addHides :: [(Name, Maybe Accessibility)] -> Idris ()
1773addHides xs = do i <- getIState
1774 let defh = default_access i
1775 let (hs, as) = partition isNothing xs
1778 (map (\ (n, _) -> (n, defh)) hs ++
1779 map (\ (n, Just a) -> (n, a)) as)
1780 where isNothing (_, Nothing) = True
1783 doHide (n, a) = do setAccessibility n a
1784 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