language-dickinson-1.0.0.0: src/Language/Dickinson/Check/Pattern.hs
module Language.Dickinson.Check.Pattern ( traversePattern
, checkPatternDecl
) where
import Control.Applicative ((<|>))
import Data.Foldable (toList)
import Data.Foldable.Ext (foldMapAlternative)
import Data.List (group, sort)
import Data.Maybe (mapMaybe)
import Language.Dickinson.Error
import Language.Dickinson.Name
import Language.Dickinson.Type
traversePattern :: Pattern a -> [Name a]
traversePattern (PatternVar _ n) = [n]
traversePattern (PatternTuple _ ps) = traversePattern =<< toList ps
traversePattern Wildcard{} = []
traversePattern PatternCons{} = []
traversePattern (OrPattern _ ps) = traversePattern =<< toList ps
checkPattern :: Pattern a -> Maybe (DickinsonError a)
checkPattern p = checkCoherent p <|> checkNames p
checkNames :: Pattern a -> Maybe (DickinsonError a)
checkNames p = foldMapAlternative announce (group $ sort (traversePattern p))
where announce (_:y:_) = Just $ MultiBind (loc y) y p
announce _ = Nothing
noVar :: Pattern a -> Bool
noVar PatternVar{} = False
noVar (PatternTuple _ ps) = all noVar ps
noVar Wildcard{} = True
noVar PatternCons{} = True
noVar (OrPattern _ ps) = all noVar ps
-- in theory I guess if an or-pattern bound a variable in all its leaves (and
-- all were the same type) I guess it would work
--
-- but this throws out any or-patterns containing wildcards or variables
checkCoherent :: Pattern a -> Maybe (DickinsonError a)
checkCoherent PatternVar{} = Nothing
checkCoherent (PatternTuple _ ps) = foldMapAlternative checkCoherent ps
checkCoherent Wildcard{} = Nothing
checkCoherent PatternCons{} = Nothing
checkCoherent o@(OrPattern l _) | noVar o = Nothing
| otherwise = Just $ SuspectPattern l o
checkPatternExpr :: Expression a -> Maybe (DickinsonError a)
checkPatternExpr Var{} = Nothing
checkPatternExpr Literal{} = Nothing
checkPatternExpr StrChunk{} = Nothing
checkPatternExpr (Interp _ es) = foldMapAlternative checkPatternExpr es
checkPatternExpr (MultiInterp _ es) = foldMapAlternative checkPatternExpr es
checkPatternExpr (Apply _ e e') = checkPatternExpr e <|> checkPatternExpr e'
checkPatternExpr (Match _ e brs) = foldMapAlternative (checkPattern . fst) brs <|> checkPatternExpr e <|> foldMapAlternative (checkPatternExpr . snd) brs
checkPatternExpr (Choice _ brs) = foldMapAlternative (checkPatternExpr . snd) brs
checkPatternExpr (Concat _ es) = foldMapAlternative checkPatternExpr es
checkPatternExpr (Tuple _ es) = foldMapAlternative checkPatternExpr es
checkPatternExpr (Lambda _ _ _ e) = checkPatternExpr e
checkPatternExpr (Flatten _ e) = checkPatternExpr e
checkPatternExpr (Let _ bs e) = foldMapAlternative (checkPatternExpr . snd) bs <|> checkPatternExpr e
checkPatternExpr (Annot _ e _) = checkPatternExpr e
checkPatternExpr Constructor{} = Nothing
checkPatternDecl :: [Declaration a] -> Maybe (DickinsonError a)
checkPatternDecl ds =
foldMapAlternative checkPatternExpr (mapMaybe defExprM ds)