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
27 -> Module.CanonicalModule
28 -> Result.Result w Error.Error DT.VariantDict
29patternMatches interfaces modul =
31 name = Module.name modul
32 body = Module.body modul
34 toTagDict interfaces name (Module.unions body)
36 const (Map.map (Map.map length) tagDict)
37 <$> checkExpression tagDict (Module.program body)
45 Map.Map Var.Home (Map.Map Tag [TagInfo])
57toTagDict :: Module.Interfaces -> ModuleName.Canonical -> Module.Unions -> TagDict
58toTagDict interfaces localName localUnions =
71 Map.singleton Var.BuiltIn $
81 |> Map.map (toTagMapping . Module.iUnions)
82 |> Map.mapKeysMonotonic Var.Module
83 |> Map.insert (Var.Module localName) (toTagMapping localUnions)
85 Map.union builtinDict interfaceDict
88toTagMapping :: Module.Unions -> Map.Map Tag [TagInfo]
91 toTagAndArity (_tvars, tagInfoList) =
93 info = map (\(tag, args) -> TagInfo tag (length args)) tagInfoList
95 map (second (const info)) tagInfoList
98 |> concatMap toTagAndArity
102lookupOtherTags :: Var.Canonical -> TagDict -> [TagInfo]
103lookupOtherTags (Var.Canonical home name) tagDict =
104 case Map.lookup name =<< Map.lookup home tagDict of
109 if Help.isTuple name then
110 [ TagInfo name (read (drop 6 name)) ]
113 "Since the Nitpick phase happens after canonicalization and type \
114 \inference, it is impossible that a pattern in a case cannot be \
125 -> Result.Result w Error.Error ()
126checkExpression tagDict (A.A region expression) =
129 checkExpression tagDict
144 E.ExplicitList listExprs ->
145 F.traverse_ go listExprs
147 E.Binop _ leftExpr rightExpr ->
148 go2 leftExpr rightExpr
150 E.Lambda pattern@(A.A patRegion _) body ->
151 checkPatterns tagDict patRegion Error.Arg [pattern]
157 E.If branches finally ->
158 F.traverse_ (uncurry go2) branches
163 <* F.traverse_ goDef defs
165 goDef (Canonical.Definition _ pattern@(A.A patRegion _) expr _) =
166 checkPatterns tagDict patRegion Error.LetBound [pattern]
169 E.Case expr branches ->
171 <* checkPatterns tagDict region Error.Case (map fst branches)
172 <* F.traverse_ (go . snd) branches
174 E.Data _ctor exprs ->
177 E.Access record _field ->
180 E.Update record fields ->
182 <* F.traverse_ (go . snd) fields
185 F.traverse_ (go . snd) fields
199 -> [Pattern.Canonical]
200 -> Result.Result w Error.Error ()
201checkPatterns tagDict region origin patterns =
202 checkPatternsHelp tagDict region origin [Anything] patterns
210 -> [Pattern.Canonical]
211 -> Result.Result w Error.Error ()
212checkPatternsHelp tagDict region origin unhandled patterns =
213 case (unhandled, patterns) of
218 Result.throw region (Error.Incomplete origin unhandled)
220 (_, pattern@(A.A localRegion _) : remainingPatterns) ->
221 do newUnhandled <- filterPatterns tagDict localRegion pattern unhandled
222 checkPatternsHelp tagDict region origin newUnhandled remainingPatterns
230 -> Result.Result w Error.Error [Pattern]
231filterPatterns tagDict region pattern unhandled =
234 fromCanonicalPattern pattern
237 intersection pat nitPattern == Nothing
239 if all noIntersection unhandled then
240 Result.throw region Error.Redundant
243 do let complementPatterns = complement tagDict nitPattern
246 (\p -> Maybe.mapMaybe (intersection p) complementPatterns)
251-- PATTERN INTERSECTION
254intersection :: Pattern -> Pattern -> Maybe Pattern
255intersection pattern1 pattern2 =
256 case (pattern1, pattern2) of
257 (Alias _ pattern1', _) ->
258 intersection pattern1' pattern2
260 (_, Alias _ pattern2') ->
261 intersection pattern1 pattern2'
275 (Data ctor1 args1, Data ctor2 args2) ->
276 if ctor1 /= ctor2 then
279 Data ctor1 <$> sequence (zipWith intersection args1 args2)
281 (Record _, Record _) ->
284 (Literal lit1, Literal lit2) ->
290 (AnythingBut literals, Literal lit) ->
291 if Set.member lit literals then
296 (Literal lit, AnythingBut literals) ->
297 if Set.member lit literals then
302 (AnythingBut literals1, AnythingBut literals2) ->
303 Just (AnythingBut (Set.union literals1 literals2))
313complement :: TagDict -> Pattern -> [Pattern]
314complement tagDict nitPattern =
319 Alias _name pattern ->
320 complement tagDict pattern
329 [AnythingBut (Set.singleton lit)]
331 AnythingBut literals ->
332 map Literal (Set.toList literals)
334 Data ctor patterns ->
335 complementData tagDict ctor patterns
338complementData :: TagDict -> Var.Canonical -> [Pattern] -> [Pattern]
339complementData tagDict tag patterns =
342 lookupOtherTags tag tagDict
345 Maybe.mapMaybe (tagToPattern tag) otherTags
351 concat (zipWith (makeArgComplements tagDict tag arity) [0..] patterns)
353 tagComplements ++ argComplements
356tagToPattern :: Var.Canonical -> TagInfo -> Maybe Pattern
357tagToPattern (Var.Canonical home rootTag) (TagInfo tag arity) =
358 if rootTag == tag then
361 Just (Data (Var.Canonical home tag) (replicate arity Anything))
364makeArgComplements :: TagDict -> Var.Canonical -> Int -> Int -> Pattern -> [Pattern]
365makeArgComplements tagDict tag arity index argPattern =
368 complement tagDict argPattern
371 replicate index Anything
373 : replicate (arity - index - 1) Anything
375 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