@@ -595,18 +595,12 @@ fnDecl' syn = checkFixity $
595 do (doc, argDocs, fc, opts', n, nfc, acc) <- try (do
595 do (doc, argDocs, fc, opts', n, nfc, acc) <- try (do
596 pushIndent
596 pushIndent
597 (doc, argDocs) <- docstring syn
597 (doc, argDocs) <- docstring syn
599− let initOpts = if default_total ist
602− opts <- fnOpts initOpts
603− acc <- accessibility
604− opts' <- fnOpts opts
598+ (opts, acc) <- fnOpts
605 (n_in, nfc) <- fnName
599 (n_in, nfc) <- fnName
606 let n = expandNS syn n_in
600 let n = expandNS syn n_in
607 fc <- getFC
601 fc <- getFC
608 lchar ':'
602 lchar ':'
609− return (doc, argDocs, fc, opts', n, nfc, acc))
603+ return (doc, argDocs, fc, opts, n, nfc, acc))
610 ty <- typeExpr (allowImp syn)
604 ty <- typeExpr (allowImp syn)
611 terminator
605 terminator
612 -- If it's a top level function, note the accessibility
606 -- If it's a top level function, note the accessibility
@@ -634,10 +628,40 @@ fnDecl' syn = checkFixity $
634 | otherwise = return True
628 | otherwise = return True
635 fixityOK _ = return True
629 fixityOK _ = return True
637−{-| Parses function options given initial options
631+{-| Parses a series of function and accessbility options
634+FnOpts ::= FnOpt* Accessibility FnOpt*
637+fnOpts :: IdrisParser ([FnOpt], Accessibility)
640+ acc <- accessibility
642+ let allOpts = opts ++ opts'
643+ let existingTotality = allOpts `intersect` [TotalFn, CoveringFn, PartialFn]
644+ opts'' <- addDefaultTotality (nub existingTotality) allOpts
645+ return (opts'', acc)
646+ where prettyTot TotalFn = "total"
647+ prettyTot PartialFn = "partial"
648+ prettyTot CoveringFn = "covering"
649+ addDefaultTotality [] opts = do
651+ case default_total ist of
652+ DefaultCheckingTotal -> return (TotalFn:opts)
653+ DefaultCheckingCovering -> return (CoveringFn:opts)
654+ DefaultCheckingPartial -> return opts -- Don't add partial so that --warn-partial still reports warnings if necessary
655+ addDefaultTotality [tot] opts = return opts
656+ -- Should really be a semantics error instead of a parser error
657+ addDefaultTotality (tot1:tot2:tots) opts =
658+ fail ("Conflicting totality modifiers specified " ++ prettyTot tot1 ++ " and " ++ prettyTot tot2)
661+{-| Parses a function option
640−FnOpts ::= 'total'
664+FnOpt ::= 'total'
641 | 'partial'
665 | 'partial'
642 | 'covering'
666 | 'covering'
643 | 'implicit'
667 | 'implicit'
@@ -660,37 +684,31 @@ NameTimesList ::=
663−-- FIXME: Check compatability for function options (i.e. partal/total)
665−-- Issue #1574 on the issue tracker.
666−-- https://github.com/idris-lang/Idris-dev/issues/1574
667−fnOpts :: [FnOpt] -> IdrisParser [FnOpt]
687+fnOpt :: IdrisParser FnOpt
669− = do reservedHL "total"; fnOpts (TotalFn : opts)
688+fnOpt = do reservedHL "total"; return TotalFn
670− <|> do reservedHL "partial"; fnOpts (PartialFn : (opts \\ [TotalFn]))
689+ <|> do reservedHL "partial"; return PartialFn
671− <|> do reservedHL "covering"; fnOpts (CoveringFn : (opts \\ [TotalFn]))
690+ <|> do reservedHL "covering"; return CoveringFn
672− <|> do try (lchar '%' *> reserved "export"); c <- fmap fst stringLiteral;
691+ <|> do try (lchar '%' *> reserved "export"); c <- fmap fst stringLiteral;
673− fnOpts (CExport c : opts)
692+ return $ CExport c
674− <|> do try (lchar '%' *> reserved "no_implicit");
693+ <|> do try (lchar '%' *> reserved "no_implicit");
675− fnOpts (NoImplicit : opts)
694+ return NoImplicit
676− <|> do try (lchar '%' *> reserved "inline");
695+ <|> do try (lchar '%' *> reserved "inline");
677− fnOpts (Inlinable : opts)
696+ return Inlinable
678− <|> do try (lchar '%' *> reserved "assert_total");
697+ <|> do try (lchar '%' *> reserved "assert_total");
679− fnOpts (AssertTotal : opts)
698+ return AssertTotal
680− <|> do try (lchar '%' *> reserved "error_handler");
699+ <|> do try (lchar '%' *> reserved "error_handler");
681− fnOpts (ErrorHandler : opts)
700+ return ErrorHandler
682− <|> do try (lchar '%' *> reserved "error_reverse");
701+ <|> do try (lchar '%' *> reserved "error_reverse");
683− fnOpts (ErrorReverse : opts)
702+ return ErrorReverse
684− <|> do try (lchar '%' *> reserved "reflection");
703+ <|> do try (lchar '%' *> reserved "reflection");
685− fnOpts (Reflection : opts)
704+ return Reflection
686− <|> do try (lchar '%' *> reserved "hint");
705+ <|> do try (lchar '%' *> reserved "hint");
687− fnOpts (AutoHint : opts)
706+ return AutoHint
688− <|> do lchar '%'; reserved "specialise";
707+ <|> do lchar '%'; reserved "specialise";
689− lchar '['; ns <- sepBy nameTimes (lchar ','); lchar ']'
708+ lchar '['; ns <- sepBy nameTimes (lchar ','); lchar ']';
690− fnOpts (Specialise ns : opts)
709+ return $ Specialise ns
691− <|> do reservedHL "implicit"; fnOpts (Implicit : opts)
710+ <|> do reservedHL "implicit"; return Implicit
693− <?> "function modifier"
711+ <?> "function modifier"
694 where nameTimes :: IdrisParser (Name, Maybe Int)
712 where nameTimes :: IdrisParser (Name, Maybe Int)
695 nameTimes = do n <- fst <$> fnName
713 nameTimes = do n <- fst <$> fnName
696 t <- option Nothing (do reds <- fmap fst natural
714 t <- option Nothing (do reds <- fmap fst natural
@@ -712,12 +730,7 @@ postulate syn = do (doc, ext)
712 ext <- ppostDecl
730 ext <- ppostDecl
713 return (doc, ext)
731 return (doc, ext)
714 ist <- get
732 ist <- get
715− let initOpts = if default_total ist
718− opts <- fnOpts initOpts
719− acc <- accessibility
720− opts' <- fnOpts opts
733+ (opts, acc) <- fnOpts
721 (n_in, nfc) <- fnName
734 (n_in, nfc) <- fnName
722 let n = expandNS syn n_in
735 let n = expandNS syn n_in
723 lchar ':'
736 lchar ':'
@@ -725,7 +738,7 @@ postulate syn = do (doc, ext)
725 fc <- getFC
738 fc <- getFC
726 terminator
739 terminator
727 addAcc n acc
740 addAcc n acc
728− return (PPostulate ext doc syn fc nfc opts' n ty)
741+ return (PPostulate ext doc syn fc nfc opts n ty)
729 <?> "postulate"
742 <?> "postulate"
730 where ppostDecl = do fc <- reservedHL "postulate"; return False
743 where ppostDecl = do fc <- reservedHL "postulate"; return False
731 <|> do lchar '%'; reserved "extern"; return True
744 <|> do lchar '%'; reserved "extern"; return True
@@ -940,15 +953,8 @@ InstanceName ::= '[' Name ']';
940instance_ :: Bool -> SyntaxInfo -> IdrisParser [PDecl]
953instance_ :: Bool -> SyntaxInfo -> IdrisParser [PDecl]
941instance_ kwopt syn
954instance_ kwopt syn
942 = do ist <- get
955 = do ist <- get
943− let initOpts = if default_total ist
947 (doc, argDocs) <- docstring syn
956 (doc, argDocs) <- docstring syn
948− opts <- fnOpts initOpts
949− acc <- accessibility
950− opts' <- fnOpts opts
957+ (opts, acc) <- fnOpts
952 if kwopt then optional instanceKeyword
958 if kwopt then optional instanceKeyword
953 else do instanceKeyword
959 else do instanceKeyword
954 return (Just ())
960 return (Just ())
@@ -963,7 +969,7 @@ instance_ kwopt syn
963 let t = bindList (PPi constraint) cs sc
969 let t = bindList (PPi constraint) cs sc
964 pnames <- instanceUsing
970 pnames <- instanceUsing
965 ds <- instanceBlock syn
971 ds <- instanceBlock syn
966− return [PInstance doc argDocs syn fc cs' pnames acc opts' cn cnfc args [] t en ds]
972+ return [PInstance doc argDocs syn fc cs' pnames acc opts cn cnfc args [] t en ds]
967 <?> "implementation declaration"
973 <?> "implementation declaration"
968 where instanceName :: IdrisParser Name
974 where instanceName :: IdrisParser Name
969 instanceName = do lchar '['; n_in <- fst <$> fnName; lchar ']'
975 instanceName = do lchar '['; n_in <- fst <$> fnName; lchar ']'
@@ -1424,14 +1430,15 @@ pLangExt = (reserved "TypeProviders" >> return TypeProviders)
1424{- | Parses a totality
1430{- | Parses a totality
1427−Totality ::= 'partial' | 'total'
1433+Totality ::= 'partial' | 'total' | 'covering'
1431−totality :: IdrisParser Bool
1437+totality :: IdrisParser DefaultTotality
1433− = do reservedHL "total"; return True
1439+ = do reservedHL "total"; return DefaultCheckingTotal
1434− <|> do reservedHL "partial"; return False
1440+ <|> do reservedHL "partial"; return DefaultCheckingPartial
1441+ <|> do reservedHL "covering"; return DefaultCheckingCovering
1436{- | Parses a type provider
1443{- | Parses a type provider