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)
26import Idris.ElabTerm hiding (namespace, params)
32import Idris.ParseHelpers
39import Util.DynamicLinker
44import Control.Applicative
46import Control.Monad.State.Strict
49import qualified Data.List.Split as Spl
53import qualified Data.HashSet as HS
54import qualified Data.Text as T
55import qualified Data.ByteString.UTF8 as UTF8
63 grammar shortcut notation:
64 ~CHARSEQ = complement of char sequence (i.e. any character except CHARSEQ)
65 RULE? = optional rule (i.e. RULE or nothing)
66 RULE* = repeated rule (i.e. RULE zero or more times)
67 RULE+ = repeated rule with at least one match (i.e. RULE one or more times)
68 RULE! = invalid rule (i.e. rule that is not valid in context, report meaningful error in case)
69 RULE{n} = rule repeated n times
74{- | Parses module definition
75 ModuleHeader ::= 'module' Identifier_t ';'?;
77moduleHeader :: IdrisParser [String]
78moduleHeader = try (do reserved "module"
80 option ';' (lchar ';')
81 return (moduleName i))
83 where moduleName x = case span (/='.') x of
85 (x, '.':y) -> x : moduleName y
87{- | Parses an import statement
88 Import ::= 'import' Identifier_t ';'?;
90import_ :: IdrisParser String
91import_ = do reserved "import"
93 option ';' (lchar ';')
95 <?> "import statement"
96 where toPath f = foldl1' (</>) (Spl.splitOn "." f)
98{- | Parses program source
101prog :: SyntaxInfo -> IdrisParser [PDecl]
102prog syn = do whiteSpace
103 decls <- many (decl syn)
106 let c = (concat decls)
109{- | Parses a top-level declaration
125decl :: SyntaxInfo -> IdrisParser [PDecl]
126decl syn = do notEndBlock
128 where declBody :: IdrisParser [PDecl]
136 <|> do d <- dsl syn; return [d]
140 <|> do import_; fail "imports must be at top of file"
142 declBody' :: IdrisParser [PDecl]
143 declBody' = do d <- decl' syn
145 let d' = fmap (debindApp syn . (desugar syn i)) d
148{- | Parses a top-level declaration with possible syntax sugar
157decl' :: SyntaxInfo -> IdrisParser PDecl
165{- | Parses a syntax extension declaration (and adds the rule to parser state)
166 SyntaxDecl ::= SyntaxRule;
168syntaxDecl :: SyntaxInfo -> IdrisParser PDecl
169syntaxDecl syn = do s <- syntaxRule syn
171 let rs = syntax_rules i
172 let ns = syntax_keywords i
173 let ibc = ibc_write i
174 let ks = map show (names s)
175 put (i { syntax_rules = s : rs,
176 syntax_keywords = ks ++ ns,
177 ibc_write = IBCSyntax s : map IBCKeyword ks ++ ibc })
179 return (PSyntax fc s)
180 where names (Rule syms _ _) = mapMaybe ename syms
181 ename (Keyword n) = Just n
184{- | Parses a syntax extension declaration
185SyntaxRuleOpts ::= 'term' | 'pattern';
188 SyntaxRuleOpts? 'syntax' SyntaxSym+ '=' TypeExpr Terminator;
190SyntaxSym ::= '[' Name_t ']'
196syntaxRule :: SyntaxInfo -> IdrisParser Syntax
200 sty <- option AnySyntax (do reserved "term"; return TermSyntax
201 <|> do reserved "pattern"; return PatternSyntax)
204 syms <- some syntaxSym
205 when (all isExpr syms) $ unexpected "missing keywords in syntax rule"
206 let ns = mapMaybe getName syms
207 when (length ns /= length (nub ns))
208 $ unexpected "repeated variable in syntax rule"
210 tm <- typeExpr (allowImp syn)
212 return (Rule (mkSimple syms) tm sty)
214 isExpr (Expr _) = True
216 getName (Expr n) = Just n
218 -- Can't parse two full expressions (i.e. expressions with application) in a row
219 -- so change them both to a simple expression
220 mkSimple (Expr e : es) = SimpleExpr e : mkSimple' es
221 mkSimple xs = mkSimple' xs
223 mkSimple' (Expr e : Expr e1 : es) = SimpleExpr e : SimpleExpr e1 :
225 mkSimple' (e : es) = e : mkSimple' es
229{- | Parses a syntax symbol (either binding variable, keyword or expression)
230SyntaxSym ::= '[' Name_t ']'
236syntaxSym :: IdrisParser SSymbol
237syntaxSym = try (do lchar '['; n <- name; lchar ']'
239 <|> try (do lchar '{'; n <- name; lchar '}'
243 <|> do sym <- stringLiteral
247{- | Parses a function declaration with possible syntax sugar
248 FunDecl ::= FunDecl';
250fnDecl :: SyntaxInfo -> IdrisParser [PDecl]
251fnDecl syn = try (do notEndBlock
254 let d' = fmap (desugar syn i) d
255 return [d']) <?> "function declaration"
257{- Parses a function declaration
259 DocComment_t? FnOpts* Accessibility? FnOpts* FnName TypeSig Terminator
265fnDecl' :: SyntaxInfo -> IdrisParser PDecl
266fnDecl' syn = checkFixity $
267 do (doc, fc, opts', n, acc) <- try (do
268 doc <- option "" (docComment '|')
271 let initOpts = if default_total ist
274 opts <- fnOpts initOpts
275 acc <- optional accessibility
278 let n = expandNS syn n_in
281 return (doc, fc, opts', n, acc))
282 ty <- typeExpr (allowImp syn)
285 return (PTy doc syn fc opts' n ty)
289 <?> "function declaration"
290 where checkFixity :: IdrisParser PDecl -> IdrisParser PDecl
291 checkFixity p = do decl <- p
293 Nothing -> return decl
294 Just n -> do fOk <- fixityOK n
296 "Missing fixity declaration for " ++ show n
298 getName (PTy _ _ _ _ n _) = Just n
300 fixityOK (NS n _) = fixityOK n
301 fixityOK (UN n) | all (flip elem opChars) n =
302 do fixities <- fmap idris_infixes get
303 return . elem n . map (\ (Fix _ op) -> op) $ fixities
304 | otherwise = return True
305 fixityOK _ = return True
307{- Parses function options given initial options
313 | '%' 'specialise' '[' NameTimesList? ']'
316NameTimes ::= FnName Natural?;
320 | NameTimes ',' NameTimesList
324-- FIXME: Check compatability for function options (i.e. partal/total)
325fnOpts :: [FnOpt] -> IdrisParser [FnOpt]
327 = do reserved "total"; fnOpts (TotalFn : opts)
328 <|> do reserved "partial"; fnOpts (PartialFn : (opts \\ [TotalFn]))
329 <|> do try (lchar '%' *> reserved "export"); c <- stringLiteral;
330 fnOpts (CExport c : opts)
331 <|> do try (lchar '%' *> reserved "assert_total");
332 fnOpts (AssertTotal : opts)
333 <|> do try (lchar '%' *> reserved "reflection");
334 fnOpts (Reflection : opts)
335 <|> do lchar '%'; reserved "specialise";
336 lchar '['; ns <- sepBy nameTimes (lchar ','); lchar ']'
337 fnOpts (Specialise ns : opts)
338 <|> do reserved "implicit"; fnOpts (Implicit : opts)
340 <?> "function modifier"
341 where nameTimes :: IdrisParser (Name, Maybe Int)
342 nameTimes = do n <- fnName
343 t <- option Nothing (do reds <- natural
344 return (Just (fromInteger reds)))
347{- | Parses a postulate
350 DocComment_t? 'postulate' FnOpts* Accesibility? FnOpts* FnName TypeSig Terminator
353postulate :: SyntaxInfo -> IdrisParser PDecl
354postulate syn = do doc <- try $ do doc <- option "" (docComment '|')
359 let initOpts = if default_total ist
362 opts <- fnOpts initOpts
363 acc <- optional accessibility
366 let n = expandNS syn n_in
368 ty <- typeExpr (allowImp syn)
372 return (PPostulate doc syn fc opts' n ty)
375{- | Parses a using declaration
378 'using' '(' UsingDeclList ')' OpenBlock Decl* CloseBlock
381using_ :: SyntaxInfo -> IdrisParser [PDecl]
383 do reserved "using"; lchar '('; ns <- usingDeclList syn; lchar ')'
385 let uvars = using syn
386 ds <- many (decl (syn { using = uvars ++ ns }))
389 <?> "using declaration"
391{- | Parses a parameters declaration
394 'parameters' '(' TypeDeclList ')' OpenBlock Decl* CloseBlock
397params :: SyntaxInfo -> IdrisParser [PDecl]
399 do reserved "parameters"; lchar '('; ns <- typeDeclList syn; lchar ')'
401 let pvars = syn_params syn
402 ds <- many (decl syn { syn_params = pvars ++ ns })
405 return [PParams fc ns (concat ds)]
406 <?> "parameters declaration"
408{- | Parses a mutual declaration (for mutually recursive functions)
411 'mutual' OpenBlock Decl* CloseBlock
414mutual :: SyntaxInfo -> IdrisParser [PDecl]
418 let pvars = syn_params syn
419 ds <- many (decl syn)
422 return [PMutual fc (concat ds)]
425{- | Parses a namespace declaration
428 'namespace' identifier OpenBlock Decl+ CloseBlock
431namespace :: SyntaxInfo -> IdrisParser [PDecl]
433 do reserved "namespace"; n <- identifier;
435 ds <- some (decl syn { syn_namespace = n : syn_namespace syn })
437 return [PNamespace n (concat ds)]
438 <?> "namespace declaration"
440{- |Parses a methods block (for instances)
441 InstanceBlock ::= 'where' OpenBlock FnDecl* CloseBlock
443instanceBlock :: SyntaxInfo -> IdrisParser [PDecl]
444instanceBlock syn = do reserved "where"
446 ds <- many (fnDecl syn)
451{- |Parses a methods and instances block (for type classes)
459 'where' OpenBlock MethodOrInstance* CloseBlock
462classBlock :: SyntaxInfo -> IdrisParser [PDecl]
463classBlock syn = do reserved "where"
465 ds <- many ((notEndBlock >> instance_ syn) <|> fnDecl syn)
470{- |Parses a type class declaration
474 | '(' Name ':' Expr ')'
478 DocComment_t? Accessibility? 'class' ConstraintList? Name ClassArgument* ClassBlock?
481class_ :: SyntaxInfo -> IdrisParser [PDecl]
482class_ syn = do (doc, acc) <- try (do
483 doc <- option "" (docComment '|')
484 acc <- optional accessibility
486 reserved "class"; fc <- getFC; cons <- constraintList syn; n_in <- name
487 let n = expandNS syn n_in
489 ds <- option [] (classBlock syn)
490 accData acc n (concatMap declared ds)
491 return [PClass doc syn fc cons n cs ds]
492 <?> "type-class declaration"
494 carg :: IdrisParser (Name, PTerm)
495 carg = do lchar '('; i <- name; lchar ':'; ty <- expr syn; lchar ')'
500{- |Parses a type class instance declaration
503 'instance' InstanceName? ConstraintList? Name SimpleExpr* InstanceBlock?
506 InstanceName ::= '[' Name ']';
508instance_ :: SyntaxInfo -> IdrisParser [PDecl]
509instance_ syn = do reserved "instance"; fc <- getFC
510 en <- optional instanceName
511 cs <- constraintList syn
513 args <- many (simpleExpr syn)
514 let sc = PApp fc (PRef fc cn) (map pexp args)
515 let t = bindList (PPi constraint) (map (\x -> (MN 0 "c", x)) cs) sc
516 ds <- option [] (instanceBlock syn)
517 return [PInstance syn fc cs cn args t en ds]
518 <?> "instance declaration"
519 where instanceName :: IdrisParser Name
520 instanceName = do lchar '['; n_in <- fnName; lchar ']'
521 let n = expandNS syn n_in
526{- | Parses a using declaration list
534 | UsingDecl ',' UsingDeclList'
542usingDeclList :: SyntaxInfo -> IdrisParser [Using]
544 = try (sepBy1 (usingDecl syn) (lchar ','))
545 <|> do ns <- sepBy1 name (lchar ',')
547 t <- typeExpr (disallowImp syn)
548 return (map (\x -> UImplicit x t) ns)
549 <?> "using declaration list"
551{- |Parses a using declaration
557usingDecl :: SyntaxInfo -> IdrisParser Using
558usingDecl syn = try (do x <- fnName
560 t <- typeExpr (disallowImp syn)
561 return (UImplicit x t))
564 return (UConstraint c xs)
565 <?> "using declaration"
567{- | Parse a clause with patterns
570pattern :: SyntaxInfo -> IdrisParser PDecl
571pattern syn = do fc <- getFC
573 return (PClauses fc [] (MN 2 "_") [clause]) -- collect together later
576{- | Parse a constant applicative form declaration
577 CAF ::= 'let' FnName '=' Expr Terminator;
579caf :: SyntaxInfo -> IdrisParser PDecl
580caf syn = do reserved "let"
581 n_in <- fnName; let n = expandNS syn n_in
587 <?> "constant applicative form declaration"
589{- | Parse an argument expression
590 ArgExpr ::= HSimpleExpr | {- In Pattern External (User-defined) Expression -};
592argExpr :: SyntaxInfo -> IdrisParser PTerm
593argExpr syn = let syn' = syn { inPattern = True } in
594 try (hsimpleExpr syn') <|> simpleExternalExpr syn'
595 <?> "argument expression"
597{- | Parse a right hand side of a function
603RHSName ::= '{' FnName '}';
605rhs :: SyntaxInfo -> Name -> IdrisParser PTerm
606rhs syn n = do lchar '='; expr syn
608 name <- option n' (do symbol "{"; n <- fnName; symbol "}";
611 return (addLet name r)
612 <|> do reserved "impossible"; return PImpossible
613 <?> "function right hand side"
614 where mkN :: Name -> Name
615 mkN (UN x) = UN (x++"_lemma_1")
616 mkN (NS x n) = NS (mkN x) n
619 addLet :: Name -> PTerm -> PTerm
620 addLet nm (PLet n ty val r) = PLet n ty val (addLet nm r)
621 addLet nm (PCase fc t cs) = PCase fc t (map addLetC cs)
622 where addLetC (l, r) = (l, addLet nm r)
623 addLet nm r = (PLet (UN "value") Placeholder r (PMetavar nm))
625{- |Parses a function clause
626RHSOrWithBlock ::= RHS WhereOrTerminator
627 | 'with' SimpleExpr OpenBlock FnDecl+ CloseBlock
629Clause ::= WExpr+ RHSOrWithBlock
630 | SimpleExpr '<==' FnName RHS WhereOrTerminator
631 | ArgExpr Operator ArgExpr WExpr* RHSOrWithBlock {- Except "=" and "?=" operators to avoid ambiguity -}
632 | FnName ConstraintArg* ImplicitOrArgExpr* WExpr* RHSOrWithBlock
634ImplicitOrArgExpr ::= ImplicitArg | ArgExpr;
635WhereOrTerminator ::= WhereBlock | Terminator;
637clause :: SyntaxInfo -> IdrisParser PClause
639 = do wargs <- try (do pushIndent; some (wExpr syn))
642 n <- case lastParse ist of
644 Nothing -> fail "Invalid clause"
646 let ctxt = tt_ctxt ist
647 let wsyn = syn { syn_namespace = [] }
648 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
653 return $ PClauseR fc wargs r wheres) <|> (do
656 wval <- simpleExpr syn
658 ds <- some $ fnDecl syn
659 let withs = concat ds
661 return $ PWithR fc wargs wval withs)
662 <|> do ty <- try (do pushIndent
667 n_in <- fnName; let n = expandNS syn n_in
670 let ctxt = tt_ctxt ist
671 let wsyn = syn { syn_namespace = [] }
672 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
677 let capp = PLet (MN 0 "match")
680 (PRef fc (MN 0 "match"))
682 put (ist { lastParse = Just n })
683 return $ PClause fc n capp [] r wheres
684 <|> do (l, op) <- try (do
688 when (op == "=" || op == "?=" ) $
689 fail "infix clause definition with \"=\" and \"?=\" not supported "
691 let n = expandNS syn (UN op)
694 wargs <- many (wExpr syn)
696 let wsyn = syn { syn_namespace = [] }
697 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
703 let capp = PApp fc (PRef fc n) [pexp l, pexp r]
704 put (ist { lastParse = Just n })
705 return $ PClause fc n capp wargs rs wheres) <|> (do
708 lchar '(' <?> "parenthesized expression"
709 wval <- bracketed syn
711 ds <- some $ fnDecl syn
714 let capp = PApp fc (PRef fc n) [pexp l, pexp r]
715 let withs = map (fillLHSD n capp wargs) $ concat ds
716 put (ist { lastParse = Just n })
717 return $ PWith fc n capp wargs wval withs)
719 n_in <- fnName; let n = expandNS syn n_in
720 cargs <- many (constraintArg syn)
722 args <- many (try (implicitArg (syn { inPattern = True } ))
723 <|> (fmap pexp (argExpr syn)))
724 wargs <- many (wExpr syn)
725 let capp = PApp fc (PRef fc n)
729 let ctxt = tt_ctxt ist
730 let wsyn = syn { syn_namespace = [] }
731 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
737 put (ist { lastParse = Just n })
738 return $ PClause fc n capp wargs r wheres) <|> (do
741 put (ist { lastParse = Just n })
742 lchar '(' <?> "parenthesized expression"
743 wval <- bracketed syn
745 ds <- some $ fnDecl syn
746 let withs = map (fillLHSD n capp wargs) $ concat ds
749 return $ PWith fc n capp wargs wval withs)
750 <?> "function clause"
752 fillLHS :: Name -> PTerm -> [PTerm] -> PClause -> PClause
753 fillLHS n capp owargs (PClauseR fc wargs v ws)
754 = PClause fc n capp (owargs ++ wargs) v ws
755 fillLHS n capp owargs (PWithR fc wargs v ws)
756 = PWith fc n capp (owargs ++ wargs) v
757 (map (fillLHSD n capp (owargs ++ wargs)) ws)
760 fillLHSD :: Name -> PTerm -> [PTerm] -> PDecl -> PDecl
761 fillLHSD n c a (PClauses fc o fn cs) = PClauses fc o fn (map (fillLHS n c a) cs)
764{- |Parses with pattern
767wExpr :: SyntaxInfo -> IdrisParser PTerm
768wExpr syn = do lchar '|'
772{- |Parses a where block
773WhereBlock ::= 'where' OpenBlock Decl+ CloseBlock;
775whereBlock :: Name -> SyntaxInfo -> IdrisParser ([PDecl], [(Name, Name)])
777 = do reserved "where"
778 ds <- indentedBlock1 (decl syn)
779 let dns = concatMap (concatMap declared) ds
780 return (concat ds, map (\x -> (x, decoration syn x)) dns)
783{- |Parses a code generation target language name
792codegen_ :: IdrisParser Codegen
793codegen_ = do reserved "C"; return ViaC
794 <|> do reserved "Java"; return ViaJava
795 <|> do reserved "JavaScript"; return ViaJavaScript
796 <|> do reserved "Node"; return ViaNode
797 <|> do reserved "LLVM"; return ViaLLVM
798 <|> do reserved "Bytecode"; return Bytecode
799 <?> "code generation language"
801{- |Parses a compiler directive
804 | String ',' StringList
807Directive ::= '%' Directive';
809Directive' ::= 'lib' CodeGen String_t
810 | 'link' CodeGen String_t
811 | 'flag' CodeGen String_t
812 | 'include' CodeGen String_t
815 | 'access' Accessibility
818 | 'dynamic' StringList
819 | 'name' Name NameList
820 | 'language' 'TypeProviders'
821 | 'language' 'ErrorReflection'
824directive :: SyntaxInfo -> IdrisParser [PDecl]
825directive syn = do try (lchar '%' *> reserved "lib"); cgn <- codegen_; lib <- stringLiteral;
826 return [PDirective (do addLib cgn lib
827 addIBC (IBCLib cgn lib))]
828 <|> do try (lchar '%' *> reserved "link"); cgn <- codegen_; obj <- stringLiteral;
829 return [PDirective (do dirs <- allImportDirs
830 o <- liftIO $ findInPath dirs obj
831 addIBC (IBCObj cgn obj) -- just name, search on loading ibc
832 addObjectFile cgn o)]
833 <|> do try (lchar '%' *> reserved "flag"); cgn <- codegen_;
834 flag <- stringLiteral
835 return [PDirective (do addIBC (IBCCGFlag cgn flag)
837 <|> do try (lchar '%' *> reserved "include"); cgn <- codegen_; hdr <- stringLiteral;
838 return [PDirective (do addHdr cgn hdr
839 addIBC (IBCHeader cgn hdr))]
840 <|> do try (lchar '%' *> reserved "hide"); n <- fnName
841 return [PDirective (do setAccessibility n Hidden
842 addIBC (IBCAccess n Hidden))]
843 <|> do try (lchar '%' *> reserved "freeze"); n <- iName []
844 return [PDirective (do setAccessibility n Frozen
845 addIBC (IBCAccess n Frozen))]
846 <|> do try (lchar '%' *> reserved "access"); acc <- accessibility
847 return [PDirective (do i <- get
848 put(i { default_access = acc }))]
849 <|> do try (lchar '%' *> reserved "default"); tot <- totality
851 put (i { default_total = tot } )
852 return [PDirective (do i <- get
853 put(i { default_total = tot }))]
854 <|> do try (lchar '%' *> reserved "logging"); i <- natural;
855 return [PDirective (setLogLevel (fromInteger i))]
856 <|> do try (lchar '%' *> reserved "dynamic"); libs <- sepBy1 stringLiteral (lchar ',');
857 return [PDirective (do added <- addDyLib libs
859 Left lib -> addIBC (IBCDyLib (lib_name lib))
862 <|> do try (lchar '%' *> reserved "name")
864 ns <- sepBy1 name (lchar ',')
866 (do mapM_ (addNameHint ty) ns
867 mapM_ (\n -> addIBC (IBCNameHint (ty, n))) ns)]
868 <|> do try (lchar '%' *> reserved "language"); ext <- pLangExt;
869 return [PDirective (addLangExt ext)]
872pLangExt :: IdrisParser LanguageExt
873pLangExt = (reserved "TypeProviders" >> return TypeProviders)
874 <|> (reserved "ErrorReflection" >> return ErrorReflection)
876{- | Parses a totality
877Totality ::= 'partial' | 'total'
879totality :: IdrisParser Bool
881 = do reserved "total"; return True
882 <|> do reserved "partial"; return False
884{- | Parses a type provider
885Provider ::= '%' 'provide' '(' FnName TypeSig ')' 'with' Expr;
887provider :: SyntaxInfo -> IdrisParser [PDecl]
888provider syn = do try (lchar '%' *> reserved "provide");
889 lchar '('; n <- fnName; lchar ':'; t <- typeExpr syn; lchar ')'
893 return [PProvider syn fc n t e]
896{- | Parses a transform
897Transform ::= '%' 'transform' Expr '==>' Expr
899transform :: SyntaxInfo -> IdrisParser [PDecl]
900transform syn = do try (lchar '%' *> reserved "transform")
901 -- leave it unchecked, until we work out what this should
903-- safety <- option True (do reserved "unsafe"
909 return [PTransform fc False l r]
913{- * Loading and parsing -}
914{- | Parses an expression from input -}
915parseExpr :: IState -> String -> Result PTerm
916parseExpr st = runparser (fullExpr defaultSyntax) st "(input)"
918{- | Parses a tactic from input -}
919parseTactic :: IState -> String -> Result PTactic
920parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
922-- | Parse module header and imports
923parseImports :: FilePath -> String -> Idris ([String], [String], Maybe Delta)
924parseImports fname input
926 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
927 Failure err -> fail (show err)
928 Success (x, i) -> do -- Discard state updates (there should be
931 where imports :: IdrisParser (([String], [String], Maybe Delta), IState)
932 imports = do whiteSpace
933 mname <- moduleHeader
936 isEof <- lookAheadMatches eof
941 return ((mname, ps, mrk'), i)
943-- | There should be a better way of doing this...
944findFC :: Doc -> (FC, String)
945findFC x = let s = show (plain x) in
946 case span (/= ':') s of
947 (failname, ':':rest) -> case span isDigit rest of
948 (line, ':':rest') -> (FC failname (read line) 0, drop 2 (dropWhile (/= ':') rest'))
950-- | A program is a list of declarations, possibly with associated
951-- documentation strings.
952parseProg :: SyntaxInfo -> FilePath -> String -> Maybe Delta ->
954parseProg syn fname input mrk
956 case runparser mainProg i fname input of
957 Failure doc -> do -- FIXME: Get error location from trifecta
958 -- this can't be the solution!
959 let (fc, msg) = findFC doc
961 case idris_outputmode i of
962 RawOutput -> ihputStrLn (idris_outh i) (show doc)
963 IdeSlave n -> ihWarn (idris_outh i) fc msg
964 putIState (i { errLine = Just (fc_line fc) }) -- Just errl })
966 Success (x, i) -> do putIState i
968 where mainProg :: IdrisParser ([PDecl], IState)
969 mainProg = case mrk of
970 Nothing -> do i <- get; return ([], i)
977{- | Load idris module and show error if something wrong happens -}
978loadModule :: Handle -> FilePath -> Idris String
980 = idrisCatch (loadModule' outh f)
981 (\e -> do setErrLine (getErrLine e)
987{- | Load idris module -}
988loadModule' :: Handle -> FilePath -> Idris String
991 let file = takeWhile (/= ' ') f
992 ibcsd <- valIBCSubDir i
994 fp <- liftIO $ findImport ids ibcsd file
995 if file `elem` imported i
996 then iLOG $ "Already read " ++ file
997 else do putIState (i { imported = file : imported i })
999 IDR fn -> loadSource outh False fn
1000 LIDR fn -> loadSource outh True fn
1002 idrisCatch (loadIBC fn)
1003 (\c -> do iLOG $ fn ++ " failed " ++ show c
1005 IDR sfn -> loadSource outh False sfn
1006 LIDR sfn -> loadSource outh True sfn)
1007 let (dir, fh) = splitFileName file
1008 return (dropExtension fh)
1011{- | Load idris code from file -}
1012loadFromIFile :: Handle -> IFileType -> Idris ()
1013loadFromIFile h i@(IBC fn src)
1014 = do iLOG $ "Skipping " ++ getSrcFile i
1015 idrisCatch (loadIBC fn)
1016 (\err -> ierror $ LoadingFailed fn err)
1018 getSrcFile (IDR fn) = fn
1019 getSrcFile (LIDR fn) = fn
1020 getSrcFile (IBC f src) = getSrcFile src
1022loadFromIFile h (IDR fn) = loadSource' h False fn
1023loadFromIFile h (LIDR fn) = loadSource' h True fn
1025{-| Load idris source code and show error if something wrong happens -}
1026loadSource' :: Handle -> Bool -> FilePath -> Idris ()
1028 = idrisCatch (loadSource h lidr r)
1029 (\e -> do setErrLine (getErrLine e)
1033{- | Load Idris source code-}
1034loadSource :: Handle -> Bool -> FilePath -> Idris ()
1036 = do iLOG ("Reading " ++ f)
1038 let def_total = default_total i
1039 file_in <- runIO $ readFile f
1040 file <- if lidr then tclift $ unlit f file_in else return file_in
1041 (mname, modules, pos) <- parseImports f file
1043 putIState (i { default_access = Hidden })
1044 clearIBC -- start a new .ibc file
1045 mapM_ (addIBC . IBCImport) modules
1046 ds' <- parseProg (defaultSyntax {syn_namespace = reverse mname })
1048 unless (null ds') $ do
1049 let ds = namespaces mname ds'
1050 logLvl 3 (showDecls True ds)
1052 logLvl 10 (show (toAlist (idris_implicits i)))
1053 logLvl 3 (show (idris_infixes i))
1054 -- Now add all the declarations to the context
1056 when v $ ihputStrLn h $ "Type checking " ++ f
1057 -- we totality check after every Mutual block, so if
1058 -- anything is a single definition, wrap it in a
1059 -- mutual block on its own
1060 elabDecls toplevel (map toMutual ds)
1062 -- simplify every definition do give the totality checker
1064 mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
1065 updateContext (simplifyCasedef n))
1066 (map snd (idris_totcheck i))
1067 -- build size change graph from simplified definitions
1068 iLOG "Totality checking"
1070 mapM_ buildSCG (idris_totcheck i)
1071 mapM_ checkDeclTotality (idris_totcheck i)
1073 -- Redo totality check for deferred names
1074 let deftots = idris_defertotcheck i
1075 iLOG $ "Totality checking " ++ show deftots
1076 mapM_ (\x -> do tot <- getTotality x
1078 Total _ -> setTotality x Unchecked
1079 _ -> return ()) (map snd deftots)
1080 mapM_ buildSCG deftots
1081 mapM_ checkDeclTotality deftots
1083 iLOG ("Finished " ++ f)
1084 ibcsd <- valIBCSubDir i
1085 iLOG "Universe checking"
1087 let ibc = ibcPathNoFallback ibcsd f
1089 addHides (hide_list i)
1092 idrisCatch (do writeIBC f ibc; clearIBC)
1093 (\c -> return ()) -- failure is harmless
1095 putIState (i { default_total = def_total,
1100 namespaces :: [String] -> [PDecl] -> [PDecl]
1101 namespaces [] ds = ds
1102 namespaces (x:xs) ds = [PNamespace x (namespaces xs ds)]
1104 toMutual :: PDecl -> PDecl
1105 toMutual m@(PMutual _ d) = m
1106 toMutual (PNamespace x ds) = PNamespace x (map toMutual ds)
1107 toMutual x = let r = PMutual (fileFC "single mutual") [x] in
1109 PClauses _ _ _ _ -> r
1110 PClass _ _ _ _ _ _ _ -> r
1111 PInstance _ _ _ _ _ _ _ _ -> r
1114{- | Adds names to hide list -}
1115addHides :: [(Name, Maybe Accessibility)] -> Idris ()
1116addHides xs = do i <- getIState
1117 let defh = default_access i
1118 let (hs, as) = partition isNothing xs
1121 (map (\ (n, _) -> (n, defh)) hs ++
1122 map (\ (n, Just a) -> (n, a)) as)
1123 where isNothing (_, Nothing) = True
1126 doHide (n, a) = do setAccessibility n a
1127 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