1module Nitpick.PatternMatches (patternMatches) where
3import Control.Arrow (second)
4import qualified Data.Foldable as F
5import qualified Data.Map as Map
6import qualified Data.Maybe as Maybe
7import qualified Data.Set as Set
9import qualified AST.Expression.General as E
10import qualified AST.Expression.Canonical as Canonical
11import qualified AST.Helpers as Help
12import qualified AST.Module as Module
13import qualified AST.Module.Name as ModuleName
14import qualified AST.Pattern as Pattern
15import qualified AST.Variable as Var
16import Elm.Utils ((|>))
17import Nitpick.Pattern (Pattern(..), fromCanonicalPattern)
18import qualified Optimize.DecisionTree as DT
19import qualified Reporting.Annotation as A
20import qualified Reporting.Error.Pattern as Error
21import qualified Reporting.Region as Region
22import qualified Reporting.Result as Result
29 -> Result.Result w Error.Error DT.VariantDict
30patternMatches interfaces (Module.Module _ name _ info) =
33 toTagDict interfaces name (Module.unions info)
35 const (Map.map (Map.map length) tagDict)
36 <$> checkExpression tagDict (Module.program info)
44 Map.Map Var.Home (Map.Map Tag [TagInfo])
56toTagDict :: Module.Interfaces -> ModuleName.Canonical -> Module.Unions -> TagDict
57toTagDict interfaces localName localUnions =
70 Map.singleton Var.BuiltIn $
80 |> Map.map (toTagMapping . Module.iUnions)
81 |> Map.mapKeysMonotonic Var.Module
82 |> Map.insert (Var.Module localName) (toTagMapping localUnions)
84 Map.union builtinDict interfaceDict
87toTagMapping :: Module.Unions -> Map.Map Tag [TagInfo]
90 toTagAndArity (_tvars, tagInfoList) =
92 info = map (\(tag, args) -> TagInfo tag (length args)) tagInfoList
94 map (second (const info)) tagInfoList
97 |> concatMap toTagAndArity
101lookupOtherTags :: Var.Canonical -> TagDict -> [TagInfo]
102lookupOtherTags (Var.Canonical home name) tagDict =
103 case Map.lookup name =<< Map.lookup home tagDict of
108 if Help.isTuple name then
109 [ TagInfo name (read (drop 6 name)) ]
112 "Since the Nitpick phase happens after canonicalization and type \
113 \inference, it is impossible that a pattern in a case cannot be \
124 -> Result.Result w Error.Error ()
125checkExpression tagDict (A.A region expression) =
128 checkExpression tagDict
143 E.ExplicitList listExprs ->
144 F.traverse_ go listExprs
146 E.Binop _ leftExpr rightExpr ->
147 go2 leftExpr rightExpr
149 E.Lambda pattern@(A.A patRegion _) body ->
150 checkPatterns tagDict patRegion Error.Arg [pattern]
156 E.If branches finally ->
157 F.traverse_ (uncurry go2) branches
162 <* F.traverse_ goDef defs
164 goDef (Canonical.Definition _ pattern@(A.A patRegion _) expr _) =
165 checkPatterns tagDict patRegion Error.LetBound [pattern]
168 E.Case expr branches ->
170 <* checkPatterns tagDict region Error.Case (map fst branches)
171 <* F.traverse_ (go . snd) branches
173 E.Data _ctor exprs ->
176 E.Access record _field ->
179 E.Update record fields ->
181 <* F.traverse_ (go . snd) fields
184 F.traverse_ (go . snd) fields
198 -> [Pattern.Canonical]
199 -> Result.Result w Error.Error ()
200checkPatterns tagDict region origin patterns =
201 checkPatternsHelp tagDict region origin [Anything] patterns
209 -> [Pattern.Canonical]
210 -> Result.Result w Error.Error ()
211checkPatternsHelp tagDict region origin unhandled patterns =
212 case (unhandled, patterns) of
217 Result.throw region (Error.Incomplete origin unhandled)
219 (_, pattern@(A.A localRegion _) : remainingPatterns) ->
220 do newUnhandled <- filterPatterns tagDict localRegion pattern unhandled
221 checkPatternsHelp tagDict region origin newUnhandled remainingPatterns
229 -> Result.Result w Error.Error [Pattern]
230filterPatterns tagDict region pattern unhandled =
233 fromCanonicalPattern pattern
236 intersection pat nitPattern == Nothing
238 if all noIntersection unhandled then
239 Result.throw region Error.Redundant
242 do let complementPatterns = complement tagDict nitPattern
245 (\p -> Maybe.mapMaybe (intersection p) complementPatterns)
250-- PATTERN INTERSECTION
253intersection :: Pattern -> Pattern -> Maybe Pattern
254intersection pattern1 pattern2 =
255 case (pattern1, pattern2) of
256 (Alias _ pattern1', _) ->
257 intersection pattern1' pattern2
259 (_, Alias _ pattern2') ->
260 intersection pattern1 pattern2'
274 (Data ctor1 args1, Data ctor2 args2) ->
275 if ctor1 /= ctor2 then
278 Data ctor1 <$> sequence (zipWith intersection args1 args2)
280 (Record _, Record _) ->
283 (Literal lit1, Literal lit2) ->
289 (AnythingBut literals, Literal lit) ->
290 if Set.member lit literals then
295 (Literal lit, AnythingBut literals) ->
296 if Set.member lit literals then
301 (AnythingBut literals1, AnythingBut literals2) ->
302 Just (AnythingBut (Set.union literals1 literals2))
312complement :: TagDict -> Pattern -> [Pattern]
313complement tagDict nitPattern =
318 Alias _name pattern ->
319 complement tagDict pattern
328 [AnythingBut (Set.singleton lit)]
330 AnythingBut literals ->
331 map Literal (Set.toList literals)
333 Data ctor patterns ->
334 complementData tagDict ctor patterns
337complementData :: TagDict -> Var.Canonical -> [Pattern] -> [Pattern]
338complementData tagDict tag patterns =
341 lookupOtherTags tag tagDict
344 Maybe.mapMaybe (tagToPattern tag) otherTags
350 concat (zipWith (makeArgComplements tagDict tag arity) [0..] patterns)
352 tagComplements ++ argComplements
355tagToPattern :: Var.Canonical -> TagInfo -> Maybe Pattern
356tagToPattern (Var.Canonical home rootTag) (TagInfo tag arity) =
357 if rootTag == tag then
360 Just (Data (Var.Canonical home tag) (replicate arity Anything))
363makeArgComplements :: TagDict -> Var.Canonical -> Int -> Int -> Pattern -> [Pattern]
364makeArgComplements tagDict tag arity index argPattern =
367 complement tagDict argPattern
370 replicate index Anything
372 : replicate (arity - index - 1) Anything
374 map (Data tag . padArgs) complementList
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