1{-# OPTIONS_GHC -Wall #-}
2module Type.Constrain.Pattern
10import Control.Arrow (second)
11import Control.Monad (foldM)
12import qualified Data.Map.Strict as Map
14import qualified AST.Canonical as Can
15import qualified AST.Module.Name as ModuleName
16import qualified Data.Index as Index
17import qualified Elm.Name as N
18import qualified Reporting.Annotation as A
19import qualified Reporting.Error.Type as E
20import qualified Reporting.Region as R
21import qualified Type.Instantiate as Instantiate
26-- ACTUALLY ADD CONSTRAINTS
29-- The constraints are stored in reverse order so that adding a new
30-- constraint is O(1) and we can reverse it at some later time.
36 , _revCons :: [Constraint]
40type Header = Map.Map N.Name (A.Located Type)
43add :: Can.Pattern -> E.PExpected Type -> State -> IO State
44add (A.At region pattern) expectation state =
50 return $ addToHeaders region name expectation state
52 Can.PAlias realPattern name ->
53 add realPattern expectation $
54 addToHeaders region name expectation state
57 do let (State headers vars revCons) = state
58 let unitCon = CPattern region E.PUnit UnitN expectation
59 return $ State headers vars (unitCon:revCons)
61 Can.PTuple a b maybeC ->
62 addTuple region a b maybeC expectation state
64 Can.PCtor home typeName (Can.Union typeVars _ _ _) ctorName _ args ->
65 addCtor region home typeName typeVars ctorName args expectation state
68 do entryVar <- mkFlexVar
69 let entryType = VarN entryVar
70 let listType = AppN ModuleName.list N.list [entryType]
72 (State headers vars revCons) <-
73 foldM (addEntry region entryType) state (Index.indexedMap (,) patterns)
75 let listCon = CPattern region E.PList listType expectation
76 return $ State headers (entryVar:vars) (listCon:revCons)
78 Can.PCons headPattern tailPattern ->
79 do entryVar <- mkFlexVar
80 let entryType = VarN entryVar
81 let listType = AppN ModuleName.list N.list [entryType]
83 let headExpectation = E.PNoExpectation entryType
84 let tailExpectation = E.PFromContext region E.PTail listType
86 (State headers vars revCons) <-
87 add headPattern headExpectation =<<
88 add tailPattern tailExpectation state
90 let listCon = CPattern region E.PList listType expectation
91 return $ State headers (entryVar:vars) (listCon : revCons)
94 do extVar <- mkFlexVar
95 let extType = VarN extVar
97 fieldVars <- traverse (\field -> (,) field <$> mkFlexVar) fields
98 let fieldTypes = Map.fromList (map (fmap VarN) fieldVars)
99 let recordType = RecordN fieldTypes extType
101 let (State headers vars revCons) = state
102 let recordCon = CPattern region E.PRecord recordType expectation
105 { _headers = Map.union headers (Map.map (A.At region) fieldTypes)
106 , _vars = map snd fieldVars ++ extVar : vars
107 , _revCons = recordCon : revCons
111 do let (State headers vars revCons) = state
112 let intCon = CPattern region E.PInt T.int expectation
113 return $ State headers vars (intCon:revCons)
116 do let (State headers vars revCons) = state
117 let strCon = CPattern region E.PStr T.string expectation
118 return $ State headers vars (strCon:revCons)
121 do let (State headers vars revCons) = state
122 let chrCon = CPattern region E.PChr T.char expectation
123 return $ State headers vars (chrCon:revCons)
126 do let (State headers vars revCons) = state
127 let boolCon = CPattern region E.PBool T.bool expectation
128 return $ State headers vars (boolCon:revCons)
135{-# NOINLINE emptyState #-}
138 State Map.empty [] []
141addToHeaders :: R.Region -> N.Name -> E.PExpected Type -> State -> State
142addToHeaders region name expectation (State headers vars revCons) =
144 tipe = getType expectation
145 newHeaders = Map.insert name (A.At region tipe) headers
147 State newHeaders vars revCons
150getType :: E.PExpected Type -> Type
153 E.PNoExpectation tipe -> tipe
154 E.PFromContext _ _ tipe -> tipe
161addEntry :: R.Region -> Type -> State -> (Index.ZeroBased, Can.Pattern) -> IO State
162addEntry listRegion tipe state (index, pattern) =
165 E.PFromContext listRegion (E.PListEntry index) tipe
167 add pattern expectation state
174addTuple :: R.Region -> Can.Pattern -> Can.Pattern -> Maybe Can.Pattern -> E.PExpected Type -> State -> IO State
175addTuple region a b maybeC expectation state =
178 let aType = VarN aVar
179 let bType = VarN bVar
183 do (State headers vars revCons) <-
184 simpleAdd b bType =<<
185 simpleAdd a aType state
187 let tupleCon = CPattern region E.PTuple (TupleN aType bType Nothing) expectation
189 return $ State headers (aVar:bVar:vars) (tupleCon:revCons)
193 let cType = VarN cVar
195 (State headers vars revCons) <-
196 simpleAdd c cType =<<
197 simpleAdd b bType =<<
198 simpleAdd a aType state
200 let tupleCon = CPattern region E.PTuple (TupleN aType bType (Just cType)) expectation
202 return $ State headers (aVar:bVar:cVar:vars) (tupleCon:revCons)
205simpleAdd :: Can.Pattern -> Type -> State -> IO State
206simpleAdd pattern patternType state =
207 add pattern (E.PNoExpectation patternType) state
211-- CONSTRAIN CONSTRUCTORS
214addCtor :: R.Region -> ModuleName.Canonical -> N.Name -> [N.Name] -> N.Name -> [Can.PatternCtorArg] -> E.PExpected Type -> State -> IO State
215addCtor region home typeName typeVarNames ctorName args expectation state =
216 do varPairs <- traverse (\var -> (,) var <$> nameToFlex var) typeVarNames
217 let typePairs = map (second VarN) varPairs
218 let freeVarDict = Map.fromList typePairs
220 (State headers vars revCons) <-
221 foldM (addCtorArg region ctorName freeVarDict) state args
223 let ctorType = AppN home typeName (map snd typePairs)
224 let ctorCon = CPattern region (E.PCtor ctorName) ctorType expectation
229 , _vars = map snd varPairs ++ vars
230 , _revCons = ctorCon : revCons
234addCtorArg :: R.Region -> N.Name -> Map.Map N.Name Type -> State -> Can.PatternCtorArg -> IO State
235addCtorArg region ctorName freeVarDict state (Can.PatternCtorArg index srcType pattern) =
236 do tipe <- Instantiate.fromSrcType freeVarDict srcType
237 let expectation = E.PFromContext region (E.PCtorArg ctorName index) tipe
238 add pattern expectation state
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