@@ -1,168 +1,135 @@
11{-# OPTIONS_GHC -Wall #-}
22module Type.Constrain.Pattern
3− ( Info(..)
4− , constrain
3+ ( State(..)
4+ , addConstraints
55 )
66 where
77
88
9+import Control.Arrow (second)
910import Control.Monad (foldM)
1011import qualified Data.Map.Strict as Map
1112
1213import qualified AST.Expression.Canonical as Can
1314import qualified AST.Module.Name as ModuleName
1415import qualified Data.Bag as Bag
16+import qualified Data.Index as Index
1517import qualified Elm.Name as N
1618import qualified Reporting.Annotation as A
1719import qualified Reporting.Error.Type as Error
1820import qualified Reporting.Region as R
1921import Type.Constraint
20−import qualified Type.Constrain.Literal as Literal
2122import qualified Type.Instantiate as Instantiate
22−import Type.Type
23−
24−
25−
26−-- CONSTRAIN PATTERN
27−
28−
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 []
34−
35− return ( headers, Bag.toList vars, CAnd (reverse cons) )
23+import Type.Type as T
3624
3725
3826
3927-- ADD CONSTRAINTS
4028
4129
42−data Info =
43− Info
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.
32+--
33+data State =
34+ State
4435 { _headers :: Map.Map N.Name (A.Located Type)
4536 , _vars :: Bag.Bag Variable
46− , _cons :: [Constraint]
37+ , _revCons :: [Constraint]
4738 }
4839
4940
50−addConstraints :: Error.PatternContext -> Can.Pattern -> Type -> Info -> IO Info
51−addConstraints context (A.A region pattern) tipe info =
41+addConstraints :: R.Region -> Error.PatternContext -> Can.Pattern -> Type -> State -> IO State
42+addConstraints outerRegion context (A.A region pattern) tipe state =
5243 case pattern of
5344 Can.PAnything ->
54− return info
55−
56− Can.PLiteral lit ->
57− do let (Info headers vars revCons) = info
58− litCon <- Literal.constrain region lit tipe
59− return $ Info headers vars (litCon:revCons)
45+ return state
6046
6147 Can.PVar name ->
62− do let (Info headers vars revCons) = info
48+ do let (State headers vars revCons) = state
6349 let newHeaders = Map.insert name (A.A region tipe) headers
64− return $ Info newHeaders vars revCons
50+ return $ State newHeaders vars revCons
6551
6652 Can.PAlias realPattern name ->
67− do let (Info headers vars revCons) = info
68− addConstraints context realPattern tipe $
69− Info (Map.insert name (A.A region tipe) headers) vars revCons
53+ do let (State headers vars revCons) = state
54+ addConstraints outerRegion context realPattern tipe $
55+ State (Map.insert name (A.A region tipe) headers) vars revCons
7056
7157 Can.PUnit ->
72− do let (Info headers vars revCons) = info
73− let unitCon = CEqual (Error.Pattern context Error.PUnit) region UnitN tipe
74− return $ Info headers vars (unitCon:revCons)
58+ do let (State headers vars revCons) = state
59+ let unitCon = CPattern outerRegion context Error.PUnit region UnitN tipe
60+ return $ State headers vars (unitCon:revCons)
7561
7662 Can.PTuple a b maybeC ->
77− addTupleConstraint context region a b maybeC tipe info
63+ addTupleConstraint outerRegion context region a b maybeC tipe state
7864
79− Can.PCtor home typeName vs ctorName args ->
80− do (Instantiate.Ctor tvars targs ttype) <- Instantiate.pattern home typeName vs args
81−
82− (Info headers vars revCons) <-
83− foldM (addCtorConstraint ctorName) info targs
84−
85− return $
86− Info
87− { _headers = headers
88− , _vars = Bag.append vars (Bag.fromList id tvars)
89− , _cons =
90− CEqual (Error.Pattern context (Error.PCtor ctorName)) region ttype tipe
91− : revCons
92− }
65+ Can.PCtor home typeName typeVars ctorName args ->
66+ addCtorConstraint outerRegion context region home typeName typeVars ctorName args tipe state
9367
9468 Can.PList patterns ->
9569 do entryVar <- mkFlexVar
9670 let entryVarN = VarN entryVar
9771 let listType = AppN ModuleName.list N.list [entryVarN]
9872
99− (Info headers vars revCons) <-
100− foldM
101− (addListConstraint entryVarN)
102− info
103− (zip patterns [ 1 .. length patterns ])
73+ (State headers vars revCons) <-
74+ foldM (addListConstraint region entryVarN) state (Index.indexedMap (,) patterns)
10475
105− let listCon = CEqual (Error.Pattern context Error.PList) region listType tipe
106− return $ Info headers (Bag.insert entryVar vars) (listCon:revCons)
76+ let listCon = CPattern outerRegion context Error.PList region listType tipe
77+ return $ State headers (Bag.insert entryVar vars) (listCon:revCons)
10778
10879 Can.PCons headPattern tailPattern ->
109− do headVar <- mkFlexVar
110− tailVar <- mkFlexVar
111− let headVarN = VarN headVar
112− let tailVarN = VarN tailVar
113− let tailType = AppN ModuleName.list N.list [tailVarN]
80+ do entryVar <- mkFlexVar
81+ let entryType = VarN entryVar
82+ let listType = AppN ModuleName.list N.list [entryType]
11483
115− (Info headers vars revCons) <-
116− addConstraints Error.PatternTail tailPattern tailType =<<
117− addConstraints Error.PatternUnknown headPattern headVarN info
84+ (State headers vars revCons) <-
85+ addConstraints region Error.PatternHead headPattern entryType =<<
86+ addConstraints region Error.PatternTail tailPattern listType state
11887
119− return $
120− Info
121− { _headers = headers
122− , _vars = Bag.insert headVar (Bag.insert tailVar vars)
123− , _cons =
124− CEqual (Error.Pattern context Error.PList) region tailType tipe
125− : CEqual Error.PatternCons region headVarN tailVarN
126− : revCons
127− }
88+ let listCon = CPattern outerRegion context Error.PList region listType tipe
89+ return $ State headers (Bag.insert entryVar vars) (listCon : revCons)
12890
12991 Can.PRecord fields ->
13092 do extVar <- mkFlexVar
93+ let extType = VarN extVar
13194
13295 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
13498
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
136101 return $
137− Info
138− { _headers = Map.union headers (Map.map (A.A region) fieldVarN)
102+ State
103+ { _headers = Map.union headers (Map.map (A.A region) fieldTypes)
139104 , _vars = Bag.insert extVar (Bag.append vars (Bag.fromList snd fieldVars))
140− , _cons =
141− CEqual
142− (Error.Pattern context Error.PRecord)
143− region
144− (RecordN fieldVarN (VarN extVar))
145− tipe
146− : revCons
105+ , _revCons = recordCon : revCons
147106 }
148107
108+ Can.PInt _ ->
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)
149112
113+ Can.PStr _ ->
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)
150117
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)
152122
153123
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
157124
158125
159126
160127-- CONSTRAIN LIST
161128
162129
163−addListConstraint :: Type -> Info -> (Can.Pattern, Int) -> IO Info
164−addListConstraint tipe info (pattern, index) =
165− addConstraints (Error.PatternList index) pattern tipe info
130+addListConstraint :: R.Region -> Type -> State -> (Index.ZeroBased, Can.Pattern) -> IO State
131+addListConstraint listRegion tipe state (index, pattern) =
132+ addConstraints listRegion (Error.PatternList index) pattern tipe state
166133
167134
168135
@@ -170,29 +137,30 @@ addListConstraint tipe info (pattern, index) =
170137
171138
172139addTupleConstraint
173− :: Error.PatternContext
140+ :: R.Region
141+ -> Error.PatternContext
174142 -> R.Region
175143 -> Can.Pattern
176144 -> Can.Pattern
177145 -> Maybe Can.Pattern
178146 -> Type
179− -> Info
180− -> IO Info
181−addTupleConstraint context region a b maybeC tipe (Info headers vars revCons) =
182− do let equal = CEqual (Error.Pattern context Error.PTuple) region
183− let addCon = addConstraints Error.PatternUnknown
184−
185− aVar <- mkFlexVar
147+ -> State
148+ -> IO State
149+addTupleConstraint parentRegion context tupleRegion a b maybeC tipe (State headers vars revCons) =
150+ do aVar <- mkFlexVar
186151 bVar <- mkFlexVar
187152 let aVarN = VarN aVar
188153 let bVarN = VarN bVar
189154
155+ let equal = CPattern parentRegion context Error.PTuple tupleRegion
156+ let addCon = addConstraints tupleRegion Error.PatternUnknown
157+
190158 case maybeC of
191159 Nothing ->
192160 do let tupleCon = equal (TupleN aVarN bVarN Nothing) tipe
193161 let newVars = Bag.insert aVar (Bag.insert bVar vars)
194162 addCon b bVarN =<<
195− addCon a aVarN (Info headers newVars (tupleCon:revCons))
163+ addCon a aVarN (State headers newVars (tupleCon:revCons))
196164
197165 Just c ->
198166 do cVar <- mkFlexVar
@@ -201,4 +169,45 @@ addTupleConstraint context region a b maybeC tipe (Info headers vars revCons) =
201169 let newVars = Bag.insert aVar (Bag.insert bVar (Bag.insert cVar vars))
202170 addCon c cVarN =<<
203171 addCon b bVarN =<<
204− addCon a aVarN (Info headers newVars (tupleCon:revCons))
172+ addCon a aVarN (State headers newVars (tupleCon:revCons))
173+
174+
175+
176+-- CONSTRAIN CONSTRUCTORS
177+
178+
179+addCtorConstraint
180+ :: R.Region
181+ -> Error.PatternContext
182+ -> R.Region
183+ -> ModuleName.Canonical
184+ -> N.Name
185+ -> [N.Name]
186+ -> N.Name
187+ -> [Can.PatternCtorArg]
188+ -> Type
189+ -> State
190+ -> IO State
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
195+
196+ (State headers vars revCons) <-
197+ foldM (addCtorArgConstraint ctorRegion ctorName freeVarDict) state args
198+
199+ let ctorType = AppN home typeName (map snd typePairs)
200+ let ctorCon = CPattern outerRegion context (Error.PCtor ctorName) ctorRegion ctorType tipe
201+
202+ return $
203+ State
204+ { _headers = headers
205+ , _vars = Bag.append vars (Bag.fromList snd varPairs)
206+ , _revCons = ctorCon : revCons
207+ }
208+
209+
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