@@ -1,168 +1,135 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2module Type.Constrain.Pattern
2module Type.Constrain.Pattern
3− ( Info(..)
3+ ( State(..)
4− , constrain
4+ , addConstraints
9+import Control.Arrow (second)
9import Control.Monad (foldM)
10import Control.Monad (foldM)
10import qualified Data.Map.Strict as Map
11import qualified Data.Map.Strict as Map
12import qualified AST.Expression.Canonical as Can
13import qualified AST.Expression.Canonical as Can
13import qualified AST.Module.Name as ModuleName
14import qualified AST.Module.Name as ModuleName
14import qualified Data.Bag as Bag
15import qualified Data.Bag as Bag
16+import qualified Data.Index as Index
15import qualified Elm.Name as N
17import qualified Elm.Name as N
16import qualified Reporting.Annotation as A
18import qualified Reporting.Annotation as A
17import qualified Reporting.Error.Type as Error
19import qualified Reporting.Error.Type as Error
18import qualified Reporting.Region as R
20import qualified Reporting.Region as R
19import Type.Constraint
21import Type.Constraint
20−import qualified Type.Constrain.Literal as Literal
21import qualified Type.Instantiate as Instantiate
22import qualified Type.Instantiate as Instantiate
22−import Type.Type
23+import Type.Type as T
29−constrain :: Can.Pattern -> Type -> IO (Map.Map N.Name (A.Located Type), [Variable], Constraint)
30−constrain pattern tipe =
31− do (Info headers vars cons) <-
32− addConstraints Error.PatternUnknown pattern tipe $
33− Info Map.empty Bag.empty []
35− return ( headers, Bag.toList vars, CAnd (reverse cons) )
39-- ADD CONSTRAINTS
27-- ADD CONSTRAINTS
30+-- The constraints are stored in reverse order so that adding a new
31+-- constraint is O(1) and we can reverse it at some later time.
42−data Info =
33+data State =
44 { _headers :: Map.Map N.Name (A.Located Type)
35 { _headers :: Map.Map N.Name (A.Located Type)
45 , _vars :: Bag.Bag Variable
36 , _vars :: Bag.Bag Variable
46− , _cons :: [Constraint]
37+ , _revCons :: [Constraint]
50−addConstraints :: Error.PatternContext -> Can.Pattern -> Type -> Info -> IO Info
41+addConstraints :: R.Region -> Error.PatternContext -> Can.Pattern -> Type -> State -> IO State
51−addConstraints context (A.A region pattern) tipe info =
42+addConstraints outerRegion context (A.A region pattern) tipe state =
52 case pattern of
43 case pattern of
53 Can.PAnything ->
44 Can.PAnything ->
54− return info
45+ return state
57− do let (Info headers vars revCons) = info
58− litCon <- Literal.constrain region lit tipe
59− return $ Info headers vars (litCon:revCons)
61 Can.PVar name ->
47 Can.PVar name ->
62− do let (Info headers vars revCons) = info
48+ do let (State headers vars revCons) = state
63 let newHeaders = Map.insert name (A.A region tipe) headers
49 let newHeaders = Map.insert name (A.A region tipe) headers
64− return $ Info newHeaders vars revCons
50+ return $ State newHeaders vars revCons
66 Can.PAlias realPattern name ->
52 Can.PAlias realPattern name ->
67− do let (Info headers vars revCons) = info
53+ do let (State headers vars revCons) = state
68− addConstraints context realPattern tipe $
54+ addConstraints outerRegion context realPattern tipe $
69− Info (Map.insert name (A.A region tipe) headers) vars revCons
55+ State (Map.insert name (A.A region tipe) headers) vars revCons
71 Can.PUnit ->
57 Can.PUnit ->
72− do let (Info headers vars revCons) = info
58+ do let (State headers vars revCons) = state
73− let unitCon = CEqual (Error.Pattern context Error.PUnit) region UnitN tipe
59+ let unitCon = CPattern outerRegion context Error.PUnit region UnitN tipe
74− return $ Info headers vars (unitCon:revCons)
60+ return $ State headers vars (unitCon:revCons)
76 Can.PTuple a b maybeC ->
62 Can.PTuple a b maybeC ->
77− addTupleConstraint context region a b maybeC tipe info
63+ addTupleConstraint outerRegion context region a b maybeC tipe state
79− Can.PCtor home typeName vs ctorName args ->
65+ Can.PCtor home typeName typeVars ctorName args ->
80− do (Instantiate.Ctor tvars targs ttype) <- Instantiate.pattern home typeName vs args
66+ addCtorConstraint outerRegion context region home typeName typeVars ctorName args tipe state
82− (Info headers vars revCons) <-
83− foldM (addCtorConstraint ctorName) info targs
88− , _vars = Bag.append vars (Bag.fromList id tvars)
90− CEqual (Error.Pattern context (Error.PCtor ctorName)) region ttype tipe
94 Can.PList patterns ->
68 Can.PList patterns ->
95 do entryVar <- mkFlexVar
69 do entryVar <- mkFlexVar
96 let entryVarN = VarN entryVar
70 let entryVarN = VarN entryVar
97 let listType = AppN ModuleName.list N.list [entryVarN]
71 let listType = AppN ModuleName.list N.list [entryVarN]
99− (Info headers vars revCons) <-
73+ (State headers vars revCons) <-
101− (addListConstraint entryVarN)
74+ foldM (addListConstraint region entryVarN) state (Index.indexedMap (,) patterns)
103− (zip patterns [ 1 .. length patterns ])
105− let listCon = CEqual (Error.Pattern context Error.PList) region listType tipe
76+ let listCon = CPattern outerRegion context Error.PList region listType tipe
106− return $ Info headers (Bag.insert entryVar vars) (listCon:revCons)
77+ return $ State headers (Bag.insert entryVar vars) (listCon:revCons)
108 Can.PCons headPattern tailPattern ->
79 Can.PCons headPattern tailPattern ->
109− do headVar <- mkFlexVar
110− tailVar <- mkFlexVar
80+ do entryVar <- mkFlexVar
111− let headVarN = VarN headVar
81+ let entryType = VarN entryVar
112− let tailVarN = VarN tailVar
113− let tailType = AppN ModuleName.list N.list [tailVarN]
82+ let listType = AppN ModuleName.list N.list [entryType]
115− (Info headers vars revCons) <-
84+ (State headers vars revCons) <-
85+ addConstraints region Error.PatternHead headPattern entryType =<<
116− addConstraints Error.PatternTail tailPattern tailType =<<
86+ addConstraints region Error.PatternTail tailPattern listType state
117− addConstraints Error.PatternUnknown headPattern headVarN info
119− return $
88+ let listCon = CPattern outerRegion context Error.PList region listType tipe
120− Info
89+ return $ State headers (Bag.insert entryVar vars) (listCon : revCons)
121− { _headers = headers
122− , _vars = Bag.insert headVar (Bag.insert tailVar vars)
124− CEqual (Error.Pattern context Error.PList) region tailType tipe
125− : CEqual Error.PatternCons region headVarN tailVarN
129 Can.PRecord fields ->
91 Can.PRecord fields ->
130 do extVar <- mkFlexVar
92 do extVar <- mkFlexVar
93+ let extType = VarN extVar
132 fieldVars <- traverse (\field -> (,) field <$> mkFlexVar) fields
95 fieldVars <- traverse (\field -> (,) field <$> mkFlexVar) fields
133− let fieldVarN = Map.fromList (map (fmap VarN) fieldVars)
96+ let fieldTypes = Map.fromList (map (fmap VarN) fieldVars)
97+ let recordType = RecordN fieldTypes extType
135− let (Info headers vars revCons) = info
99+ let (State headers vars revCons) = state
100+ let recordCon = CPattern outerRegion context Error.PRecord region recordType tipe
138− { _headers = Map.union headers (Map.map (A.A region) fieldVarN)
103+ { _headers = Map.union headers (Map.map (A.A region) fieldTypes)
139 , _vars = Bag.insert extVar (Bag.append vars (Bag.fromList snd fieldVars))
104 , _vars = Bag.insert extVar (Bag.append vars (Bag.fromList snd fieldVars))
142− (Error.Pattern context Error.PRecord)
144− (RecordN fieldVarN (VarN extVar))
146− : revCons
105+ , _revCons = recordCon : revCons
109+ do let (State headers vars revCons) = state
110+ let intCon = CPattern outerRegion context Error.PInt region T.int tipe
111+ return $ State headers vars (intCon:revCons)
114+ do let (State headers vars revCons) = state
115+ let strCon = CPattern outerRegion context Error.PStr region T.string tipe
116+ return $ State headers vars (strCon:revCons)
151−-- CONSTRAIN CONSTRUCTORS
118+ Can.PChr _ ->
119+ do let (State headers vars revCons) = state
120+ let chrCon = CPattern outerRegion context Error.PChr region T.char tipe
121+ return $ State headers vars (chrCon:revCons)
154−addCtorConstraint :: N.Name -> Info -> (Int, Type, Can.Pattern) -> IO Info
155−addCtorConstraint name info (index, argType, argPattern) =
156− addConstraints (Error.PatternArg name index) argPattern argType info
160-- CONSTRAIN LIST
127-- CONSTRAIN LIST
163−addListConstraint :: Type -> Info -> (Can.Pattern, Int) -> IO Info
130+addListConstraint :: R.Region -> Type -> State -> (Index.ZeroBased, Can.Pattern) -> IO State
164−addListConstraint tipe info (pattern, index) =
131+addListConstraint listRegion tipe state (index, pattern) =
165− addConstraints (Error.PatternList index) pattern tipe info
132+ addConstraints listRegion (Error.PatternList index) pattern tipe state
@@ -170,29 +137,30 @@ addListConstraint tipe info (pattern, index) =
172addTupleConstraint
139addTupleConstraint
173− :: Error.PatternContext
141+ -> Error.PatternContext
174 -> R.Region
142 -> R.Region
175 -> Can.Pattern
143 -> Can.Pattern
176 -> Can.Pattern
144 -> Can.Pattern
177 -> Maybe Can.Pattern
145 -> Maybe Can.Pattern
179− -> Info
147+ -> State
180− -> IO Info
148+ -> IO State
181−addTupleConstraint context region a b maybeC tipe (Info headers vars revCons) =
149+addTupleConstraint parentRegion context tupleRegion a b maybeC tipe (State headers vars revCons) =
182− do let equal = CEqual (Error.Pattern context Error.PTuple) region
183− let addCon = addConstraints Error.PatternUnknown
185− aVar <- mkFlexVar
150+ do aVar <- mkFlexVar
186 bVar <- mkFlexVar
151 bVar <- mkFlexVar
187 let aVarN = VarN aVar
152 let aVarN = VarN aVar
188 let bVarN = VarN bVar
153 let bVarN = VarN bVar
155+ let equal = CPattern parentRegion context Error.PTuple tupleRegion
156+ let addCon = addConstraints tupleRegion Error.PatternUnknown
190 case maybeC of
158 case maybeC of
191 Nothing ->
159 Nothing ->
192 do let tupleCon = equal (TupleN aVarN bVarN Nothing) tipe
160 do let tupleCon = equal (TupleN aVarN bVarN Nothing) tipe
193 let newVars = Bag.insert aVar (Bag.insert bVar vars)
161 let newVars = Bag.insert aVar (Bag.insert bVar vars)
194 addCon b bVarN =<<
162 addCon b bVarN =<<
195− addCon a aVarN (Info headers newVars (tupleCon:revCons))
163+ addCon a aVarN (State headers newVars (tupleCon:revCons))
197 Just c ->
165 Just c ->
198 do cVar <- mkFlexVar
166 do cVar <- mkFlexVar
@@ -201,4 +169,45 @@ addTupleConstraint context region a b maybeC tipe (Info headers vars revCons) =
201 let newVars = Bag.insert aVar (Bag.insert bVar (Bag.insert cVar vars))
169 let newVars = Bag.insert aVar (Bag.insert bVar (Bag.insert cVar vars))
202 addCon c cVarN =<<
170 addCon c cVarN =<<
203 addCon b bVarN =<<
171 addCon b bVarN =<<
204− addCon a aVarN (Info headers newVars (tupleCon:revCons))
172+ addCon a aVarN (State headers newVars (tupleCon:revCons))
176+-- CONSTRAIN CONSTRUCTORS
181+ -> Error.PatternContext
183+ -> ModuleName.Canonical
187+ -> [Can.PatternCtorArg]
191+addCtorConstraint outerRegion context ctorRegion home typeName typeVarNames ctorName args tipe state =
192+ do varPairs <- traverse (\var -> (,) var <$> nameToFlex var) typeVarNames
193+ let typePairs = map (second VarN) varPairs
194+ let freeVarDict = Map.fromList typePairs
196+ (State headers vars revCons) <-
197+ foldM (addCtorArgConstraint ctorRegion ctorName freeVarDict) state args
199+ let ctorType = AppN home typeName (map snd typePairs)
200+ let ctorCon = CPattern outerRegion context (Error.PCtor ctorName) ctorRegion ctorType tipe
204+ { _headers = headers
205+ , _vars = Bag.append vars (Bag.fromList snd varPairs)
206+ , _revCons = ctorCon : revCons
210+addCtorArgConstraint :: R.Region -> N.Name -> Map.Map N.Name Type -> State -> Can.PatternCtorArg -> IO State
211+addCtorArgConstraint ctorRegion ctorName freeVarDict state (Can.PatternCtorArg index srcType pattern) =
212+ do tipe <- Instantiate.fromSrcType freeVarDict srcType
213+ addConstraints ctorRegion (Error.PatternCtorArg ctorName index) pattern tipe state