{-# LANGUAGE ViewPatterns #-}
{-
Improve the structure of code
<TEST>
yes x y = if a then b else if c then d else e -- yes x y ; | a = b ; | c = d ; | otherwise = e
x `yes` y = if a then b else if c then d else e -- yes x y ; | a = b ; | c = d ; | otherwise = e
no x y = if a then b else c
-- foo b | c <- f b = c -- foo (f -> c) = c
-- foo x y b z | c:cs <- f g b = c -- foo x y (f g -> c:cs) z = c
foo b | c <- f b = c + b
foo b | c <- f b = c where f = here
foo b | c <- f b = c where foo = b
foo b | c <- f b = c \
| c <- f b = c
foo x = yes x x where yes x y = if a then b else if c then d else e -- yes x y ; | a = b ; | c = d ; | otherwise = e
foo x | otherwise = y -- foo x = y
-- FIXME: #358 foo x = x + x where -- foo x = x + x
foo x | a = b | True = d -- foo x | a = b ; | otherwise = d
foo (Bar _ _ _ _) = x -- Bar{}
foo (Bar _ x _ _) = x
foo (Bar _ _) = x
foo = case f v of _ -> x -- x
foo = case v of v -> x -- x
foo = case v of z -> z
foo = case v of _ | False -> x
foo = case v of !True -> x -- True
foo = case v of !(Just x) -> x -- (Just x)
foo = case v of !(x : xs) -> x -- (x:xs)
foo = case v of !1 -> x -- 1
foo = case v of !x -> x
foo = let ~x = 1 in y -- x
foo = let ~(x:xs) = y in z
</TEST>
-}
module Hint.Structure(structureHint) where
import Hint.Type
import Util
structureHint :: DeclHintstructureHint _ _ x =
concatMap (uncurryhints.swap) (asPatternx) ++concatMappatHint (universeBix) ++concatMapexpHint (universeBix)
hints :: (String -> Pattern -> Idea) -> Pattern -> [Idea]
hintsgen (Patternpat (UnGuardedRhsdbod) bind)
| lengthguards>2 = [gen"Use guards"$Patternpat (GuardedRhssdguards) bind]
where guards = asGuardsbod{-
-- Do not suggest view patterns, they aren't something everyone likes sufficiently
hints gen (Pattern pats (GuardedRhss _ [GuardedRhs _ [Generator _ pat (App _ op (view -> Var_ p))] bod]) bind)
| Just i <- findIndex (=~= (toNamed p :: Pat_)) pats
, p `notElem` (vars bod ++ vars bind)
, vars op `disjoint` decsBind, pvars pats `disjoint` vars op, pvars pat `disjoint` pvars pats
= [gen "Use view patterns" $
Pattern (take i pats ++ [PParen an $ PViewPat an op pat] ++ drop (i+1) pats) (UnGuardedRhs an bod) bind]
where
decsBind = nub $ concatMap declBind $ childrenBi bind
-}hintsgen (Patternpats (GuardedRhss _ [GuardedRhs _ [test] bod]) bind)
| prettyPrinttest`elem` ["otherwise","True"]
= [gen"Redundant guard"$Patternpats (UnGuardedRhsanbod) bind]
hintsgen (Patternpatsbod (Justbind)) | fbind&&False-- disabled due to bug 358
= [gen"Redundant where"$PatternpatsbodNothing]
where
f (BDecls _ x) = nullxf (IPBinds _ x) = nullxhintsgen (Patternpats (GuardedRhss _ (unsnoc -> (gs, GuardedRhs _ [test] bod))) bind)
| prettyPrinttest=="True"
= [gen"Use otherwise"$Patternpats (GuardedRhssan$gs++ [GuardedRhsan [Qualifieran$toNamed"otherwise"] bod]) bind]
hints _ _ = []
asGuards :: Exp_ -> [GuardedRhsS]
asGuards (Paren _ x) = asGuardsxasGuards (If _ abc) = GuardedRhsan [Qualifierana] b:asGuardscasGuardsx = [GuardedRhsan [Qualifieran$toNamed"otherwise"] x]
data Pattern = Pattern [Pat_] (RhsS) (Maybe (BindsS))
-- Invariant: Number of patterns may not changeasPattern :: Decl_ -> [(Pattern, String -> Pattern -> Idea)]
asPatternx = concatMapdecl (universeBix) ++concatMapalt (universeBix)
where
declo@(PatBindapatbrhsbind) = [(Pattern [pat] rhsbind, \msg (Pattern [pat] rhsbind) -> warnmsgo$PatBindapatbrhsbind)]
decl (FunBind _ xs) = mapmatchxsdecl _ = []
matcho@(Matchabpatrhsbind) = (Patternpatrhsbind, \msg (Patternpatrhsbind) -> warnmsgo$Matchabpatrhsbind)
matcho@(InfixMatchapbpsrhsbind) = (Pattern (p:ps) rhsbind, \msg (Pattern (p:ps) rhsbind) -> warnmsgo$InfixMatchapbpsrhsbind)
alto@(Altapatrhsbind) = [(Pattern [pat] (fromGuardedAltsrhs) bind, \msg (Pattern [pat] rhsbind) -> warnmsgo$Altapat (toGuardedAltsrhs) bind)]
-- Should these hints be in the same module? They are less structure, and more about pattern matching-- Or perhaps the entire module should be renamed Pattern, since it's all about patternspatHint :: Pat_ -> [Idea]
patHinto@(PApp _ nameargs) | lengthargs>=3&&allisPWildCardargs = [warn"Use record patterns"o$PRecanname []]
patHinto@(PBangPat _ x) | fx = [err"Redundant bang pattern"ox]
where f (PParen _ x) = fxf (PAsPat _ _ x) = fxfPLit{} = TruefPApp{} = TruefPInfixApp{} = Truef _ = FalsepatHinto@(PIrrPat _ x) | fx = [err"Redundant irrefutable pattern"ox]
where f (PParen _ x) = fxf (PAsPat _ _ x) = fxfPWildCard{} = TruefPVar{} = Truef _ = FalsepatHint _ = []
expHint :: Exp_ -> [Idea]
expHinto@(Case _ _ [Alt _ PWildCard{} (UnGuardedAlt _ e) Nothing]) = [warn"Redundant case"oe]
expHinto@(Case _ (Var _ x) [Alt _ (PVar _ y) (UnGuardedAlt _ e) Nothing])
| x=~=UnQualany = [warn"Redundant case"oe]
expHint _ = []