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 type classes and instances)
441 MethodsBlock ::= 'where' OpenBlock FnDecl* CloseBlock
443methodsBlock :: SyntaxInfo -> IdrisParser [PDecl]
444methodsBlock syn = do reserved "where"
446 ds <- many (fnDecl syn)
451{- |Parses a type class declaration
455 | '(' Name ':' Expr ')'
459 DocComment_t? Accessibility? 'class' ConstraintList? Name ClassArgument* MethodsBlock?
462class_ :: SyntaxInfo -> IdrisParser [PDecl]
463class_ syn = do (doc, acc) <- try (do
464 doc <- option "" (docComment '|')
465 acc <- optional accessibility
467 reserved "class"; fc <- getFC; cons <- constraintList syn; n_in <- name
468 let n = expandNS syn n_in
470 ds <- option [] (methodsBlock syn)
471 accData acc n (concatMap declared ds)
472 return [PClass doc syn fc cons n cs ds]
473 <?> "type-class declaration"
475 carg :: IdrisParser (Name, PTerm)
476 carg = do lchar '('; i <- name; lchar ':'; ty <- expr syn; lchar ')'
481{- |Parses a type class instance declaration
484 'instance' InstanceName? ConstraintList? Name SimpleExpr* MethodsBlock?
487 InstanceName ::= '[' Name ']';
489instance_ :: SyntaxInfo -> IdrisParser [PDecl]
490instance_ syn = do reserved "instance"; fc <- getFC
491 en <- optional instanceName
492 cs <- constraintList syn
494 args <- many (simpleExpr syn)
495 let sc = PApp fc (PRef fc cn) (map pexp args)
496 let t = bindList (PPi constraint) (map (\x -> (MN 0 "c", x)) cs) sc
497 ds <- option [] (methodsBlock syn)
498 return [PInstance syn fc cs cn args t en ds]
499 <?> "instance declaratioN"
500 where instanceName :: IdrisParser Name
501 instanceName = do lchar '['; n_in <- fnName; lchar ']'
502 let n = expandNS syn n_in
507{- | Parses a using declaration list
515 | UsingDecl ',' UsingDeclList'
523usingDeclList :: SyntaxInfo -> IdrisParser [Using]
525 = try (sepBy1 (usingDecl syn) (lchar ','))
526 <|> do ns <- sepBy1 name (lchar ',')
528 t <- typeExpr (disallowImp syn)
529 return (map (\x -> UImplicit x t) ns)
530 <?> "using declaration list"
532{- |Parses a using declaration
538usingDecl :: SyntaxInfo -> IdrisParser Using
539usingDecl syn = try (do x <- fnName
541 t <- typeExpr (disallowImp syn)
542 return (UImplicit x t))
545 return (UConstraint c xs)
546 <?> "using declaration"
548{- | Parse a clause with patterns
551pattern :: SyntaxInfo -> IdrisParser PDecl
552pattern syn = do fc <- getFC
554 return (PClauses fc [] (MN 2 "_") [clause]) -- collect together later
557{- | Parse a constant applicative form declaration
558 CAF ::= 'let' FnName '=' Expr Terminator;
560caf :: SyntaxInfo -> IdrisParser PDecl
561caf syn = do reserved "let"
562 n_in <- fnName; let n = expandNS syn n_in
568 <?> "constant applicative form declaration"
570{- | Parse an argument expression
571 ArgExpr ::= HSimpleExpr | {- In Pattern External (User-defined) Expression -};
573argExpr :: SyntaxInfo -> IdrisParser PTerm
574argExpr syn = let syn' = syn { inPattern = True } in
575 try (hsimpleExpr syn') <|> simpleExternalExpr syn'
576 <?> "argument expression"
578{- | Parse a right hand side of a function
584RHSName ::= '{' FnName '}';
586rhs :: SyntaxInfo -> Name -> IdrisParser PTerm
587rhs syn n = do lchar '='; expr syn
589 name <- option n' (do symbol "{"; n <- fnName; symbol "}";
592 return (addLet name r)
593 <|> do reserved "impossible"; return PImpossible
594 <?> "function right hand side"
595 where mkN :: Name -> Name
596 mkN (UN x) = UN (x++"_lemma_1")
597 mkN (NS x n) = NS (mkN x) n
600 addLet :: Name -> PTerm -> PTerm
601 addLet nm (PLet n ty val r) = PLet n ty val (addLet nm r)
602 addLet nm (PCase fc t cs) = PCase fc t (map addLetC cs)
603 where addLetC (l, r) = (l, addLet nm r)
604 addLet nm r = (PLet (UN "value") Placeholder r (PMetavar nm))
606{- |Parses a function clause
607RHSOrWithBlock ::= RHS WhereOrTerminator
608 | 'with' SimpleExpr OpenBlock FnDecl+ CloseBlock
610Clause ::= WExpr+ RHSOrWithBlock
611 | SimpleExpr '<==' FnName RHS WhereOrTerminator
612 | ArgExpr Operator ArgExpr WExpr* RHSOrWithBlock {- Except "=" and "?=" operators to avoid ambiguity -}
613 | FnName ConstraintArg* ImplicitOrArgExpr* WExpr* RHSOrWithBlock
615ImplicitOrArgExpr ::= ImplicitArg | ArgExpr;
616WhereOrTerminator ::= WhereBlock | Terminator;
618clause :: SyntaxInfo -> IdrisParser PClause
620 = do wargs <- try (do pushIndent; some (wExpr syn))
623 n <- case lastParse ist of
625 Nothing -> fail "Invalid clause"
627 let ctxt = tt_ctxt ist
628 let wsyn = syn { syn_namespace = [] }
629 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
634 return $ PClauseR fc wargs r wheres) <|> (do
637 wval <- simpleExpr syn
639 ds <- some $ fnDecl syn
640 let withs = concat ds
642 return $ PWithR fc wargs wval withs)
643 <|> do ty <- try (do pushIndent
648 n_in <- fnName; let n = expandNS syn n_in
651 let ctxt = tt_ctxt ist
652 let wsyn = syn { syn_namespace = [] }
653 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
658 let capp = PLet (MN 0 "match")
661 (PRef fc (MN 0 "match"))
663 put (ist { lastParse = Just n })
664 return $ PClause fc n capp [] r wheres
665 <|> do (l, op) <- try (do
669 when (op == "=" || op == "?=" ) $
670 fail "infix clause definition with \"=\" and \"?=\" not supported "
672 let n = expandNS syn (UN op)
675 wargs <- many (wExpr syn)
677 let wsyn = syn { syn_namespace = [] }
678 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
684 let capp = PApp fc (PRef fc n) [pexp l, pexp r]
685 put (ist { lastParse = Just n })
686 return $ PClause fc n capp wargs rs wheres) <|> (do
689 lchar '(' <?> "parenthesized expression"
690 wval <- bracketed syn
692 ds <- some $ fnDecl syn
695 let capp = PApp fc (PRef fc n) [pexp l, pexp r]
696 let withs = map (fillLHSD n capp wargs) $ concat ds
697 put (ist { lastParse = Just n })
698 return $ PWith fc n capp wargs wval withs)
700 n_in <- fnName; let n = expandNS syn n_in
701 cargs <- many (constraintArg syn)
703 args <- many (try (implicitArg (syn { inPattern = True } ))
704 <|> (fmap pexp (argExpr syn)))
705 wargs <- many (wExpr syn)
706 let capp = PApp fc (PRef fc n)
710 let ctxt = tt_ctxt ist
711 let wsyn = syn { syn_namespace = [] }
712 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
718 put (ist { lastParse = Just n })
719 return $ PClause fc n capp wargs r wheres) <|> (do
722 put (ist { lastParse = Just n })
723 lchar '(' <?> "parenthesized expression"
724 wval <- bracketed syn
726 ds <- some $ fnDecl syn
727 let withs = map (fillLHSD n capp wargs) $ concat ds
730 return $ PWith fc n capp wargs wval withs)
731 <?> "function clause"
733 fillLHS :: Name -> PTerm -> [PTerm] -> PClause -> PClause
734 fillLHS n capp owargs (PClauseR fc wargs v ws)
735 = PClause fc n capp (owargs ++ wargs) v ws
736 fillLHS n capp owargs (PWithR fc wargs v ws)
737 = PWith fc n capp (owargs ++ wargs) v
738 (map (fillLHSD n capp (owargs ++ wargs)) ws)
741 fillLHSD :: Name -> PTerm -> [PTerm] -> PDecl -> PDecl
742 fillLHSD n c a (PClauses fc o fn cs) = PClauses fc o fn (map (fillLHS n c a) cs)
745{- |Parses with pattern
748wExpr :: SyntaxInfo -> IdrisParser PTerm
749wExpr syn = do lchar '|'
753{- |Parses a where block
754WhereBlock ::= 'where' OpenBlock Decl+ CloseBlock;
756whereBlock :: Name -> SyntaxInfo -> IdrisParser ([PDecl], [(Name, Name)])
758 = do reserved "where"
759 ds <- indentedBlock1 (decl syn)
760 let dns = concatMap (concatMap declared) ds
761 return (concat ds, map (\x -> (x, decoration syn x)) dns)
764{- |Parses a code generation target language name
773codegen_ :: IdrisParser Codegen
774codegen_ = do reserved "C"; return ViaC
775 <|> do reserved "Java"; return ViaJava
776 <|> do reserved "JavaScript"; return ViaJavaScript
777 <|> do reserved "Node"; return ViaNode
778 <|> do reserved "LLVM"; return ViaLLVM
779 <|> do reserved "Bytecode"; return Bytecode
780 <?> "code generation language"
782{- |Parses a compiler directive
785 | String ',' StringList
788Directive ::= '%' Directive';
790Directive' ::= 'lib' CodeGen String_t
791 | 'link' CodeGen String_t
792 | 'flag' CodeGen String_t
793 | 'include' CodeGen String_t
796 | 'access' Accessibility
799 | 'dynamic' StringList
800 | 'name' Name NameList
801 | 'language' 'TypeProviders'
802 | 'language' 'ErrorReflection'
805directive :: SyntaxInfo -> IdrisParser [PDecl]
806directive syn = do try (lchar '%' *> reserved "lib"); cgn <- codegen_; lib <- stringLiteral;
807 return [PDirective (do addLib cgn lib
808 addIBC (IBCLib cgn lib))]
809 <|> do try (lchar '%' *> reserved "link"); cgn <- codegen_; obj <- stringLiteral;
810 return [PDirective (do dirs <- allImportDirs
811 o <- liftIO $ findInPath dirs obj
812 addIBC (IBCObj cgn obj) -- just name, search on loading ibc
813 addObjectFile cgn o)]
814 <|> do try (lchar '%' *> reserved "flag"); cgn <- codegen_;
815 flag <- stringLiteral
816 return [PDirective (do addIBC (IBCCGFlag cgn flag)
818 <|> do try (lchar '%' *> reserved "include"); cgn <- codegen_; hdr <- stringLiteral;
819 return [PDirective (do addHdr cgn hdr
820 addIBC (IBCHeader cgn hdr))]
821 <|> do try (lchar '%' *> reserved "hide"); n <- fnName
822 return [PDirective (do setAccessibility n Hidden
823 addIBC (IBCAccess n Hidden))]
824 <|> do try (lchar '%' *> reserved "freeze"); n <- iName []
825 return [PDirective (do setAccessibility n Frozen
826 addIBC (IBCAccess n Frozen))]
827 <|> do try (lchar '%' *> reserved "access"); acc <- accessibility
828 return [PDirective (do i <- get
829 put(i { default_access = acc }))]
830 <|> do try (lchar '%' *> reserved "default"); tot <- totality
832 put (i { default_total = tot } )
833 return [PDirective (do i <- get
834 put(i { default_total = tot }))]
835 <|> do try (lchar '%' *> reserved "logging"); i <- natural;
836 return [PDirective (setLogLevel (fromInteger i))]
837 <|> do try (lchar '%' *> reserved "dynamic"); libs <- sepBy1 stringLiteral (lchar ',');
838 return [PDirective (do added <- addDyLib libs
840 Left lib -> addIBC (IBCDyLib (lib_name lib))
843 <|> do try (lchar '%' *> reserved "name")
845 ns <- sepBy1 name (lchar ',')
847 (do mapM_ (addNameHint ty) ns
848 mapM_ (\n -> addIBC (IBCNameHint (ty, n))) ns)]
849 <|> do try (lchar '%' *> reserved "language"); ext <- pLangExt;
850 return [PDirective (addLangExt ext)]
853pLangExt :: IdrisParser LanguageExt
854pLangExt = (reserved "TypeProviders" >> return TypeProviders)
855 <|> (reserved "ErrorReflection" >> return ErrorReflection)
857{- | Parses a totality
858Totality ::= 'partial' | 'total'
860totality :: IdrisParser Bool
862 = do reserved "total"; return True
863 <|> do reserved "partial"; return False
865{- | Parses a type provider
866Provider ::= '%' 'provide' '(' FnName TypeSig ')' 'with' Expr;
868provider :: SyntaxInfo -> IdrisParser [PDecl]
869provider syn = do try (lchar '%' *> reserved "provide");
870 lchar '('; n <- fnName; lchar ':'; t <- typeExpr syn; lchar ')'
874 return [PProvider syn fc n t e]
877{- | Parses a transform
878Transform ::= '%' 'transform' Expr '==>' Expr
880transform :: SyntaxInfo -> IdrisParser [PDecl]
881transform syn = do try (lchar '%' *> reserved "transform")
882 -- leave it unchecked, until we work out what this should
884-- safety <- option True (do reserved "unsafe"
890 return [PTransform fc False l r]
894{- * Loading and parsing -}
895{- | Parses an expression from input -}
896parseExpr :: IState -> String -> Result PTerm
897parseExpr st = runparser (fullExpr defaultSyntax) st "(input)"
899{- | Parses a tactic from input -}
900parseTactic :: IState -> String -> Result PTactic
901parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
903-- | Parse module header and imports
904parseImports :: FilePath -> String -> Idris ([String], [String], Maybe Delta)
905parseImports fname input
907 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
908 Failure err -> fail (show err)
909 Success (x, i) -> do -- Discard state updates (there should be
912 where imports :: IdrisParser (([String], [String], Maybe Delta), IState)
913 imports = do whiteSpace
914 mname <- moduleHeader
917 isEof <- lookAheadMatches eof
922 return ((mname, ps, mrk'), i)
924-- | There should be a better way of doing this...
925findFC :: Doc -> (FC, String)
926findFC x = let s = show (plain x) in
927 case span (/= ':') s of
928 (failname, ':':rest) -> case span isDigit rest of
929 (line, ':':rest') -> (FC failname (read line) 0, drop 2 (dropWhile (/= ':') rest'))
931-- | A program is a list of declarations, possibly with associated
932-- documentation strings.
933parseProg :: SyntaxInfo -> FilePath -> String -> Maybe Delta ->
935parseProg syn fname input mrk
937 case runparser mainProg i fname input of
938 Failure doc -> do -- FIXME: Get error location from trifecta
939 -- this can't be the solution!
940 let (fc, msg) = findFC doc
942 case idris_outputmode i of
943 RawOutput -> ihputStrLn (idris_outh i) (show doc)
944 IdeSlave n -> ihWarn (idris_outh i) fc msg
945 putIState (i { errLine = Just (fc_line fc) }) -- Just errl })
947 Success (x, i) -> do putIState i
949 where mainProg :: IdrisParser ([PDecl], IState)
950 mainProg = case mrk of
951 Nothing -> do i <- get; return ([], i)
958{- | Load idris module and show error if something wrong happens -}
959loadModule :: Handle -> FilePath -> Idris String
961 = idrisCatch (loadModule' outh f)
962 (\e -> do setErrLine (getErrLine e)
968{- | Load idris module -}
969loadModule' :: Handle -> FilePath -> Idris String
972 let file = takeWhile (/= ' ') f
973 ibcsd <- valIBCSubDir i
975 fp <- liftIO $ findImport ids ibcsd file
976 if file `elem` imported i
977 then iLOG $ "Already read " ++ file
978 else do putIState (i { imported = file : imported i })
980 IDR fn -> loadSource outh False fn
981 LIDR fn -> loadSource outh True fn
983 idrisCatch (loadIBC fn)
984 (\c -> do iLOG $ fn ++ " failed " ++ show c
986 IDR sfn -> loadSource outh False sfn
987 LIDR sfn -> loadSource outh True sfn)
988 let (dir, fh) = splitFileName file
989 return (dropExtension fh)
992{- | Load idris code from file -}
993loadFromIFile :: Handle -> IFileType -> Idris ()
994loadFromIFile h i@(IBC fn src)
995 = do iLOG $ "Skipping " ++ getSrcFile i
996 idrisCatch (loadIBC fn)
997 (\err -> ierror $ LoadingFailed fn err)
999 getSrcFile (IDR fn) = fn
1000 getSrcFile (LIDR fn) = fn
1001 getSrcFile (IBC f src) = getSrcFile src
1003loadFromIFile h (IDR fn) = loadSource' h False fn
1004loadFromIFile h (LIDR fn) = loadSource' h True fn
1006{-| Load idris source code and show error if something wrong happens -}
1007loadSource' :: Handle -> Bool -> FilePath -> Idris ()
1009 = idrisCatch (loadSource h lidr r)
1010 (\e -> do setErrLine (getErrLine e)
1014{- | Load Idris source code-}
1015loadSource :: Handle -> Bool -> FilePath -> Idris ()
1017 = do iLOG ("Reading " ++ f)
1019 let def_total = default_total i
1020 file_in <- runIO $ readFile f
1021 file <- if lidr then tclift $ unlit f file_in else return file_in
1022 (mname, modules, pos) <- parseImports f file
1024 putIState (i { default_access = Hidden })
1025 clearIBC -- start a new .ibc file
1026 mapM_ (addIBC . IBCImport) modules
1027 ds' <- parseProg (defaultSyntax {syn_namespace = reverse mname })
1029 unless (null ds') $ do
1030 let ds = namespaces mname ds'
1031 logLvl 3 (showDecls True ds)
1033 logLvl 10 (show (toAlist (idris_implicits i)))
1034 logLvl 3 (show (idris_infixes i))
1035 -- Now add all the declarations to the context
1037 when v $ ihputStrLn h $ "Type checking " ++ f
1038 -- we totality check after every Mutual block, so if
1039 -- anything is a single definition, wrap it in a
1040 -- mutual block on its own
1041 elabDecls toplevel (map toMutual ds)
1043 -- simplify every definition do give the totality checker
1045 mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
1046 updateContext (simplifyCasedef n))
1047 (map snd (idris_totcheck i))
1048 -- build size change graph from simplified definitions
1049 iLOG "Totality checking"
1051 mapM_ buildSCG (idris_totcheck i)
1052 mapM_ checkDeclTotality (idris_totcheck i)
1054 -- Redo totality check for deferred names
1055 let deftots = idris_defertotcheck i
1056 iLOG $ "Totality checking " ++ show deftots
1057 mapM_ (\x -> do tot <- getTotality x
1059 Total _ -> setTotality x Unchecked
1060 _ -> return ()) (map snd deftots)
1061 mapM_ buildSCG deftots
1062 mapM_ checkDeclTotality deftots
1064 iLOG ("Finished " ++ f)
1065 ibcsd <- valIBCSubDir i
1066 iLOG "Universe checking"
1068 let ibc = ibcPathNoFallback ibcsd f
1070 addHides (hide_list i)
1073 idrisCatch (do writeIBC f ibc; clearIBC)
1074 (\c -> return ()) -- failure is harmless
1076 putIState (i { default_total = def_total,
1081 namespaces :: [String] -> [PDecl] -> [PDecl]
1082 namespaces [] ds = ds
1083 namespaces (x:xs) ds = [PNamespace x (namespaces xs ds)]
1085 toMutual :: PDecl -> PDecl
1086 toMutual m@(PMutual _ d) = m
1087 toMutual (PNamespace x ds) = PNamespace x (map toMutual ds)
1088 toMutual x = let r = PMutual (fileFC "single mutual") [x] in
1090 PClauses _ _ _ _ -> r
1091 PClass _ _ _ _ _ _ _ -> r
1092 PInstance _ _ _ _ _ _ _ _ -> r
1095{- | Adds names to hide list -}
1096addHides :: [(Name, Maybe Accessibility)] -> Idris ()
1097addHides xs = do i <- getIState
1098 let defh = default_access i
1099 let (hs, as) = partition isNothing xs
1102 (map (\ (n, _) -> (n, defh)) hs ++
1103 map (\ (n, Just a) -> (n, a)) as)
1104 where isNothing (_, Nothing) = True
1107 doHide (n, a) = do setAccessibility n a
1108 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