language-dickinson-1.3.0.0: src/Language/Dickinson/Check/Exhaustive.hs
module Language.Dickinson.Check.Exhaustive ( checkExhaustive
, foliate
) where
import Control.Applicative ((<|>))
import Data.Foldable (toList)
import Data.List (inits)
import Data.Maybe (mapMaybe)
import Language.Dickinson.Check.Common
import Language.Dickinson.Error
import Language.Dickinson.Pattern.Useless
import Language.Dickinson.Type
checkExhaustive :: [Declaration a] -> Maybe (DickinsonWarning a)
checkExhaustive ds = runPatternM (checkDeclsM ds)
checkDeclsM :: [Declaration a] -> PatternM (Maybe (DickinsonWarning a))
checkDeclsM ds =
patternEnvDecls ds *>
mapSumM checkDeclM ds
checkDeclM :: Declaration a -> PatternM (Maybe (DickinsonWarning a))
checkDeclM TyDecl{} = pure Nothing
checkDeclM (Define _ _ e) = checkExprM e
isExhaustiveM :: [Pattern a] -> a -> PatternM (Maybe (DickinsonWarning a))
isExhaustiveM ps loc = do
e <- isExhaustive ps
pure $ if e
then Nothing
else Just $ InexhaustiveMatch loc
uselessErr :: [Pattern a] -> Pattern a -> PatternM (Maybe (DickinsonWarning a))
uselessErr ps p = {-# SCC "uselessErr" #-} do
e <- useful ps p
pure $ if e
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 :: [Pattern a] -> a -> PatternM (Maybe (DickinsonWarning a))
checkMatch ps loc = {-# SCC "checkMatch" #-}
(<|>)
<$> mapSumM (uncurry uselessErr) ({-# SCC "foliate" #-} foliate ps)
<*> isExhaustiveM ps loc
checkExprM :: Expression a -> PatternM (Maybe (DickinsonWarning a))
checkExprM Var{} = pure Nothing
checkExprM Literal{} = pure Nothing
checkExprM StrChunk{} = pure Nothing
checkExprM Constructor{} = pure Nothing
checkExprM BuiltinFn{} = pure Nothing
checkExprM (Flatten _ e) = checkExprM e
checkExprM (Annot _ e _) = checkExprM e
checkExprM (Lambda _ _ _ e) = checkExprM e
checkExprM (Choice _ brs) = mapSumM checkExprM (snd <$> brs)
checkExprM (Let _ brs e) = (<|>) <$> mapSumM checkExprM (snd <$> brs) <*> checkExprM e
checkExprM (Interp _ es) = mapSumM checkExprM es
checkExprM (MultiInterp _ es) = mapSumM checkExprM es
checkExprM (Apply _ e e') = (<|>) <$> checkExprM e <*> checkExprM e'
checkExprM (Concat _ es) = mapSumM checkExprM es
checkExprM (Tuple _ es) = mapSumM checkExprM es
checkExprM (Match l e brs) =
(<|>)
<$> checkExprM e
<*> ((<|>) <$> checkMatch (toList (fst <$> brs)) l <*> mapSumM checkExprM (snd <$> brs))