@@ -1,46 +1,32 @@
1−{-# LANGUAGE NamedFieldPuns #-}
1+{-# LANGUAGE NamedFieldPuns, TupleSections #-}
2module CheckMatch
2module CheckMatch
3− ( MatchResult (..)
3+ ( checkBody
4− , ErrorType (..)
4+ , Pat (..)
5− , checkModule
5+ , CanonicalPat
8−import Control.Applicative ((<$>))
8+import Control.Applicative ((<$>), (<*>))
9+import Control.Monad.Except (throwError)
10+import Control.Monad (liftM)
11+import Control.Monad (forM)
13+import Data.Maybe (mapMaybe, catMaybes)
14+import qualified Data.Set as Set
15+import qualified Data.Map as Map
9import qualified AST.Expression.General as General
17import qualified AST.Expression.General as General
10import qualified AST.Expression.Canonical as Canonical
18import qualified AST.Expression.Canonical as Canonical
11−import AST.Module
19+import qualified AST.Module as Module
12import qualified AST.Pattern as Pattern
20import qualified AST.Pattern as Pattern
13import AST.Pattern (CanonicalPattern)
21import AST.Pattern (CanonicalPattern)
14−import qualified AST.Annotation as Annotation
22+import qualified Reporting.Annotation as Annotation
15−import qualified Data.Map as Map
23+import qualified Reporting.Region as Region
16import qualified AST.Variable as Var
24import qualified AST.Variable as Var
17−import qualified AST.Literal as Literal
25+import qualified Reporting.Error.CheckMatch as Error
18−import Data.Maybe (mapMaybe)
26+import Reporting.Warning.CheckMatch
19−import Control.Monad (forM)
20−import qualified Data.Set as Set
23− = Redundant CanonicalPattern
24− | Inexhaustive CanonicalPat
31− | Alias String (Pat var)
34− | Literal Literal.Literal
35− -- It's a shame that I had to replicate the entire pattern type, but it's
36− -- essential to have this constructor.
37− | AnythingBut (Set.Set Literal.Literal)
38− deriving (Show, Eq, Ord)
40−type CanonicalPat = Pat Var.Canonical
42fromPattern :: CanonicalPattern -> CanonicalPat
28fromPattern :: CanonicalPattern -> CanonicalPat
43−fromPattern p = case p of
29+fromPattern (Annotation.A _region p) = case p of
44 Pattern.Data ctor ps -> Data ctor (map fromPattern ps)
30 Pattern.Data ctor ps -> Data ctor (map fromPattern ps)
45 Pattern.Record fs -> Record fs
31 Pattern.Record fs -> Record fs
46 Pattern.Alias s p -> Alias s (fromPattern p)
32 Pattern.Alias s p -> Alias s (fromPattern p)
@@ -48,73 +34,88 @@ fromPattern p = case p of
48 Pattern.Anything -> Anything
34 Pattern.Anything -> Anything
49 Pattern.Literal l -> Literal l
35 Pattern.Literal l -> Literal l
51−data ErrorType = ConstructorNotFound Var.Canonical
37+concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
38+concatMapM f = liftM concat . mapM f
40+mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]
41+mapMaybeM f = liftM catMaybes . mapM f
53−checkModule :: [CanonicalAdt] -> Module exports CanonicalBody -> [(Either ErrorType MatchResult, Annotation.Region)]
43+maybeCons :: Maybe a -> [a] -> [a]
54−checkModule adts (Module {body}) = checkBody body where
44+maybeCons = maybe id (:)
55− checkBody :: CanonicalBody -> [(Either ErrorType MatchResult, Annotation.Region)]
56− checkBody (CanonicalBody {program}) = checkExpr program
46+type M = Either (Annotation.Located Error.Error)
49+ -> Module.CanonicalBody
50+ -> M [Annotation.Located Warning]
51+checkBody interfaces = checkExpr . Module.program where
58− checkExpr :: Canonical.Expr -> [(Either ErrorType MatchResult, Annotation.Region)]
52+ checkExpr :: Canonical.Expr -> M [Annotation.Located Warning]
59 checkExpr (Annotation.A r e) = case e of
53 checkExpr (Annotation.A r e) = case e of
60− General.ExplicitList es -> concatMap checkExpr es
54+ General.ExplicitList es -> concatMapM checkExpr es
61− General.Binop _ e e' -> checkExpr e ++ checkExpr e'
55+ General.Binop _ e e' -> (++) <$> checkExpr e <*> checkExpr e'
62− General.Lambda p e -> (checkMatch [p], r) : checkExpr e
56+ General.Lambda p e -> maybeCons <$> checkMatch r [p] <*> checkExpr e
63− General.App e e' -> checkExpr e ++ checkExpr e'
57+ General.App e e' -> (++) <$> checkExpr e <*> checkExpr e'
64− General.MultiIf branches -> concatMap (\(b,e) -> checkExpr b ++ checkExpr e) branches
58+ General.MultiIf branches -> concatMapM (\(b,e) -> (++) <$> checkExpr b <*> checkExpr e) branches
66− General.Let defs e -> ps ++ rhssResults ++ checkExpr e
60+ General.Let defs e -> fmap concat $ sequence [ps, rhssResults, checkExpr e]
68− ps = map (\(Canonical.Definition p _ _) -> (checkMatch [p], r)) defs
62+ ps = mapMaybeM (\(Canonical.Definition p _ _) -> checkMatch r [p]) defs
69− rhssResults = concatMap (\(Canonical.Definition _ e _) -> checkExpr e) defs
63+ rhssResults = concatMapM (\(Canonical.Definition _ e _) -> checkExpr e) defs
71− General.Case e branches ->
65+ General.Case e branches -> do
66+ eResults <- checkExpr e
67+ result <- checkMatch r ps
72− (checkMatch ps, r) : checkExpr e ++ concatMap (checkExpr . snd) branches
68+ branchResults <- concatMapM (checkExpr . snd) branches
69+ return (eResults ++ maybeCons result branchResults)
73 where ps = map fst branches
70 where ps = map fst branches
75− General.Data _ctor es -> concatMap checkExpr es
72+ General.Data _ctor es -> concatMapM checkExpr es
76 General.Access e _f -> checkExpr e
73 General.Access e _f -> checkExpr e
77 General.Remove e _f -> checkExpr e
74 General.Remove e _f -> checkExpr e
78− General.Insert e _f e' -> checkExpr e ++ checkExpr e'
75+ General.Insert e _f e' -> (++) <$> checkExpr e <*> checkExpr e'
79 General.Modify e _ -> checkExpr e
76 General.Modify e _ -> checkExpr e
80− General.Record fields -> concatMap (checkExpr . snd) fields
77+ General.Record fields -> concatMapM (checkExpr . snd) fields
81− General.Port _pi -> []
78+ General.Port _pi -> return []
82− _ -> []
79+ _ -> return []
84− ctorToAdt :: Var.Canonical -> Maybe CanonicalAdt
81+ ctorToAdt :: Var.Canonical -> Maybe (Module.AdtInfo String)
85− ctorToAdt = \k -> Map.lookup k m where
82+ ctorToAdt = \(Var.Canonical {Var.home,Var.name}) -> Map.lookup name =<< Map.lookup home m where
86− m =
83+ m :: Map.Map Var.Home (Map.Map String {- ctor name -} (Module.AdtInfo String))
87− Map.fromList $ concatMap (\adt@(_adtName, (_tyVars, ctors)) ->
84+ m = builtins `Map.union` fromModules where
88− map (\(ctor,_args) -> (ctor, adt)) ctors)
85+ builtins = Map.empty -- TODO
90−
87+ fromModules = Map.mapKeysMonotonic Var.Module (Map.map Module.iAdts interfaces)
91− ctorToAdtExn :: Var.Canonical -> Either ErrorType CanonicalAdt
88+
89+ ctorToAdtErr :: Region.Region -> Var.Canonical -> M (Module.AdtInfo String)
92− ctorToAdtExn c = case ctorToAdt c of
90+ ctorToAdtErr region c = case ctorToAdt c of
93− Nothing -> Left (ConstructorNotFound c)
91+ Nothing -> throwError (Annotation.A region (Error.ConstructorTypeNotFound c))
94− Just adt -> Right adt
92+ Just adt -> return adt
96− complement :: CanonicalPat -> Either ErrorType [CanonicalPat]
94+ complement :: Region.Region -> CanonicalPat -> M [CanonicalPat]
97− complement p = case p of
95+ complement region p = case p of
98 Data ctor ps -> do
96 Data ctor ps -> do
97+ let ctorName = Var.name ctor
98+ ctorHome = Var.home ctor
99− (_adtName, (_tyVars, ctors)) <- ctorToAdtExn ctor
99+ (_tyVars, ctors) <- ctorToAdtErr region ctor
100 -- A pattern is in the complement of this one if it uses one of the
100 -- A pattern is in the complement of this one if it uses one of the
101 -- other constructors of this type...
101 -- other constructors of this type...
102 let otherCtorPatterns =
102 let otherCtorPatterns =
103 map (\(ctor',args) ->
103 map (\(ctor',args) ->
104+ Data (Var.Canonical {Var.name = ctor', Var.home = ctorHome})
104− Data ctor' (replicate (length args) Anything))
105+ (replicate (length args) Anything))
105− (filter (\(ctor', _) -> ctor' /= ctor) ctors)
106+ $ filter (\(ctor', _) -> ctor' /= ctorName) ctors
106 -- or if it uses this constructor and one of its argument patterns is
107 -- or if it uses this constructor and one of its argument patterns is
107 -- in the complement of an argument pattern here.
108 -- in the complement of an argument pattern here.
108 numArgs = length ps
109 numArgs = length ps
109 sandwich pat i = replicate i Anything ++ pat : replicate (numArgs - i - 1) Anything
110 sandwich pat i = replicate i Anything ++ pat : replicate (numArgs - i - 1) Anything
111 argComplement <- fmap concat . forM (zip [0..] ps) $ \(i, argP) ->
112 argComplement <- fmap concat . forM (zip [0..] ps) $ \(i, argP) ->
112− map (\argP' -> Data ctor (sandwich argP' i)) <$> (complement argP)
113+ map (\argP' -> Data ctor (sandwich argP' i)) <$> (complement region argP)
114 return (otherCtorPatterns ++ argComplement)
115 return (otherCtorPatterns ++ argComplement)
116 Record _fs -> return []
117 Record _fs -> return []
117− Alias _s p -> complement p
118+ Alias _s p -> complement region p
118 Var _s -> return []
119 Var _s -> return []
119 Anything -> return []
120 Anything -> return []
120 Literal l -> return [AnythingBut (Set.singleton l)]
121 Literal l -> return [AnythingBut (Set.singleton l)]
@@ -143,16 +144,18 @@ checkModule adts (Module {body}) = checkBody body where
143 (AnythingBut ls1, AnythingBut ls2) -> Just (AnythingBut (Set.union ls1 ls2))
144 (AnythingBut ls1, AnythingBut ls2) -> Just (AnythingBut (Set.union ls1 ls2))
144 _ -> Nothing
145 _ -> Nothing
146− checkMatch :: [CanonicalPattern] -> Either ErrorType MatchResult
147+ checkMatch :: Region.Region -> [CanonicalPattern] -> M (Maybe (Annotation.Located Warning))
147− checkMatch = go [Anything] where
148+ checkMatch region = go [Anything] where
148− go :: [CanonicalPat] -> [CanonicalPattern] -> Either ErrorType MatchResult
149+ go :: [CanonicalPat] -> [CanonicalPattern] -> M (Maybe (Annotation.Located Warning))
149− go [] [] = return Ok
150+ go [] [] = return Nothing
150− go (q:_) [] = return (Inexhaustive q)
151+ go qs@(_:_) [] = return (Just (Annotation.A region (Inexhaustive qs)))
151 go unhandled (p:ps) =
152 go unhandled (p:ps) =
152− let pp = fromPattern p in
153+ let pp = fromPattern p
154+ Annotation.A region _ = p
153 if all (\q -> intersection q pp == Nothing) unhandled
156 if all (\q -> intersection q pp == Nothing) unhandled
154− then return (Redundant p)
157+ then return (Just (Annotation.A region (Redundant p)))
156− pComp <- complement pp
159+ pComp <- complement region pp
157 go (concatMap (\q -> mapMaybe (intersection q) pComp) unhandled) ps
160 go (concatMap (\q -> mapMaybe (intersection q) pComp) unhandled) ps