3
3
-- | This module is loosely based off /Warnings for pattern matching/ by Luc
4
4
-- Maranget
5
5
module Language.Dickinson.Pattern.Useless ( PatternM
6
+ , PatternEnv
6
7
, runPatternM
7
8
, isExhaustive
8
9
, patternEnvDecls
@@ -12,15 +13,14 @@ module Language.Dickinson.Pattern.Useless ( PatternM
12
13
, specializeTag
13
14
) where
14
15
15
- import Control.Monad (forM , forM_ )
16
- import Control.Monad.State.Strict (State , evalState , get )
16
+ import Control.Monad (forM_ )
17
+ import Control.Monad.State.Strict (State , execState )
17
18
import Data.Coerce (coerce )
18
19
import Data.Foldable (toList , traverse_ )
19
20
import Data.Functor (void )
20
21
import Data.IntMap.Strict (findWithDefault )
21
22
import qualified Data.IntMap.Strict as IM
22
23
import qualified Data.IntSet as IS
23
- import Data.List.Ext
24
24
import Language.Dickinson.Name
25
25
import Language.Dickinson.Type
26
26
import Language.Dickinson.Unique
@@ -52,34 +52,32 @@ patternEnvDecls = traverse_ declAdd
52
52
-- TODO: just reader monad... writer at beginning?
53
53
type PatternM = State PatternEnv
54
54
55
- runPatternM :: PatternM a -> a
56
- runPatternM = flip evalState (PatternEnv mempty mempty )
55
+ runPatternM :: PatternM a -> PatternEnv
56
+ runPatternM = flip execState (PatternEnv mempty mempty )
57
57
58
58
-- given a constructor name, get the IntSet of all constructors of that type
59
- assocUniques :: Name a -> PatternM IS. IntSet
60
- assocUniques (Name _ (Unique i) _) = {-# SCC "assocUniques" #-} do
61
- st <- get
62
- let ty = findWithDefault internalError i (types st)
63
- pure $ findWithDefault internalError ty (allCons st)
59
+ assocUniques :: PatternEnv -> Name a -> IS. IntSet
60
+ assocUniques env (Name _ (Unique i) _) = {-# SCC "assocUniques" #-}
61
+ let ty = findWithDefault internalError i (types env)
62
+ in findWithDefault internalError ty (allCons env)
64
63
65
64
internalError :: a
66
65
internalError = error " Internal error: lookup in a PatternEnv failed"
67
66
68
- isExhaustive :: [Pattern a ] -> PatternM Bool
69
- isExhaustive ps = {-# SCC "isExhaustive" #-} not <$> useful ps (Wildcard undefined )
67
+ isExhaustive :: PatternEnv -> [Pattern a ] -> Bool
68
+ isExhaustive env ps = {-# SCC "isExhaustive" #-} not $ useful env ps (Wildcard undefined )
70
69
71
- isCompleteSet :: [Name a ] -> PatternM (Maybe [Name () ])
72
- isCompleteSet [] = pure Nothing
73
- isCompleteSet ns@ (n: _) = do
74
- allU <- assocUniques n
75
- let ty = coerce (unique <$> ns)
76
- pure $
77
- if IS. null (allU IS. \\ IS. fromList ty)
70
+ isCompleteSet :: PatternEnv -> [Name a ] -> Maybe [Name () ]
71
+ isCompleteSet _ [] = Nothing
72
+ isCompleteSet env ns@ (n: _) =
73
+ let allU = assocUniques env n
74
+ ty = coerce (unique <$> ns)
75
+ in if IS. null (allU IS. \\ IS. fromList ty)
78
76
then Just ((\ u -> Name undefined (Unique u) () ) <$> IS. toList allU)
79
77
else Nothing
80
78
81
- useful :: [Pattern a ] -> Pattern a -> PatternM Bool
82
- useful ps p = usefulMaranget [[p'] | p' <- ps] [p]
79
+ useful :: PatternEnv -> [Pattern a ] -> Pattern a -> Bool
80
+ useful env ps p = usefulMaranget env [[p'] | p' <- ps] [p]
83
81
84
82
sanityFailed :: a
85
83
sanityFailed = error " Sanity check failed! Perhaps you ran the pattern match exhaustiveness checker on an ill-typed program?"
@@ -126,31 +124,31 @@ extrCons (OrPattern _ ps) = concatMap extrCons (toList ps)
126
124
extrCons _ = []
127
125
128
126
-- Is the first column of the pattern matrix complete?
129
- fstComplete :: [[Pattern a ]] -> PatternM ( Complete () )
130
- fstComplete ps = {-# SCC "fstComplete" #-}
127
+ fstComplete :: PatternEnv -> [[Pattern a ]] -> Complete ()
128
+ fstComplete env ps = {-# SCC "fstComplete" #-}
131
129
if maxTupleLength > 0
132
- then pure $ CompleteTuple maxTupleLength
130
+ then CompleteTuple maxTupleLength
133
131
else maybe NotComplete CompleteTags
134
- <$> isCompleteSet (concatMap extrCons fstColumn)
132
+ $ isCompleteSet env (concatMap extrCons fstColumn)
135
133
where fstColumn = fmap head ps
136
134
tuple (PatternTuple _ ps') = length ps'
137
135
tuple (OrPattern _ ps') = maximum (tuple <$> ps')
138
136
tuple _ = 0
139
137
maxTupleLength = maximum (tuple <$> fstColumn)
140
138
141
139
-- follows maranget paper
142
- usefulMaranget :: [[Pattern a ]] -> [Pattern a ] -> PatternM Bool
143
- usefulMaranget [] _ = pure True
144
- usefulMaranget _ [] = pure False
145
- usefulMaranget ps (PatternCons _ c: qs) = usefulMaranget (specializeTag c ps) qs
146
- usefulMaranget ps (PatternTuple _ ps': qs) = usefulMaranget (specializeTuple (length ps') ps) (toList ps' ++ qs)
147
- usefulMaranget ps (OrPattern _ ps': qs) = forAnyA ps' $ \ p -> usefulMaranget ps (p: qs)
148
- usefulMaranget ps (q: qs) = do -- var or wildcard
149
- cont <- fstComplete ps
140
+ usefulMaranget :: PatternEnv -> [[Pattern a ]] -> [Pattern a ] -> Bool
141
+ usefulMaranget _ [] _ = True
142
+ usefulMaranget _ _ [] = False
143
+ usefulMaranget env ps (PatternCons _ c: qs) = usefulMaranget env (specializeTag c ps) qs
144
+ usefulMaranget env ps (PatternTuple _ ps': qs) = usefulMaranget env (specializeTuple (length ps') ps) (toList ps' ++ qs)
145
+ usefulMaranget env ps (OrPattern _ ps': qs) = any ( \ p -> usefulMaranget env ps (p: qs)) ps'
146
+ usefulMaranget env ps (q: qs) = -- var or wildcard
147
+ let cont = fstComplete env ps in
150
148
case cont of
151
- NotComplete -> usefulMaranget (defaultMatrix ps) qs
152
- CompleteTuple n -> usefulMaranget (specializeTuple n ps) (specializeTupleVector n q qs)
153
- CompleteTags ns -> or <$> forM ns (\ n -> usefulMaranget (specializeTag n (forget ps)) (fmap void qs))
149
+ NotComplete -> usefulMaranget env (defaultMatrix ps) qs
150
+ CompleteTuple n -> usefulMaranget env (specializeTuple n ps) (specializeTupleVector n q qs)
151
+ CompleteTags ns -> or $ fmap (\ n -> usefulMaranget env (specializeTag n (forget ps)) (fmap void qs)) ns
154
152
155
153
specializeTupleVector :: Int -> Pattern a -> [Pattern a ] -> [Pattern a ]
156
154
specializeTupleVector n p ps = {-# SCC "specializeTupleVector" #-} replicate n p ++ ps
0 commit comments