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)
24import Idris.Delaborate
27import Idris.ElabTerm hiding (namespace, params)
33import Idris.ParseHelpers
40import Util.DynamicLinker
43import Idris.Core.Evaluate
45import Control.Applicative
47import Control.Monad.Error (throwError, catchError)
48import Control.Monad.State.Strict
51import qualified Data.List.Split as Spl
55import qualified Data.HashSet as HS
56import qualified Data.Text as T
57import qualified Data.ByteString.UTF8 as UTF8
65 grammar shortcut notation:
66 ~CHARSEQ = complement of char sequence (i.e. any character except CHARSEQ)
67 RULE? = optional rule (i.e. RULE or nothing)
68 RULE* = repeated rule (i.e. RULE zero or more times)
69 RULE+ = repeated rule with at least one match (i.e. RULE one or more times)
70 RULE! = invalid rule (i.e. rule that is not valid in context, report meaningful error in case)
71 RULE{n} = rule repeated n times
76{- | Parses module definition
77 ModuleHeader ::= 'module' Identifier_t ';'?;
79moduleHeader :: IdrisParser [String]
80moduleHeader = try (do reserved "module"
82 option ';' (lchar ';')
83 return (moduleName i))
85 where moduleName x = case span (/='.') x of
87 (x, '.':y) -> x : moduleName y
89{- | Parses an import statement
90 Import ::= 'import' Identifier_t ';'?;
92import_ :: IdrisParser String
93import_ = do reserved "import"
95 option ';' (lchar ';')
97 <?> "import statement"
98 where toPath f = foldl1' (</>) (Spl.splitOn "." f)
100{- | Parses program source
103prog :: SyntaxInfo -> IdrisParser [PDecl]
104prog syn = do whiteSpace
105 decls <- many (decl syn)
108 let c = (concat decls)
111{- | Parses a top-level declaration
127decl :: SyntaxInfo -> IdrisParser [PDecl]
128decl syn = do notEndBlock
130 where declBody :: IdrisParser [PDecl]
138 <|> do d <- dsl syn; return [d]
142 <|> do import_; fail "imports must be at top of file"
144 declBody' :: IdrisParser [PDecl]
145 declBody' = do d <- decl' syn
147 let d' = fmap (debindApp syn . (desugar syn i)) d
150{- | Parses a top-level declaration with possible syntax sugar
159decl' :: SyntaxInfo -> IdrisParser PDecl
167{- | Parses a syntax extension declaration (and adds the rule to parser state)
168 SyntaxDecl ::= SyntaxRule;
170syntaxDecl :: SyntaxInfo -> IdrisParser PDecl
171syntaxDecl syn = do s <- syntaxRule syn
173 let rs = syntax_rules i
174 let ns = syntax_keywords i
175 let ibc = ibc_write i
176 let ks = map show (names s)
177 put (i { syntax_rules = s : rs,
178 syntax_keywords = ks ++ ns,
179 ibc_write = IBCSyntax s : map IBCKeyword ks ++ ibc })
181 return (PSyntax fc s)
182 where names (Rule syms _ _) = mapMaybe ename syms
183 ename (Keyword n) = Just n
186{- | Parses a syntax extension declaration
187SyntaxRuleOpts ::= 'term' | 'pattern';
190 SyntaxRuleOpts? 'syntax' SyntaxSym+ '=' TypeExpr Terminator;
192SyntaxSym ::= '[' Name_t ']'
198syntaxRule :: SyntaxInfo -> IdrisParser Syntax
202 sty <- option AnySyntax (do reserved "term"; return TermSyntax
203 <|> do reserved "pattern"; return PatternSyntax)
206 syms <- some syntaxSym
207 when (all isExpr syms) $ unexpected "missing keywords in syntax rule"
208 let ns = mapMaybe getName syms
209 when (length ns /= length (nub ns))
210 $ unexpected "repeated variable in syntax rule"
212 tm <- typeExpr (allowImp syn)
214 return (Rule (mkSimple syms) tm sty)
216 isExpr (Expr _) = True
218 getName (Expr n) = Just n
220 -- Can't parse two full expressions (i.e. expressions with application) in a row
221 -- so change them both to a simple expression
222 mkSimple (Expr e : es) = SimpleExpr e : mkSimple' es
223 mkSimple xs = mkSimple' xs
225 mkSimple' (Expr e : Expr e1 : es) = SimpleExpr e : SimpleExpr e1 :
227 mkSimple' (e : es) = e : mkSimple' es
231{- | Parses a syntax symbol (either binding variable, keyword or expression)
232SyntaxSym ::= '[' Name_t ']'
238syntaxSym :: IdrisParser SSymbol
239syntaxSym = try (do lchar '['; n <- name; lchar ']'
241 <|> try (do lchar '{'; n <- name; lchar '}'
245 <|> do sym <- stringLiteral
249{- | Parses a function declaration with possible syntax sugar
250 FunDecl ::= FunDecl';
252fnDecl :: SyntaxInfo -> IdrisParser [PDecl]
253fnDecl syn = try (do notEndBlock
256 let d' = fmap (desugar syn i) d
257 return [d']) <?> "function declaration"
259{- Parses a function declaration
261 DocComment_t? FnOpts* Accessibility? FnOpts* FnName TypeSig Terminator
267fnDecl' :: SyntaxInfo -> IdrisParser PDecl
268fnDecl' syn = checkFixity $
269 do (doc, fc, opts', n, acc) <- try (do
270 doc <- option "" (docComment '|')
273 let initOpts = if default_total ist
276 opts <- fnOpts initOpts
277 acc <- optional accessibility
280 let n = expandNS syn n_in
283 return (doc, fc, opts', n, acc))
284 ty <- typeExpr (allowImp syn)
287 return (PTy doc syn fc opts' n ty)
291 <?> "function declaration"
292 where checkFixity :: IdrisParser PDecl -> IdrisParser PDecl
293 checkFixity p = do decl <- p
295 Nothing -> return decl
296 Just n -> do fOk <- fixityOK n
298 "Missing fixity declaration for " ++ show n
300 getName (PTy _ _ _ _ n _) = Just n
302 fixityOK (NS n _) = fixityOK n
303 fixityOK (UN n) | all (flip elem opChars) n =
304 do fixities <- fmap idris_infixes get
305 return . elem n . map (\ (Fix _ op) -> op) $ fixities
306 | otherwise = return True
307 fixityOK _ = return True
309{- Parses function options given initial options
314 | '%' 'error_handler'
316 | '%' 'specialise' '[' NameTimesList? ']'
319NameTimes ::= FnName Natural?;
323 | NameTimes ',' NameTimesList
327-- FIXME: Check compatability for function options (i.e. partal/total)
328fnOpts :: [FnOpt] -> IdrisParser [FnOpt]
330 = do reserved "total"; fnOpts (TotalFn : opts)
331 <|> do reserved "partial"; fnOpts (PartialFn : (opts \\ [TotalFn]))
332 <|> do try (lchar '%' *> reserved "export"); c <- stringLiteral;
333 fnOpts (CExport c : opts)
334 <|> do try (lchar '%' *> reserved "assert_total");
335 fnOpts (AssertTotal : opts)
336 <|> do try (lchar '%' *> reserved "error_handler");
337 fnOpts (ErrorHandler : opts)
338 <|> do try (lchar '%' *> reserved "reflection");
339 fnOpts (Reflection : opts)
340 <|> do lchar '%'; reserved "specialise";
341 lchar '['; ns <- sepBy nameTimes (lchar ','); lchar ']'
342 fnOpts (Specialise ns : opts)
343 <|> do reserved "implicit"; fnOpts (Implicit : opts)
345 <?> "function modifier"
346 where nameTimes :: IdrisParser (Name, Maybe Int)
347 nameTimes = do n <- fnName
348 t <- option Nothing (do reds <- natural
349 return (Just (fromInteger reds)))
352{- | Parses a postulate
355 DocComment_t? 'postulate' FnOpts* Accesibility? FnOpts* FnName TypeSig Terminator
358postulate :: SyntaxInfo -> IdrisParser PDecl
359postulate syn = do doc <- try $ do doc <- option "" (docComment '|')
364 let initOpts = if default_total ist
367 opts <- fnOpts initOpts
368 acc <- optional accessibility
371 let n = expandNS syn n_in
373 ty <- typeExpr (allowImp syn)
377 return (PPostulate doc syn fc opts' n ty)
380{- | Parses a using declaration
383 'using' '(' UsingDeclList ')' OpenBlock Decl* CloseBlock
386using_ :: SyntaxInfo -> IdrisParser [PDecl]
388 do reserved "using"; lchar '('; ns <- usingDeclList syn; lchar ')'
390 let uvars = using syn
391 ds <- many (decl (syn { using = uvars ++ ns }))
394 <?> "using declaration"
396{- | Parses a parameters declaration
399 'parameters' '(' TypeDeclList ')' OpenBlock Decl* CloseBlock
402params :: SyntaxInfo -> IdrisParser [PDecl]
404 do reserved "parameters"; lchar '('; ns <- typeDeclList syn; lchar ')'
406 let pvars = syn_params syn
407 ds <- many (decl syn { syn_params = pvars ++ ns })
410 return [PParams fc ns (concat ds)]
411 <?> "parameters declaration"
413{- | Parses a mutual declaration (for mutually recursive functions)
416 'mutual' OpenBlock Decl* CloseBlock
419mutual :: SyntaxInfo -> IdrisParser [PDecl]
423 let pvars = syn_params syn
424 ds <- many (decl syn)
427 return [PMutual fc (concat ds)]
430{- | Parses a namespace declaration
433 'namespace' identifier OpenBlock Decl+ CloseBlock
436namespace :: SyntaxInfo -> IdrisParser [PDecl]
438 do reserved "namespace"; n <- identifier;
440 ds <- some (decl syn { syn_namespace = n : syn_namespace syn })
442 return [PNamespace n (concat ds)]
443 <?> "namespace declaration"
445{- |Parses a methods block (for instances)
446 InstanceBlock ::= 'where' OpenBlock FnDecl* CloseBlock
448instanceBlock :: SyntaxInfo -> IdrisParser [PDecl]
449instanceBlock syn = do reserved "where"
451 ds <- many (fnDecl syn)
456{- |Parses a methods and instances block (for type classes)
464 'where' OpenBlock MethodOrInstance* CloseBlock
467classBlock :: SyntaxInfo -> IdrisParser [PDecl]
468classBlock syn = do reserved "where"
470 ds <- many ((notEndBlock >> instance_ syn) <|> fnDecl syn)
475{- |Parses a type class declaration
479 | '(' Name ':' Expr ')'
483 DocComment_t? Accessibility? 'class' ConstraintList? Name ClassArgument* ClassBlock?
486class_ :: SyntaxInfo -> IdrisParser [PDecl]
487class_ syn = do (doc, acc) <- try (do
488 doc <- option "" (docComment '|')
489 acc <- optional accessibility
491 reserved "class"; fc <- getFC; cons <- constraintList syn; n_in <- name
492 let n = expandNS syn n_in
494 ds <- option [] (classBlock syn)
495 accData acc n (concatMap declared ds)
496 return [PClass doc syn fc cons n cs ds]
497 <?> "type-class declaration"
499 carg :: IdrisParser (Name, PTerm)
500 carg = do lchar '('; i <- name; lchar ':'; ty <- expr syn; lchar ')'
505{- |Parses a type class instance declaration
508 'instance' InstanceName? ConstraintList? Name SimpleExpr* InstanceBlock?
511 InstanceName ::= '[' Name ']';
513instance_ :: SyntaxInfo -> IdrisParser [PDecl]
514instance_ syn = do reserved "instance"; fc <- getFC
515 en <- optional instanceName
516 cs <- constraintList syn
518 args <- many (simpleExpr syn)
519 let sc = PApp fc (PRef fc cn) (map pexp args)
520 let t = bindList (PPi constraint) (map (\x -> (MN 0 "constraint", x)) cs) sc
521 ds <- option [] (instanceBlock syn)
522 return [PInstance syn fc cs cn args t en ds]
523 <?> "instance declaration"
524 where instanceName :: IdrisParser Name
525 instanceName = do lchar '['; n_in <- fnName; lchar ']'
526 let n = expandNS syn n_in
531{- | Parses a using declaration list
539 | UsingDecl ',' UsingDeclList'
547usingDeclList :: SyntaxInfo -> IdrisParser [Using]
549 = try (sepBy1 (usingDecl syn) (lchar ','))
550 <|> do ns <- sepBy1 name (lchar ',')
552 t <- typeExpr (disallowImp syn)
553 return (map (\x -> UImplicit x t) ns)
554 <?> "using declaration list"
556{- |Parses a using declaration
562usingDecl :: SyntaxInfo -> IdrisParser Using
563usingDecl syn = try (do x <- fnName
565 t <- typeExpr (disallowImp syn)
566 return (UImplicit x t))
569 return (UConstraint c xs)
570 <?> "using declaration"
572{- | Parse a clause with patterns
575pattern :: SyntaxInfo -> IdrisParser PDecl
576pattern syn = do fc <- getFC
578 return (PClauses fc [] (MN 2 "_") [clause]) -- collect together later
581{- | Parse a constant applicative form declaration
582 CAF ::= 'let' FnName '=' Expr Terminator;
584caf :: SyntaxInfo -> IdrisParser PDecl
585caf syn = do reserved "let"
586 n_in <- fnName; let n = expandNS syn n_in
592 <?> "constant applicative form declaration"
594{- | Parse an argument expression
595 ArgExpr ::= HSimpleExpr | {- In Pattern External (User-defined) Expression -};
597argExpr :: SyntaxInfo -> IdrisParser PTerm
598argExpr syn = let syn' = syn { inPattern = True } in
599 try (hsimpleExpr syn') <|> simpleExternalExpr syn'
600 <?> "argument expression"
602{- | Parse a right hand side of a function
608RHSName ::= '{' FnName '}';
610rhs :: SyntaxInfo -> Name -> IdrisParser PTerm
611rhs syn n = do lchar '='; expr syn
613 name <- option n' (do symbol "{"; n <- fnName; symbol "}";
616 return (addLet name r)
617 <|> do reserved "impossible"; return PImpossible
618 <?> "function right hand side"
619 where mkN :: Name -> Name
620 mkN (UN x) = UN (x++"_lemma_1")
621 mkN (NS x n) = NS (mkN x) n
624 addLet :: Name -> PTerm -> PTerm
625 addLet nm (PLet n ty val r) = PLet n ty val (addLet nm r)
626 addLet nm (PCase fc t cs) = PCase fc t (map addLetC cs)
627 where addLetC (l, r) = (l, addLet nm r)
628 addLet nm r = (PLet (UN "value") Placeholder r (PMetavar nm))
630{- |Parses a function clause
631RHSOrWithBlock ::= RHS WhereOrTerminator
632 | 'with' SimpleExpr OpenBlock FnDecl+ CloseBlock
634Clause ::= WExpr+ RHSOrWithBlock
635 | SimpleExpr '<==' FnName RHS WhereOrTerminator
636 | ArgExpr Operator ArgExpr WExpr* RHSOrWithBlock {- Except "=" and "?=" operators to avoid ambiguity -}
637 | FnName ConstraintArg* ImplicitOrArgExpr* WExpr* RHSOrWithBlock
639ImplicitOrArgExpr ::= ImplicitArg | ArgExpr;
640WhereOrTerminator ::= WhereBlock | Terminator;
642clause :: SyntaxInfo -> IdrisParser PClause
644 = do wargs <- try (do pushIndent; some (wExpr syn))
647 n <- case lastParse ist of
649 Nothing -> fail "Invalid clause"
651 let ctxt = tt_ctxt ist
652 let wsyn = syn { syn_namespace = [] }
653 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
658 return $ PClauseR fc wargs r wheres) <|> (do
661 wval <- simpleExpr syn
663 ds <- some $ fnDecl syn
664 let withs = concat ds
666 return $ PWithR fc wargs wval withs)
667 <|> do ty <- try (do pushIndent
672 n_in <- fnName; let n = expandNS syn n_in
675 let ctxt = tt_ctxt ist
676 let wsyn = syn { syn_namespace = [] }
677 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
682 let capp = PLet (MN 0 "match")
685 (PRef fc (MN 0 "match"))
687 put (ist { lastParse = Just n })
688 return $ PClause fc n capp [] r wheres
689 <|> do (l, op) <- try (do
693 when (op == "=" || op == "?=" ) $
694 fail "infix clause definition with \"=\" and \"?=\" not supported "
696 let n = expandNS syn (UN op)
699 wargs <- many (wExpr syn)
701 let wsyn = syn { syn_namespace = [] }
702 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
708 let capp = PApp fc (PRef fc n) [pexp l, pexp r]
709 put (ist { lastParse = Just n })
710 return $ PClause fc n capp wargs rs wheres) <|> (do
713 lchar '(' <?> "parenthesized expression"
714 wval <- bracketed syn
716 ds <- some $ fnDecl syn
719 let capp = PApp fc (PRef fc n) [pexp l, pexp r]
720 let withs = map (fillLHSD n capp wargs) $ concat ds
721 put (ist { lastParse = Just n })
722 return $ PWith fc n capp wargs wval withs)
724 n_in <- fnName; let n = expandNS syn n_in
725 cargs <- many (constraintArg syn)
727 args <- many (try (implicitArg (syn { inPattern = True } ))
728 <|> (fmap pexp (argExpr syn)))
729 wargs <- many (wExpr syn)
730 let capp = PApp fc (PRef fc n)
734 let ctxt = tt_ctxt ist
735 let wsyn = syn { syn_namespace = [] }
736 (wheres, nmap) <- choice [do x <- whereBlock n wsyn
742 put (ist { lastParse = Just n })
743 return $ PClause fc n capp wargs r wheres) <|> (do
746 put (ist { lastParse = Just n })
747 lchar '(' <?> "parenthesized expression"
748 wval <- bracketed syn
750 ds <- some $ fnDecl syn
751 let withs = map (fillLHSD n capp wargs) $ concat ds
754 return $ PWith fc n capp wargs wval withs)
755 <?> "function clause"
757 fillLHS :: Name -> PTerm -> [PTerm] -> PClause -> PClause
758 fillLHS n capp owargs (PClauseR fc wargs v ws)
759 = PClause fc n capp (owargs ++ wargs) v ws
760 fillLHS n capp owargs (PWithR fc wargs v ws)
761 = PWith fc n capp (owargs ++ wargs) v
762 (map (fillLHSD n capp (owargs ++ wargs)) ws)
765 fillLHSD :: Name -> PTerm -> [PTerm] -> PDecl -> PDecl
766 fillLHSD n c a (PClauses fc o fn cs) = PClauses fc o fn (map (fillLHS n c a) cs)
769{- |Parses with pattern
772wExpr :: SyntaxInfo -> IdrisParser PTerm
773wExpr syn = do lchar '|'
777{- |Parses a where block
778WhereBlock ::= 'where' OpenBlock Decl+ CloseBlock;
780whereBlock :: Name -> SyntaxInfo -> IdrisParser ([PDecl], [(Name, Name)])
782 = do reserved "where"
783 ds <- indentedBlock1 (decl syn)
784 let dns = concatMap (concatMap declared) ds
785 return (concat ds, map (\x -> (x, decoration syn x)) dns)
788{- |Parses a code generation target language name
797codegen_ :: IdrisParser Codegen
798codegen_ = do reserved "C"; return ViaC
799 <|> do reserved "Java"; return ViaJava
800 <|> do reserved "JavaScript"; return ViaJavaScript
801 <|> do reserved "Node"; return ViaNode
802 <|> do reserved "LLVM"; return ViaLLVM
803 <|> do reserved "Bytecode"; return Bytecode
804 <?> "code generation language"
806{- |Parses a compiler directive
809 | String ',' StringList
812Directive ::= '%' Directive';
814Directive' ::= 'lib' CodeGen String_t
815 | 'link' CodeGen String_t
816 | 'flag' CodeGen String_t
817 | 'include' CodeGen String_t
820 | 'access' Accessibility
823 | 'dynamic' StringList
824 | 'name' Name NameList
825 | 'language' 'TypeProviders'
826 | 'language' 'ErrorReflection'
829directive :: SyntaxInfo -> IdrisParser [PDecl]
830directive syn = do try (lchar '%' *> reserved "lib"); cgn <- codegen_; lib <- stringLiteral;
831 return [PDirective (do addLib cgn lib
832 addIBC (IBCLib cgn lib))]
833 <|> do try (lchar '%' *> reserved "link"); cgn <- codegen_; obj <- stringLiteral;
834 return [PDirective (do dirs <- allImportDirs
835 o <- liftIO $ findInPath dirs obj
836 addIBC (IBCObj cgn obj) -- just name, search on loading ibc
837 addObjectFile cgn o)]
838 <|> do try (lchar '%' *> reserved "flag"); cgn <- codegen_;
839 flag <- stringLiteral
840 return [PDirective (do addIBC (IBCCGFlag cgn flag)
842 <|> do try (lchar '%' *> reserved "include"); cgn <- codegen_; hdr <- stringLiteral;
843 return [PDirective (do addHdr cgn hdr
844 addIBC (IBCHeader cgn hdr))]
845 <|> do try (lchar '%' *> reserved "hide"); n <- fnName
846 return [PDirective (do setAccessibility n Hidden
847 addIBC (IBCAccess n Hidden))]
848 <|> do try (lchar '%' *> reserved "freeze"); n <- iName []
849 return [PDirective (do setAccessibility n Frozen
850 addIBC (IBCAccess n Frozen))]
851 <|> do try (lchar '%' *> reserved "access"); acc <- accessibility
852 return [PDirective (do i <- get
853 put(i { default_access = acc }))]
854 <|> do try (lchar '%' *> reserved "default"); tot <- totality
856 put (i { default_total = tot } )
857 return [PDirective (do i <- get
858 put(i { default_total = tot }))]
859 <|> do try (lchar '%' *> reserved "logging"); i <- natural;
860 return [PDirective (setLogLevel (fromInteger i))]
861 <|> do try (lchar '%' *> reserved "dynamic"); libs <- sepBy1 stringLiteral (lchar ',');
862 return [PDirective (do added <- addDyLib libs
864 Left lib -> addIBC (IBCDyLib (lib_name lib))
867 <|> do try (lchar '%' *> reserved "name")
869 ns <- sepBy1 name (lchar ',')
872 ty' <- case lookupCtxtName ty (idris_implicits i) of
873 [(tyn, _)] -> return tyn
874 [] -> throwError (NoSuchVariable ty)
875 tyns -> throwError (CantResolveAlts (map show (map fst tyns)))
876 mapM_ (addNameHint ty') ns
877 mapM_ (\n -> addIBC (IBCNameHint (ty', n))) ns)]
878 <|> do try (lchar '%' *> reserved "language"); ext <- pLangExt;
879 return [PDirective (addLangExt ext)]
882pLangExt :: IdrisParser LanguageExt
883pLangExt = (reserved "TypeProviders" >> return TypeProviders)
884 <|> (reserved "ErrorReflection" >> return ErrorReflection)
886{- | Parses a totality
887Totality ::= 'partial' | 'total'
889totality :: IdrisParser Bool
891 = do reserved "total"; return True
892 <|> do reserved "partial"; return False
894{- | Parses a type provider
895Provider ::= '%' 'provide' '(' FnName TypeSig ')' 'with' Expr;
897provider :: SyntaxInfo -> IdrisParser [PDecl]
898provider syn = do try (lchar '%' *> reserved "provide");
899 lchar '('; n <- fnName; lchar ':'; t <- typeExpr syn; lchar ')'
903 return [PProvider syn fc n t e]
906{- | Parses a transform
907Transform ::= '%' 'transform' Expr '==>' Expr
909transform :: SyntaxInfo -> IdrisParser [PDecl]
910transform syn = do try (lchar '%' *> reserved "transform")
911 -- leave it unchecked, until we work out what this should
913-- safety <- option True (do reserved "unsafe"
919 return [PTransform fc False l r]
923{- * Loading and parsing -}
924{- | Parses an expression from input -}
925parseExpr :: IState -> String -> Result PTerm
926parseExpr st = runparser (fullExpr defaultSyntax) st "(input)"
928{- | Parses a tactic from input -}
929parseTactic :: IState -> String -> Result PTactic
930parseTactic st = runparser (fullTactic defaultSyntax) st "(input)"
932-- | Parse module header and imports
933parseImports :: FilePath -> String -> Idris ([String], [String], Maybe Delta)
934parseImports fname input
936 case parseString (runInnerParser (evalStateT imports i)) (Directed (UTF8.fromString fname) 0 0 0 0) input of
937 Failure err -> fail (show err)
938 Success (x, i) -> do -- Discard state updates (there should be
941 where imports :: IdrisParser (([String], [String], Maybe Delta), IState)
942 imports = do whiteSpace
943 mname <- moduleHeader
946 isEof <- lookAheadMatches eof
951 return ((mname, ps, mrk'), i)
953-- | There should be a better way of doing this...
954findFC :: Doc -> (FC, String)
955findFC x = let s = show (plain x) in
956 case span (/= ':') s of
957 (failname, ':':rest) -> case span isDigit rest of
958 (line, ':':rest') -> case span isDigit rest' of
959 (col, ':':msg) -> (FC failname (read line) (read col), msg)
961-- | A program is a list of declarations, possibly with associated
962-- documentation strings.
963parseProg :: SyntaxInfo -> FilePath -> String -> Maybe Delta ->
965parseProg syn fname input mrk
967 case runparser mainProg i fname input of
968 Failure doc -> do -- FIXME: Get error location from trifecta
969 -- this can't be the solution!
970 let (fc, msg) = findFC doc
972 case idris_outputmode i of
973 RawOutput -> ihputStrLn (idris_outh i) (show doc)
974 IdeSlave n -> ihWarn (idris_outh i) fc msg
975 putIState (i { errLine = Just (fc_line fc) }) -- Just errl })
977 Success (x, i) -> do putIState i
979 where mainProg :: IdrisParser ([PDecl], IState)
980 mainProg = case mrk of
981 Nothing -> do i <- get; return ([], i)
988{- | Load idris module and show error if something wrong happens -}
989loadModule :: Handle -> FilePath -> Idris String
991 = idrisCatch (loadModule' outh f)
992 (\e -> do setErrLine (getErrLine e)
998{- | Load idris module -}
999loadModule' :: Handle -> FilePath -> Idris String
1002 let file = takeWhile (/= ' ') f
1003 ibcsd <- valIBCSubDir i
1004 ids <- allImportDirs
1005 fp <- liftIO $ findImport ids ibcsd file
1006 if file `elem` imported i
1007 then iLOG $ "Already read " ++ file
1008 else do putIState (i { imported = file : imported i })
1010 IDR fn -> loadSource outh False fn
1011 LIDR fn -> loadSource outh True fn
1013 idrisCatch (loadIBC fn)
1014 (\c -> do iLOG $ fn ++ " failed " ++ pshow i c
1016 IDR sfn -> loadSource outh False sfn
1017 LIDR sfn -> loadSource outh True sfn)
1018 let (dir, fh) = splitFileName file
1019 return (dropExtension fh)
1022{- | Load idris code from file -}
1023loadFromIFile :: Handle -> IFileType -> Idris ()
1024loadFromIFile h i@(IBC fn src)
1025 = do iLOG $ "Skipping " ++ getSrcFile i
1026 idrisCatch (loadIBC fn)
1027 (\err -> ierror $ LoadingFailed fn err)
1029 getSrcFile (IDR fn) = fn
1030 getSrcFile (LIDR fn) = fn
1031 getSrcFile (IBC f src) = getSrcFile src
1033loadFromIFile h (IDR fn) = loadSource' h False fn
1034loadFromIFile h (LIDR fn) = loadSource' h True fn
1036{-| Load idris source code and show error if something wrong happens -}
1037loadSource' :: Handle -> Bool -> FilePath -> Idris ()
1039 = idrisCatch (loadSource h lidr r)
1040 (\e -> do setErrLine (getErrLine e)
1044{- | Load Idris source code-}
1045loadSource :: Handle -> Bool -> FilePath -> Idris ()
1047 = do iLOG ("Reading " ++ f)
1049 let def_total = default_total i
1050 file_in <- runIO $ readFile f
1051 file <- if lidr then tclift $ unlit f file_in else return file_in
1052 (mname, modules, pos) <- parseImports f file
1054 putIState (i { default_access = Hidden })
1055 clearIBC -- start a new .ibc file
1056 mapM_ (addIBC . IBCImport) modules
1057 ds' <- parseProg (defaultSyntax {syn_namespace = reverse mname })
1059 unless (null ds') $ do
1060 let ds = namespaces mname ds'
1061 logLvl 3 (showDecls True ds)
1063 logLvl 10 (show (toAlist (idris_implicits i)))
1064 logLvl 3 (show (idris_infixes i))
1065 -- Now add all the declarations to the context
1067 when v $ ihputStrLn h $ "Type checking " ++ f
1068 -- we totality check after every Mutual block, so if
1069 -- anything is a single definition, wrap it in a
1070 -- mutual block on its own
1071 elabDecls toplevel (map toMutual ds)
1073 -- simplify every definition do give the totality checker
1075 mapM_ (\n -> do logLvl 5 $ "Simplifying " ++ show n
1076 updateContext (simplifyCasedef n))
1077 (map snd (idris_totcheck i))
1078 -- build size change graph from simplified definitions
1079 iLOG "Totality checking"
1081 mapM_ buildSCG (idris_totcheck i)
1082 mapM_ checkDeclTotality (idris_totcheck i)
1084 -- Redo totality check for deferred names
1085 let deftots = idris_defertotcheck i
1086 iLOG $ "Totality checking " ++ show deftots
1087 mapM_ (\x -> do tot <- getTotality x
1089 Total _ -> setTotality x Unchecked
1090 _ -> return ()) (map snd deftots)
1091 mapM_ buildSCG deftots
1092 mapM_ checkDeclTotality deftots
1094 iLOG ("Finished " ++ f)
1095 ibcsd <- valIBCSubDir i
1096 iLOG "Universe checking"
1098 let ibc = ibcPathNoFallback ibcsd f
1100 addHides (hide_list i)
1103 idrisCatch (do writeIBC f ibc; clearIBC)
1104 (\c -> return ()) -- failure is harmless
1106 putIState (i { default_total = def_total,
1111 namespaces :: [String] -> [PDecl] -> [PDecl]
1112 namespaces [] ds = ds
1113 namespaces (x:xs) ds = [PNamespace x (namespaces xs ds)]
1115 toMutual :: PDecl -> PDecl
1116 toMutual m@(PMutual _ d) = m
1117 toMutual (PNamespace x ds) = PNamespace x (map toMutual ds)
1118 toMutual x = let r = PMutual (fileFC "single mutual") [x] in
1120 PClauses _ _ _ _ -> r
1121 PClass _ _ _ _ _ _ _ -> r
1122 PInstance _ _ _ _ _ _ _ _ -> r
1125{- | Adds names to hide list -}
1126addHides :: [(Name, Maybe Accessibility)] -> Idris ()
1127addHides xs = do i <- getIState
1128 let defh = default_access i
1129 let (hs, as) = partition isNothing xs
1132 (map (\ (n, _) -> (n, defh)) hs ++
1133 map (\ (n, Just a) -> (n, a)) as)
1134 where isNothing (_, Nothing) = True
1137 doHide (n, a) = do setAccessibility n a
1138 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