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 Text.Trifecta.Delta
12import Text.Trifecta hiding (span, stringLiteral, charLiteral, natural, symbol, char, string, whiteSpace)
13import Text.Parser.LookAhead
14import Text.Parser.Expression
15import qualified Text.Parser.Token as Tok
16import qualified Text.Parser.Char as Chr
17import qualified Text.Parser.Token.Highlight as Hi
19import Text.PrettyPrint.ANSI.Leijen (Doc, plain)
20import qualified Text.PrettyPrint.ANSI.Leijen as ANSI
22import Idris.AbsSyntax hiding (namespace, params)
25import Idris.Delaborate
27import Idris.Elab.Value
36import Idris.ParseHelpers
41import Idris.Docstrings hiding (Unchecked)
45import Util.DynamicLinker
46import qualified Util.Pretty as P
49import Idris.Core.Evaluate
51import Control.Applicative hiding (Const)
53import Control.Monad.State.Strict
57import qualified Data.List.Split as Spl
62import qualified Data.Map as M
63import qualified Data.HashSet as HS
64import qualified Data.Text as T
65import qualified Data.ByteString.UTF8 as UTF8
66import qualified Data.Set as S
75 grammar shortcut notation:
76 ~CHARSEQ = complement of char sequence (i.e. any character except CHARSEQ)
77 RULE? = optional rule (i.e. RULE or nothing)
78 RULE* = repeated rule (i.e. RULE zero or more times)
79 RULE+ = repeated rule with at least one match (i.e. RULE one or more times)
80 RULE! = invalid rule (i.e. rule that is not valid in context, report meaningful error in case)
81 RULE{n} = rule repeated n times
87{- | Parses module definition
90 ModuleHeader ::= 'module' Identifier_t ';'?;
93moduleHeader :: IdrisParser (Maybe (Docstring ()), [String])
94moduleHeader = try (do docs <- optional docComment
98 option ';' (lchar ';')
99 return (fmap fst docs, moduleName i))
100 <|> try (do lchar '%'; reserved "unqualified"
101 return (Nothing, []))
102 <|> return (Nothing, moduleName "Main")
103 where moduleName x = case span (/='.') x of
105 (x, '.':y) -> x : moduleName y
106 noArgs (Just (_, args)) | not (null args) = fail "Modules do not take arguments"
109{- | Parses an import statement
112 Import ::= 'import' Identifier_t ';'?;
115import_ :: IdrisParser (Bool, String, Maybe String, FC)
116import_ = do fc <- getFC
118 reexport <- option False (do reserved "public"; return True)
120 newName <- optional (reserved "as" *> identifier)
121 option ';' (lchar ';')
122 return (reexport, toPath id, toPath <$> newName, fc)
123 <?> "import statement"
124 where toPath = foldl1' (</>) . Spl.splitOn "."
126{- | Parses program source
132prog :: SyntaxInfo -> IdrisParser [PDecl]
133prog syn = do whiteSpace
134 decls <- many (decl syn)
135 let c = (concat decls)
137 Nothing -> do notOpenBraces; eof
141 put ist { idris_parsedSpan = Just (FC (fc_fname fc) (0,0) (fc_end fc)),
142 ibc_write = IBCParsedRegion fc : ibc_write ist }
145{-| Parses a top-level declaration
164decl :: SyntaxInfo -> IdrisParser [PDecl]
165decl syn = do fc <- getFC
166 -- if we're after maxline, stop here
167 let continue = case maxline syn of
169 Just l -> if fst (fc_end fc) > l
170 then mut_nesting syn /= 0
172 if continue then do notEndBlock
174 else fail "End of readable input"
175 where declBody :: IdrisParser [PDecl]
183 <|> do d <- dsl syn; return [d]
187 <|> do import_; fail "imports must be at top of file"
189 declBody' :: IdrisParser [PDecl]
190 declBody' = do d <- decl' syn
192 let d' = fmap (debindApp syn . (desugar syn i)) d
195{- | Parses a top-level declaration with possible syntax sugar
207decl' :: SyntaxInfo -> IdrisParser PDecl
215{- | Parses a syntax extension declaration (and adds the rule to parser state)
218 SyntaxDecl ::= SyntaxRule;
221syntaxDecl :: SyntaxInfo -> IdrisParser PDecl
222syntaxDecl syn = do s <- syntaxRule syn
224 put (i `addSyntax` s)
226 return (PSyntax fc s)
228-- | Extend an 'IState' with a new syntax extension. See also 'addReplSyntax'.
229addSyntax :: IState -> Syntax -> IState
230addSyntax i s = i { syntax_rules = updateSyntaxRules [s] rs,
231 syntax_keywords = ks ++ ns,
232 ibc_write = IBCSyntax s : map IBCKeyword ks ++ ibc }
233 where rs = syntax_rules i
234 ns = syntax_keywords i
236 ks = map show (syntaxNames s)
238-- | Like 'addSyntax', but no effect on the IBC.
239addReplSyntax :: IState -> Syntax -> IState
240addReplSyntax i s = i { syntax_rules = updateSyntaxRules [s] rs,
241 syntax_keywords = ks ++ ns }
242 where rs = syntax_rules i
243 ns = syntax_keywords i
244 ks = map show (syntaxNames s)
246{- | Parses a syntax extension declaration
249SyntaxRuleOpts ::= 'term' | 'pattern';
254 SyntaxRuleOpts? 'syntax' SyntaxSym+ '=' TypeExpr Terminator;
258SyntaxSym ::= '[' Name_t ']'
265syntaxRule :: SyntaxInfo -> IdrisParser Syntax
269 sty <- option AnySyntax (do reserved "term"; return TermSyntax
270 <|> do reserved "pattern"; return PatternSyntax)
273 syms <- some syntaxSym
274 when (all isExpr syms) $ unexpected "missing keywords in syntax rule"
275 let ns = mapMaybe getName syms
276 when (length ns /= length (nub ns))
277 $ unexpected "repeated variable in syntax rule"
279 tm <- typeExpr (allowImp syn)
281 return (Rule (mkSimple syms) tm sty)
283 isExpr (Expr _) = True
285 getName (Expr n) = Just n
287 -- Can't parse two full expressions (i.e. expressions with application) in a row
288 -- so change them both to a simple expression
289 mkSimple (Expr e : es) = SimpleExpr e : mkSimple' es
290 mkSimple xs = mkSimple' xs
292 mkSimple' (Expr e : Expr e1 : es) = SimpleExpr e : SimpleExpr e1 :
294 mkSimple' (e : es) = e : mkSimple' es
298{- | Parses a syntax symbol (either binding variable, keyword or expression)
301SyntaxSym ::= '[' Name_t ']'
308syntaxSym :: IdrisParser SSymbol
309syntaxSym = try (do lchar '['; n <- name; lchar ']'
311 <|> try (do lchar '{'; n <- name; lchar '}'
315 <|> do sym <- stringLiteral
319{- | Parses a function declaration with possible syntax sugar
322 FunDecl ::= FunDecl';
325fnDecl :: SyntaxInfo -> IdrisParser [PDecl]
326fnDecl syn = try (do notEndBlock
329 let d' = fmap (desugar syn i) d
330 return [d']) <?> "function declaration"
332{-| Parses a function declaration
336 DocComment_t? FnOpts* Accessibility? FnOpts* FnName TypeSig Terminator
343fnDecl' :: SyntaxInfo -> IdrisParser PDecl
344fnDecl' syn = checkFixity $
345 do (doc, argDocs, fc, opts', n, acc) <- try (do
347 (doc, argDocs) <- option noDocs docComment
349 let doc' = annotCode (tryFullExpr syn ist) doc
350 argDocs' = [ (n, annotCode (tryFullExpr syn ist) d)
351 | (n, d) <- argDocs ]
353 initOpts = if default_total ist
356 opts <- fnOpts initOpts
357 acc <- optional accessibility
360 let n = expandNS syn n_in
363 return (doc', argDocs', fc, opts', n, acc))
364 ty <- typeExpr (allowImp syn)
367 return (PTy doc argDocs syn fc opts' n ty)
371 <?> "function declaration"
372 where checkFixity :: IdrisParser PDecl -> IdrisParser PDecl
373 checkFixity p = do decl <- p
375 Nothing -> return decl
376 Just n -> do fOk <- fixityOK n
378 "Missing fixity declaration for " ++ show n
380 getName (PTy _ _ _ _ _ n _) = Just n
382 fixityOK (NS n _) = fixityOK n
383 fixityOK (UN n) | all (flip elem opChars) (str n) =
384 do fixities <- fmap idris_infixes get
385 return . elem (str n) . map (\ (Fix _ op) -> op) $ fixities
386 | otherwise = return True
387 fixityOK _ = return True
389{-| Parses function options given initial options
397 | '%' 'error_handler'
399 | '%' 'specialise' '[' NameTimesList? ']'
404NameTimes ::= FnName Natural?;
410 | NameTimes ',' NameTimesList
414-- FIXME: Check compatability for function options (i.e. partal/total)
416-- Issue #1574 on the issue tracker.
417-- https://github.com/idris-lang/Idris-dev/issues/1574
418fnOpts :: [FnOpt] -> IdrisParser [FnOpt]
420 = do reserved "total"; fnOpts (TotalFn : opts)
421 <|> do reserved "partial"; fnOpts (PartialFn : (opts \\ [TotalFn]))
422 <|> do reserved "covering"; fnOpts (CoveringFn : (opts \\ [TotalFn]))
423 <|> do try (lchar '%' *> reserved "export"); c <- stringLiteral;
424 fnOpts (CExport c : opts)
425 <|> do try (lchar '%' *> reserved "no_implicit");
426 fnOpts (NoImplicit : opts)
427 <|> do try (lchar '%' *> reserved "inline");
428 fnOpts (Inlinable : opts)
429 <|> do try (lchar '%' *> reserved "assert_total");
430 fnOpts (AssertTotal : opts)
431 <|> do try (lchar '%' *> reserved "error_handler");
432 fnOpts (ErrorHandler : opts)
433 <|> do try (lchar '%' *> reserved "error_reverse");
434 fnOpts (ErrorReverse : opts)
435 <|> do try (lchar '%' *> reserved "reflection");
436 fnOpts (Reflection : opts)
437 <|> do lchar '%'; reserved "specialise";
438 lchar '['; ns <- sepBy nameTimes (lchar ','); lchar ']'
439 fnOpts (Specialise ns : opts)
440 <|> do reserved "implicit"; fnOpts (Implicit : opts)
442 <?> "function modifier"
443 where nameTimes :: IdrisParser (Name, Maybe Int)
444 nameTimes = do n <- fnName
445 t <- option Nothing (do reds <- natural
446 return (Just (fromInteger reds)))
449{- | Parses a postulate
453 DocComment_t? 'postulate' FnOpts* Accesibility? FnOpts* FnName TypeSig Terminator
457postulate :: SyntaxInfo -> IdrisParser PDecl
458postulate syn = do doc <- try $ do (doc, _) <- option noDocs docComment
460 let doc' = annotCode (tryFullExpr syn ist) doc
465 let initOpts = if default_total ist
468 opts <- fnOpts initOpts
469 acc <- optional accessibility
472 let n = expandNS syn n_in
474 ty <- typeExpr (allowImp syn)
478 return (PPostulate doc syn fc opts' n ty)
481{- | Parses a using declaration
485 'using' '(' UsingDeclList ')' OpenBlock Decl* CloseBlock
489using_ :: SyntaxInfo -> IdrisParser [PDecl]
491 do reserved "using"; lchar '('; ns <- usingDeclList syn; lchar ')'
493 let uvars = using syn
494 ds <- many (decl (syn { using = uvars ++ ns }))
497 <?> "using declaration"
499{- | Parses a parameters declaration
503 'parameters' '(' TypeDeclList ')' OpenBlock Decl* CloseBlock
507params :: SyntaxInfo -> IdrisParser [PDecl]
509 do reserved "parameters"; lchar '('; ns <- typeDeclList syn; lchar ')'
511 let pvars = syn_params syn
512 ds <- many (decl syn { syn_params = pvars ++ ns })
515 return [PParams fc ns (concat ds)]
516 <?> "parameters declaration"
518{- | Parses a mutual declaration (for mutually recursive functions)
522 'mutual' OpenBlock Decl* CloseBlock
526mutual :: SyntaxInfo -> IdrisParser [PDecl]
530 let pvars = syn_params syn
531 ds <- many (decl (syn { mut_nesting = mut_nesting syn + 1 } ))
534 return [PMutual fc (concat ds)]
537{-| Parses a namespace declaration
541 'namespace' identifier OpenBlock Decl+ CloseBlock
545namespace :: SyntaxInfo -> IdrisParser [PDecl]
547 do reserved "namespace"; n <- identifier;
549 ds <- some (decl syn { syn_namespace = n : syn_namespace syn })
551 return [PNamespace n (concat ds)]
552 <?> "namespace declaration"
554{- | Parses a methods block (for instances)
557 InstanceBlock ::= 'where' OpenBlock FnDecl* CloseBlock
560instanceBlock :: SyntaxInfo -> IdrisParser [PDecl]
561instanceBlock syn = do reserved "where"
563 ds <- many (fnDecl syn)
568{- | Parses a methods and instances block (for type classes)
579 'where' OpenBlock MethodOrInstance* CloseBlock
583classBlock :: SyntaxInfo -> IdrisParser [PDecl]
584classBlock syn = do reserved "where"
586 ds <- many ((notEndBlock >> instance_ syn) <|> fnDecl syn)
591{-| Parses a type class declaration
596 | '(' Name ':' Expr ')'
602 DocComment_t? Accessibility? 'class' ConstraintList? Name ClassArgument* ClassBlock?
606class_ :: SyntaxInfo -> IdrisParser [PDecl]
607class_ syn = do (doc, argDocs, acc) <- try (do
608 (doc, argDocs) <- option noDocs docComment
610 let doc' = annotCode (tryFullExpr syn ist) doc
611 argDocs' = [ (n, annotCode (tryFullExpr syn ist) d)
612 | (n, d) <- argDocs ]
613 acc <- optional accessibility
614 return (doc', argDocs', acc))
615 reserved "class"; fc <- getFC; cons <- constraintList syn; n_in <- fnName
616 let n = expandNS syn n_in
618 ds <- option [] (classBlock syn)
619 accData acc n (concatMap declared ds)
620 return [PClass doc syn fc cons n cs argDocs ds]
621 <?> "type-class declaration"
623 carg :: IdrisParser (Name, PTerm)
624 carg = do lchar '('; i <- name; lchar ':'; ty <- expr syn; lchar ')'
629{- | Parses a type class instance declaration
633 'instance' InstanceName? ConstraintList? Name SimpleExpr* InstanceBlock?
638InstanceName ::= '[' Name ']';
641instance_ :: SyntaxInfo -> IdrisParser [PDecl]
642instance_ syn = do reserved "instance"; fc <- getFC
643 en <- optional instanceName
644 cs <- constraintList syn
646 args <- many (simpleExpr syn)
647 let sc = PApp fc (PRef fc cn) (map pexp args)
648 let t = bindList (PPi constraint) cs sc
649 ds <- option [] (instanceBlock syn)
650 return [PInstance syn fc cs cn args t en ds]
651 <?> "instance declaration"
652 where instanceName :: IdrisParser Name
653 instanceName = do lchar '['; n_in <- fnName; lchar ']'
654 let n = expandNS syn n_in
659{- | Parses a using declaration list
671 | UsingDecl ',' UsingDeclList'
682usingDeclList :: SyntaxInfo -> IdrisParser [Using]
684 = try (sepBy1 (usingDecl syn) (lchar ','))
685 <|> do ns <- sepBy1 name (lchar ',')
687 t <- typeExpr (disallowImp syn)
688 return (map (\x -> UImplicit x t) ns)
689 <?> "using declaration list"
691{- |Parses a using declaration
700usingDecl :: SyntaxInfo -> IdrisParser Using
701usingDecl syn = try (do x <- fnName
703 t <- typeExpr (disallowImp syn)
704 return (UImplicit x t))
707 return (UConstraint c xs)
708 <?> "using declaration"
710{- | Parse a clause with patterns
716pattern :: SyntaxInfo -> IdrisParser PDecl
717pattern syn = do fc <- getFC
719 return (PClauses fc [] (sMN 2 "_") [clause]) -- collect together later
722{- | Parse a constant applicative form declaration
725CAF ::= 'let' FnName '=' Expr Terminator;
728caf :: SyntaxInfo -> IdrisParser PDecl
729caf syn = do reserved "let"
730 n_in <- fnName; let n = expandNS syn n_in
736 <?> "constant applicative form declaration"
738{- | Parse an argument expression
741ArgExpr ::= HSimpleExpr | {- In Pattern External (User-defined) Expression -};
744argExpr :: SyntaxInfo -> IdrisParser PTerm
745argExpr syn = let syn' = syn { inPattern = True } in
746 try (hsimpleExpr syn') <|> simpleExternalExpr syn'
747 <?> "argument expression"
749{- | Parse a right hand side of a function
759RHSName ::= '{' FnName '}';
762rhs :: SyntaxInfo -> Name -> IdrisParser PTerm
763rhs syn n = do lchar '='; expr syn
766 name <- option n' (do symbol "{"; n <- fnName; symbol "}";
769 return (addLet fc name r)
770 <|> do reserved "impossible"; return PImpossible
771 <?> "function right hand side"
772 where mkN :: Name -> Name
773 mkN (UN x) = if (tnull x || not (isAlpha (thead x)))
774 then sUN "infix_op_lemma_1"
775 else sUN (str x++"_lemma_1")
776 mkN (NS x n) = NS (mkN x) n
779 addLet :: FC -> Name -> PTerm -> PTerm
780 addLet fc nm (PLet fc' n ty val r) = PLet fc' n ty val (addLet fc nm r)
781 addLet fc nm (PCase fc' t cs) = PCase fc' t (map addLetC cs)
782 where addLetC (l, r) = (l, addLet fc nm r)
783 addLet fc nm r = (PLet fc (sUN "value") Placeholder r (PMetavar nm))
785{- |Parses a function clause
788RHSOrWithBlock ::= RHS WhereOrTerminator
789 | 'with' SimpleExpr OpenBlock FnDecl+ CloseBlock
794Clause ::= WExpr+ RHSOrWithBlock
795 | SimpleExpr '<==' FnName RHS WhereOrTerminator
796 | ArgExpr Operator ArgExpr WExpr* RHSOrWithBlock {- Except "=" and "?=" operators to avoid ambiguity -}
797 | FnName ConstraintArg* ImplicitOrArgExpr* WExpr* RHSOrWithBlock
802ImplicitOrArgExpr ::= ImplicitArg | ArgExpr;
806WhereOrTerminator ::= WhereBlock | Terminator;
809clause :: SyntaxInfo -> IdrisParser PClause
811 = do wargs <- try (do pushIndent; some (wExpr syn))
814 n <- case lastParse ist of
816 Nothing -> fail "Invalid clause"
818 let ctxt = tt_ctxt ist
819 let wsyn = syn { syn_namespace = [] }
820 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
825 return $ PClauseR fc wargs r wheres) <|> (do
828 wval <- simpleExpr syn
830 ds <- some $ fnDecl syn
831 let withs = concat ds
833 return $ PWithR fc wargs wval withs)
834 <|> do ty <- try (do pushIndent
839 n_in <- fnName; let n = expandNS syn n_in
842 let ctxt = tt_ctxt ist
843 let wsyn = syn { syn_namespace = [] }
844 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
849 let capp = PLet fc (sMN 0 "match")
852 (PRef fc (sMN 0 "match"))
854 put (ist { lastParse = Just n })
855 return $ PClause fc n capp [] r wheres
856 <|> do (l, op) <- try (do
860 when (op == "=" || op == "?=" ) $
861 fail "infix clause definition with \"=\" and \"?=\" not supported "
863 let n = expandNS syn (sUN op)
866 wargs <- many (wExpr syn)
868 let wsyn = syn { syn_namespace = [] }
869 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
875 let capp = PApp fc (PRef fc n) [pexp l, pexp r]
876 put (ist { lastParse = Just n })
877 return $ PClause fc n capp wargs rs wheres) <|> (do
880 wval <- bracketed syn
882 ds <- some $ fnDecl syn
885 let capp = PApp fc (PRef fc n) [pexp l, pexp r]
886 let withs = map (fillLHSD n capp wargs) $ concat ds
887 put (ist { lastParse = Just n })
888 return $ PWith fc n capp wargs wval withs)
890 n_in <- fnName; let n = expandNS syn n_in
891 cargs <- many (constraintArg syn)
893 args <- many (try (implicitArg (syn { inPattern = True } ))
894 <|> (fmap pexp (argExpr syn)))
895 wargs <- many (wExpr syn)
896 let capp = PApp fc (PRef fc n)
900 let ctxt = tt_ctxt ist
901 let wsyn = syn { syn_namespace = [] }
902 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
908 put (ist { lastParse = Just n })
909 return $ PClause fc n capp wargs r wheres) <|> (do
912 put (ist { lastParse = Just n })
913 wval <- bracketed syn
915 ds <- some $ fnDecl syn
916 let withs = map (fillLHSD n capp wargs) $ concat ds
919 return $ PWith fc n capp wargs wval withs)
920 <?> "function clause"
922 fillLHS :: Name -> PTerm -> [PTerm] -> PClause -> PClause
923 fillLHS n capp owargs (PClauseR fc wargs v ws)
924 = PClause fc n capp (owargs ++ wargs) v ws
925 fillLHS n capp owargs (PWithR fc wargs v ws)
926 = PWith fc n capp (owargs ++ wargs) v
927 (map (fillLHSD n capp (owargs ++ wargs)) ws)
930 fillLHSD :: Name -> PTerm -> [PTerm] -> PDecl -> PDecl
931 fillLHSD n c a (PClauses fc o fn cs) = PClauses fc o fn (map (fillLHS n c a) cs)
934{-| Parses with pattern
940wExpr :: SyntaxInfo -> IdrisParser PTerm
941wExpr syn = do lchar '|'
942 expr' (syn { inPattern = True })
945{- | Parses a where block
948WhereBlock ::= 'where' OpenBlock Decl+ CloseBlock;
951whereBlock :: Name -> SyntaxInfo -> IdrisParser ([PDecl], [(Name, Name)])
953 = do reserved "where"
954 ds <- indentedBlock1 (decl syn)
955 let dns = concatMap (concatMap declared) ds
956 return (concat ds, map (\x -> (x, decoration syn x)) dns)
959{- |Parses a code generation target language name
971codegen_ :: IdrisParser Codegen
972codegen_ = do n <- identifier; return (Via (map toLower n))
973 <|> do reserved "Bytecode"; return Bytecode
974 <?> "code generation language"
976{- |Parses a compiler directive
980 | String ',' StringList
985Directive ::= '%' Directive';
989Directive' ::= 'lib' CodeGen String_t
990 | 'link' CodeGen String_t
991 | 'flag' CodeGen String_t
992 | 'include' CodeGen String_t
995 | 'access' Accessibility
998 | 'dynamic' StringList
999 | 'name' Name NameList
1000 | 'error_handlers' Name NameList
1001 | 'language' 'TypeProviders'
1002 | 'language' 'ErrorReflection'
1006directive :: SyntaxInfo -> IdrisParser [PDecl]
1007directive syn = do try (lchar '%' *> reserved "lib"); cgn <- codegen_; lib <- stringLiteral;
1008 return [PDirective (do addLib cgn lib
1009 addIBC (IBCLib cgn lib))]
1010 <|> do try (lchar '%' *> reserved "link"); cgn <- codegen_; obj <- stringLiteral;
1011 return [PDirective (do dirs <- allImportDirs
1012 o <- liftIO $ findInPath dirs obj
1013 addIBC (IBCObj cgn obj) -- just name, search on loading ibc
1014 addObjectFile cgn o)]
1015 <|> do try (lchar '%' *> reserved "flag"); cgn <- codegen_;
1016 flag <- stringLiteral
1017 return [PDirective (do addIBC (IBCCGFlag cgn flag)
1019 <|> do try (lchar '%' *> reserved "include"); cgn <- codegen_; hdr <- stringLiteral;
1020 return [PDirective (do addHdr cgn hdr
1021 addIBC (IBCHeader cgn hdr))]
1022 <|> do try (lchar '%' *> reserved "hide"); n <- fnName
1023 return [PDirective (do setAccessibility n Hidden
1024 addIBC (IBCAccess n Hidden))]
1025 <|> do try (lchar '%' *> reserved "freeze"); n <- iName []
1026 return [PDirective (do setAccessibility n Frozen
1027 addIBC (IBCAccess n Frozen))]
1028 <|> do try (lchar '%' *> reserved "access"); acc <- accessibility
1029 return [PDirective (do i <- get
1030 put(i { default_access = acc }))]
1031 <|> do try (lchar '%' *> reserved "default"); tot <- totality
1033 put (i { default_total = tot } )
1034 return [PDirective (do i <- get
1035 put(i { default_total = tot }))]
1036 <|> do try (lchar '%' *> reserved "logging"); i <- natural;
1037 return [PDirective (setLogLevel (fromInteger i))]
1038 <|> do try (lchar '%' *> reserved "dynamic"); libs <- sepBy1 stringLiteral (lchar ',');
1039 return [PDirective (do added <- addDyLib libs
1041 Left lib -> addIBC (IBCDyLib (lib_name lib))
1044 <|> do try (lchar '%' *> reserved "name")
1046 ns <- sepBy1 name (lchar ',')
1047 return [PDirective (do ty' <- disambiguate ty
1048 mapM_ (addNameHint ty') ns
1049 mapM_ (\n -> addIBC (IBCNameHint (ty', n))) ns)]
1050 <|> do try (lchar '%' *> reserved "error_handlers")
1053 ns <- sepBy1 name (lchar ',')
1054 return [PDirective (do fn' <- disambiguate fn
1055 ns' <- mapM disambiguate ns
1056 addFunctionErrorHandlers fn' arg ns'
1057 mapM_ (addIBC . IBCFunctionErrorHandler fn' arg) ns')]
1058 <|> do try (lchar '%' *> reserved "language"); ext <- pLangExt;
1059 return [PDirective (addLangExt ext)]
1061 try (lchar '%' *> reserved "used")
1064 return [PDirective (addUsedName fc fn arg)]
1067 where disambiguate :: Name -> Idris Name
1068 disambiguate n = do i <- getIState
1069 case lookupCtxtName n (idris_implicits i) of
1070 [(n', _)] -> return n'
1071 [] -> throwError (NoSuchVariable n)
1072 more -> throwError (CantResolveAlts (map fst more))
1074pLangExt :: IdrisParser LanguageExt
1075pLangExt = (reserved "TypeProviders" >> return TypeProviders)
1076 <|> (reserved "ErrorReflection" >> return ErrorReflection)
1078{- | Parses a totality
1081Totality ::= 'partial' | 'total'
1085totality :: IdrisParser Bool
1087 = do reserved "total"; return True
1088 <|> do reserved "partial"; return False
1090{- | Parses a type provider
1093Provider ::= '%' 'provide' Provider_What? '(' FnName TypeSig ')' 'with' Expr;
1094ProviderWhat ::= 'proof' | 'term' | 'type' | 'postulate'
1097provider :: SyntaxInfo -> IdrisParser [PDecl]
1098provider syn = do try (lchar '%' *> reserved "provide");
1099 provideTerm <|> providePostulate
1101 where provideTerm = do lchar '('; n <- fnName; lchar ':'; t <- typeExpr syn; lchar ')'
1104 e <- expr syn <?> "provider expression"
1105 return [PProvider syn fc (ProvTerm t e) n]
1106 providePostulate = do reserved "postulate"
1110 e <- expr syn <?> "provider expression"
1111 return [PProvider syn fc (ProvPostulate e) n]
1113{- | Parses a transform
1116Transform ::= '%' 'transform' Expr '==>' Expr
1119transform :: SyntaxInfo -> IdrisParser [PDecl]
1120transform syn = do try (lchar '%' *> reserved "transform")
1121 -- leave it unchecked, until we work out what this should
1123-- safety <- option True (do reserved "unsafe"
1129 return [PTransform fc False l r]
1133{- * Loading and parsing -}
1134{- | Parses an expression from input -}
1135parseExpr :: IState -> String -> Result PTerm
1136parseExpr st = runparser (fullExpr defaultSyntax) st "(input)"
1138{- | Parses a constant form input -}
1139parseConst :: IState -> String -> Result Const
1140parseConst st = runparser constant st "(input)"
1142{- | Parses a tactic from input -}
1143parseTactic :: IState -> String -> Result PTactic
1144parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
1146-- | Parse module header and imports
1147parseImports :: FilePath -> String -> Idris (Maybe (Docstring ()), [String], [(Bool, String, Maybe String, FC)], Maybe Delta)
1148parseImports fname input
1150 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
1151 Failure err -> fail (show err)
1152 Success (x, i) -> do putIState i
1154 where imports :: IdrisParser ((Maybe (Docstring ()), [String], [(Bool, String, Maybe String, FC)], Maybe Delta), IState)
1155 imports = do whiteSpace
1156 (mdoc, mname) <- moduleHeader
1159 isEof <- lookAheadMatches eof
1164 return ((mdoc, mname, ps, mrk'), i)
1166-- | There should be a better way of doing this...
1167findFC :: Doc -> (FC, String)
1168findFC x = let s = show (plain x) in
1169 case span (/= ':') s of
1170 (failname, ':':rest) -> case span isDigit rest of
1171 (line, ':':rest') -> case span isDigit rest' of
1172 (col, ':':msg) -> let pos = (read line, read col) in
1173 (FC failname pos pos, msg)
1175-- | Check if the coloring matches the options and corrects if necessary
1176fixColour :: Bool -> ANSI.Doc -> ANSI.Doc
1177fixColour False doc = ANSI.plain doc
1178fixColour True doc = doc
1180-- | A program is a list of declarations, possibly with associated
1181-- documentation strings.
1182parseProg :: SyntaxInfo -> FilePath -> String -> Maybe Delta ->
1184parseProg syn fname input mrk
1186 case runparser mainProg i fname input of
1187 Failure doc -> do -- FIXME: Get error location from trifecta
1188 -- this can't be the solution!
1189 -- Issue #1575 on the issue tracker.
1190 -- https://github.com/idris-lang/Idris-dev/issues/1575
1191 let (fc, msg) = findFC doc
1193 case idris_outputmode i of
1194 RawOutput h -> iputStrLn (show $ fixColour (idris_colourRepl i) doc)
1195 IdeSlave n h -> iWarn fc (P.text msg)
1196 putIState (i { errSpan = Just fc })
1198 Success (x, i) -> do putIState i
1199 reportParserWarnings
1201 where mainProg :: IdrisParser ([PDecl], IState)
1202 mainProg = case mrk of
1203 Nothing -> do i <- get; return ([], i)
1210{- | Load idris module and show error if something wrong happens -}
1211loadModule :: FilePath -> Idris (Maybe String)
1213 = idrisCatch (loadModule' f)
1214 (\e -> do setErrSpan (getErrSpan e)
1216 iWarn (getErrSpan e) $ pprintErr ist e
1219{- | Load idris module -}
1220loadModule' :: FilePath -> Idris (Maybe String)
1223 let file = takeWhile (/= ' ') f
1224 ibcsd <- valIBCSubDir i
1225 ids <- allImportDirs
1226 fp <- findImport ids ibcsd file
1227 if file `elem` imported i
1228 then do iLOG $ "Already read " ++ file
1230 else do putIState (i { imported = file : imported i })
1232 IDR fn -> loadSource False fn Nothing
1233 LIDR fn -> loadSource True fn Nothing
1235 idrisCatch (loadIBC True fn)
1236 (\c -> do iLOG $ fn ++ " failed " ++ pshow i c
1238 IDR sfn -> loadSource False sfn Nothing
1239 LIDR sfn -> loadSource True sfn Nothing)
1242{- | Load idris code from file -}
1243loadFromIFile :: Bool -> IFileType -> Maybe Int -> Idris ()
1244loadFromIFile reexp i@(IBC fn src) maxline
1245 = do iLOG $ "Skipping " ++ getSrcFile i
1246 idrisCatch (loadIBC reexp fn)
1247 (\err -> ierror $ LoadingFailed fn err)
1249 getSrcFile (IDR fn) = fn
1250 getSrcFile (LIDR fn) = fn
1251 getSrcFile (IBC f src) = getSrcFile src
1253loadFromIFile _ (IDR fn) maxline = loadSource' False fn maxline
1254loadFromIFile _ (LIDR fn) maxline = loadSource' True fn maxline
1256{-| Load idris source code and show error if something wrong happens -}
1257loadSource' :: Bool -> FilePath -> Maybe Int -> Idris ()
1258loadSource' lidr r maxline
1259 = idrisCatch (loadSource lidr r maxline)
1260 (\e -> do setErrSpan (getErrSpan e)
1263 At f e' -> iWarn f (pprintErr ist e')
1264 _ -> iWarn (getErrSpan e) (pprintErr ist e))
1266{- | Load Idris source code-}
1267loadSource :: Bool -> FilePath -> Maybe Int -> Idris ()
1268loadSource lidr f toline
1269 = do iLOG ("Reading " ++ f)
1271 let def_total = default_total i
1272 file_in <- runIO $ readFile f
1273 file <- if lidr then tclift $ unlit f file_in else return file_in
1274 (mdocs, mname, imports_in, pos) <- parseImports f file
1275 ai <- getAutoImports
1276 let imports = map (\n -> (True, n, Just n, emptyFC)) ai ++ imports_in
1277 ids <- allImportDirs
1278 ibcsd <- valIBCSubDir i
1280 do fp <- findImport ids ibcsd f
1282 LIDR fn -> ifail $ "No ibc for " ++ f
1283 IDR fn -> ifail $ "No ibc for " ++ f
1284 IBC fn src -> loadIBC True fn)
1285 [(re, fn) | (re, fn, _, _) <- imports]
1286 reportParserWarnings
1288 -- process and check module aliases
1289 let modAliases = M.fromList
1290 [(prep alias, prep realName) | (reexport, realName, Just alias, fc) <- imports]
1291 prep = map T.pack . reverse . Spl.splitOn "/"
1292 aliasNames = [(alias, fc) | (_, _, Just alias, fc) <- imports]
1293 histogram = groupBy ((==) `on` fst) . sortBy (comparing fst) $ aliasNames
1294 case map head . filter ((/= 1) . length) $ histogram of
1295 [] -> logLvl 3 $ "Module aliases: " ++ show (M.toList modAliases)
1296 (n,fc):_ -> throwError . At fc . Msg $ "import alias not unique: " ++ show n
1299 putIState (i { default_access = Hidden, module_aliases = modAliases })
1300 clearIBC -- start a new .ibc file
1301 -- record package info in .ibc
1302 imps <- allImportDirs
1303 mapM_ addIBC (map IBCImportDir imps)
1304 mapM_ (addIBC . IBCImport) [(reexport, realName) | (reexport, realName, alias, fc) <- imports]
1305 let syntax = defaultSyntax{ syn_namespace = reverse mname,
1307 ds' <- parseProg syntax f file pos
1309 -- Parsing done, now process declarations
1311 let ds = namespaces mname ds'
1312 logLvl 3 (show $ showDecls verbosePPOption ds)
1314 logLvl 10 (show (toAlist (idris_implicits i)))
1315 logLvl 3 (show (idris_infixes i))
1316 -- Now add all the declarations to the context
1318 when v $ iputStrLn $ "Type checking " ++ f
1319 -- we totality check after every Mutual block, so if
1320 -- anything is a single definition, wrap it in a
1321 -- mutual block on its own
1322 elabDecls toplevel (map toMutual ds)
1324 -- simplify every definition do give the totality checker
1326 mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
1327 updateContext (simplifyCasedef n $ getErasureInfo i))
1328 (map snd (idris_totcheck i))
1329 -- build size change graph from simplified definitions
1330 iLOG "Totality checking"
1332 mapM_ buildSCG (idris_totcheck i)
1333 mapM_ checkDeclTotality (idris_totcheck i)
1335 -- Redo totality check for deferred names
1336 let deftots = idris_defertotcheck i
1337 iLOG $ "Totality checking " ++ show deftots
1338 mapM_ (\x -> do tot <- getTotality x
1340 Total _ -> setTotality x Unchecked
1341 _ -> return ()) (map snd deftots)
1342 mapM_ buildSCG deftots
1343 mapM_ checkDeclTotality deftots
1345 iLOG ("Finished " ++ f)
1346 ibcsd <- valIBCSubDir i
1347 iLOG "Universe checking"
1349 let ibc = ibcPathNoFallback ibcsd f
1351 addHides (hide_list i)
1353 -- Save module documentation if applicable
1356 Nothing -> return ()
1357 Just docs -> addModDoc syntax mname docs
1360 -- Finally, write an ibc if checking was successful
1363 idrisCatch (do writeIBC f ibc; clearIBC)
1364 (\c -> return ()) -- failure is harmless
1366 putIState (i { default_total = def_total,
1370 namespaces :: [String] -> [PDecl] -> [PDecl]
1371 namespaces [] ds = ds
1372 namespaces (x:xs) ds = [PNamespace x (namespaces xs ds)]
1374 toMutual :: PDecl -> PDecl
1375 toMutual m@(PMutual _ d) = m
1376 toMutual (PNamespace x ds) = PNamespace x (map toMutual ds)
1377 toMutual x = let r = PMutual (fileFC "single mutual") [x] in
1379 PClauses _ _ _ _ -> r
1380 PClass _ _ _ _ _ _ _ _ -> r
1381 PInstance _ _ _ _ _ _ _ _ -> r
1384 addModDoc :: SyntaxInfo -> [String] -> Docstring () -> Idris ()
1385 addModDoc syn mname docs =
1387 docs' <- elabDocTerms recinfo (parsedDocs ist)
1388 let modDocs' = addDef docName docs' (idris_moduledocs ist)
1389 putIState ist { idris_moduledocs = modDocs' }
1390 addIBC (IBCModDocs docName)
1392 docName = NS modDocName (map T.pack (reverse mname))
1393 parsedDocs ist = annotCode (tryFullExpr syn ist) docs
1395{- | Adds names to hide list -}
1396addHides :: [(Name, Maybe Accessibility)] -> Idris ()
1397addHides xs = do i <- getIState
1398 let defh = default_access i
1399 let (hs, as) = partition isNothing xs
1402 (map (\ (n, _) -> (n, defh)) hs ++
1403 map (\ (n, Just a) -> (n, a)) as)
1404 where isNothing (_, Nothing) = True
1407 doHide (n, a) = do setAccessibility n a
1408 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