language-dickinson-1.4.1.2: src/Language/Dickinson/Check/Exhaustive.hs
module Language.Dickinson.Check.Exhaustive ( checkExhaustive
) where
import Control.Applicative ((<|>))
import Data.Foldable (toList)
import Data.Foldable.Ext
import Data.List (inits)
import Data.Maybe (mapMaybe)
import Language.Dickinson.Error
import Language.Dickinson.Pattern.Useless
import Language.Dickinson.Type
-- | Check that there are no useless pattern clauses and check that the pattern
-- matches are exhaustive
checkExhaustive :: [Declaration a] -> Maybe (DickinsonWarning a)
checkExhaustive = checkDeclsM
checkDeclsM :: [Declaration a] -> Maybe (DickinsonWarning a)
checkDeclsM ds =
let pEnv = runPatternM $ patternEnvDecls ds in
foldMapAlternative (checkDecl pEnv) ds
checkDecl :: PatternEnv -> Declaration a -> Maybe (DickinsonWarning a)
checkDecl _ TyDecl{} = Nothing
checkDecl env (Define _ _ e) = checkExpr env e
isExhaustiveErr :: PatternEnv -> [Pattern a] -> a -> Maybe (DickinsonWarning a)
isExhaustiveErr env ps loc =
if isExhaustive env ps
then Nothing
else Just $ InexhaustiveMatch loc
uselessErr :: PatternEnv -> [Pattern a] -> Pattern a -> Maybe (DickinsonWarning a)
uselessErr env ps p = {-# SCC "uselessErr" #-}
if useful env ps p
then Nothing
else Just $ UselessPattern (patAnn p) p
foliate :: [a] -> [([a], a)]
foliate = mapMaybe split . inits
where split [] = Nothing
split [_] = Nothing
split xs = Just (init xs, last xs)
checkMatch :: PatternEnv -> [Pattern a] -> a -> Maybe (DickinsonWarning a)
checkMatch env ps loc = {-# SCC "checkMatch" #-}
foldMapAlternative (uncurry (uselessErr env)) ({-# SCC "foliate" #-} foliate ps)
<|> isExhaustiveErr env ps loc
checkExpr :: PatternEnv -> Expression a -> Maybe (DickinsonWarning a)
checkExpr _ Var{} = Nothing
checkExpr _ Literal{} = Nothing
checkExpr _ StrChunk{} = Nothing
checkExpr _ Constructor{} = Nothing
checkExpr _ BuiltinFn{} = Nothing
checkExpr _ Random{} = Nothing
checkExpr env (Flatten _ e) = checkExpr env e
checkExpr env (Annot _ e _) = checkExpr env e
checkExpr env (Lambda _ _ _ e) = checkExpr env e
checkExpr env (Choice _ brs) = foldMapAlternative (checkExpr env) (snd <$> brs)
checkExpr env (Let _ brs e) = foldMapAlternative (checkExpr env) (snd <$> brs) <|> checkExpr env e
checkExpr env (Bind _ brs e) = foldMapAlternative (checkExpr env) (snd <$> brs) <|> checkExpr env e
checkExpr env (Interp _ es) = foldMapAlternative (checkExpr env) es
checkExpr env (MultiInterp _ es) = foldMapAlternative (checkExpr env) es
checkExpr env (Apply _ e e') = checkExpr env e <|> checkExpr env e'
checkExpr env (Concat _ es) = foldMapAlternative (checkExpr env) es
checkExpr env (Tuple _ es) = foldMapAlternative (checkExpr env) es
checkExpr env (Match l e brs) =
checkExpr env e
<|> checkMatch env (toList (fst <$> brs)) l <|> foldMapAlternative (checkExpr env) (snd <$> brs)