1{-# LANGUAGE NamedFieldPuns, TupleSections #-}
8import Control.Applicative ((<$>), (<*>))
9import Control.Monad.Except (throwError)
10import Control.Monad (liftM)
11import Control.Monad (forM)
13import Data.Maybe (mapMaybe, catMaybes)
14import qualified Data.Set as Set
15import qualified Data.Map as Map
17import Elm.Utils ((|>))
18import qualified AST.Expression.General as General
19import qualified AST.Expression.Canonical as Canonical
20import qualified AST.Module as Module
21import qualified AST.Pattern as Pattern
22import AST.Pattern (CanonicalPattern)
23import qualified Reporting.Annotation as Annotation
24import qualified Reporting.Region as Region
25import qualified AST.Variable as Var
26import qualified Reporting.Error.CheckMatch as Error
27import Reporting.Warning.CheckMatch
30 Either (Annotation.Located Error.Error)
33fromPattern :: CanonicalPattern -> CanonicalPat
34fromPattern (Annotation.A _region p) =
36 Pattern.Data ctor ps ->
37 Data ctor (map fromPattern ps)
43 Alias s (fromPattern p)
57 -> Module.CanonicalBody
58 -> M [Annotation.Located Warning]
60 checkExpr . Module.program
62 checkExpr :: Canonical.Expr -> M [Annotation.Located Warning]
63 checkExpr (Annotation.A r e) =
65 General.ExplicitList es ->
66 concatMapM checkExpr es
68 General.Binop _ e e' ->
69 (++) <$> checkExpr e <*> checkExpr e'
72 maybeCons <$> checkMatch r [p] <*> checkExpr e
75 (++) <$> checkExpr e <*> checkExpr e'
77 General.MultiIf branches ->
78 concatMapM (\(b,e) -> (++) <$> checkExpr b <*> checkExpr e) branches
81 concat <$> sequence [ps, rhssResults, checkExpr e]
83 ps = mapMaybeM (\(Canonical.Definition p _ _) -> checkMatch r [p]) defs
84 rhssResults = concatMapM (\(Canonical.Definition _ e _) -> checkExpr e) defs
86 General.Case e branches ->
87 do eResults <- checkExpr e
88 result <- checkMatch r ps
89 branchResults <- concatMapM (checkExpr . snd) branches
90 return (eResults ++ maybeCons result branchResults)
91 where ps = map fst branches
93 General.Data _ctor es ->
94 concatMapM checkExpr es
96 General.Access e _f ->
99 General.Remove e _f ->
102 General.Insert e _f e' ->
103 (++) <$> checkExpr e <*> checkExpr e'
105 General.Modify e _ ->
108 General.Record fields ->
109 concatMapM (checkExpr . snd) fields
115 ctorToAdt :: Var.Canonical -> Maybe (Module.AdtInfo String)
117 \(Var.Canonical {Var.home,Var.name}) -> Map.lookup name =<< Map.lookup home m
119 -- Maps home to ctor name to the adt to which that ctor belongs
120 m :: Map.Map Var.Home (Map.Map String (Module.AdtInfo String))
121 m = builtins `Map.union` fromModules where
125 fromModules = Map.mapKeysMonotonic Var.Module (Map.map Module.iAdts interfaces)
128 ctorToAdtErr :: Region.Region -> Var.Canonical -> M (Module.AdtInfo String)
129 ctorToAdtErr region c =
132 throwError (Annotation.A region (Error.ConstructorTypeNotFound c))
138 complement :: Region.Region -> CanonicalPat -> M [CanonicalPat]
139 complement region p =
142 do let ctorName = Var.name ctor
143 ctorHome = Var.home ctor
144 (_tyVars, ctors) <- ctorToAdtErr region ctor
145 -- A pattern is in the complement of this one if it uses one of the
146 -- other constructors of this type...
147 let otherCtorPat (ctor', args) =
148 Data (Var.Canonical {Var.name = ctor', Var.home = ctorHome})
149 (replicate (length args) Anything)
152 filter (\(ctor', _) -> ctor' /= ctorName) ctors
155 -- or if it uses this constructor and one of its argument patterns is
156 -- in the complement of an argument pattern here.
158 sandwich pat i = replicate i Anything ++ pat : replicate (numArgs - i - 1) Anything
160 argComplement <- fmap concat . forM (zip [0..] ps) $ \(i, argP) ->
161 map (\argP' -> Data ctor (sandwich argP' i)) <$> (complement region argP)
163 return (otherCtorPatterns ++ argComplement)
178 return [AnythingBut (Set.singleton l)]
181 return (map Literal (Set.toList ls))
183 intersection :: CanonicalPat -> CanonicalPat -> Maybe CanonicalPat
204 (Data ctor1 args1, Data ctor2 args2) ->
207 else fmap (Data ctor1) (sequence (zipWith intersection args1 args2))
209 -- TODO Assuming the fields are identical.
210 (Record _fs, Record _) ->
213 (Literal l1, Literal l2) ->
214 if l1 == l2 then Just p1 else Nothing
216 (AnythingBut ls, Literal l) ->
217 if l `Set.member` ls then Nothing else Just p2
219 (Literal l, AnythingBut ls) ->
220 if l `Set.member` ls then Nothing else Just p1
222 (AnythingBut ls1, AnythingBut ls2) ->
223 Just (AnythingBut (Set.union ls1 ls2))
227 checkMatch :: Region.Region -> [CanonicalPattern] -> M (Maybe (Annotation.Located Warning))
231 go :: [CanonicalPat] -> [CanonicalPattern] -> M (Maybe (Annotation.Located Warning))
233 case (unhandled, ps) of
238 return (Just (Annotation.A region (Inexhaustive unhandled)))
241 let pp = fromPattern p
242 Annotation.A region _ = p
244 if all (\q -> intersection q pp == Nothing) unhandled
245 then return (Just (Annotation.A region (Redundant p)))
247 do pComp <- complement region pp
248 go (concatMap (\q -> mapMaybe (intersection q) pComp) unhandled) ps'
251concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
253 liftM concat . mapM f
256mapMaybeM :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]
258 liftM catMaybes . mapM f
261maybeCons :: Maybe a -> [a] -> [a]
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list