1{-# OPTIONS_GHC -Wall #-}
2module Type.Constrain.Pattern
10import Control.Arrow (second)
11import Control.Monad (foldM)
12import qualified Data.Map.Strict as Map
13import qualified Data.Name as Name
15import qualified AST.Canonical as Can
16import qualified Data.Index as Index
17import qualified Elm.ModuleName as ModuleName
18import qualified Reporting.Annotation as A
19import qualified Reporting.Error.Type as E
20import qualified Type.Instantiate as Instantiate
25-- ACTUALLY ADD CONSTRAINTS
28-- The constraints are stored in reverse order so that adding a new
29-- constraint is O(1) and we can reverse it at some later time.
35 , _revCons :: [Constraint]
39type Header = Map.Map Name.Name (A.Located Type)
42add :: Can.Pattern -> E.PExpected Type -> State -> IO State
43add (A.At region pattern) expectation state =
49 return $ addToHeaders region name expectation state
51 Can.PAlias realPattern name ->
52 add realPattern expectation $
53 addToHeaders region name expectation state
56 do let (State headers vars revCons) = state
57 let unitCon = CPattern region E.PUnit UnitN expectation
58 return $ State headers vars (unitCon:revCons)
60 Can.PTuple a b maybeC ->
61 addTuple region a b maybeC expectation state
63 Can.PCtor home typeName (Can.Union typeVars _ _ _) ctorName _ args ->
64 addCtor region home typeName typeVars ctorName args expectation state
67 do entryVar <- mkFlexVar
68 let entryType = VarN entryVar
69 let listType = AppN ModuleName.list Name.list [entryType]
71 (State headers vars revCons) <-
72 foldM (addEntry region entryType) state (Index.indexedMap (,) patterns)
74 let listCon = CPattern region E.PList listType expectation
75 return $ State headers (entryVar:vars) (listCon:revCons)
77 Can.PCons headPattern tailPattern ->
78 do entryVar <- mkFlexVar
79 let entryType = VarN entryVar
80 let listType = AppN ModuleName.list Name.list [entryType]
82 let headExpectation = E.PNoExpectation entryType
83 let tailExpectation = E.PFromContext region E.PTail listType
85 (State headers vars revCons) <-
86 add headPattern headExpectation =<<
87 add tailPattern tailExpectation state
89 let listCon = CPattern region E.PList listType expectation
90 return $ State headers (entryVar:vars) (listCon : revCons)
93 do extVar <- mkFlexVar
94 let extType = VarN extVar
96 fieldVars <- traverse (\field -> (,) field <$> mkFlexVar) fields
97 let fieldTypes = Map.fromList (map (fmap VarN) fieldVars)
98 let recordType = RecordN fieldTypes extType
100 let (State headers vars revCons) = state
101 let recordCon = CPattern region E.PRecord recordType expectation
104 { _headers = Map.union headers (Map.map (A.At region) fieldTypes)
105 , _vars = map snd fieldVars ++ extVar : vars
106 , _revCons = recordCon : revCons
110 do let (State headers vars revCons) = state
111 let intCon = CPattern region E.PInt T.int expectation
112 return $ State headers vars (intCon:revCons)
115 do let (State headers vars revCons) = state
116 let strCon = CPattern region E.PStr T.string expectation
117 return $ State headers vars (strCon:revCons)
120 do let (State headers vars revCons) = state
121 let chrCon = CPattern region E.PChr T.char expectation
122 return $ State headers vars (chrCon:revCons)
125 do let (State headers vars revCons) = state
126 let boolCon = CPattern region E.PBool T.bool expectation
127 return $ State headers vars (boolCon:revCons)
134{-# NOINLINE emptyState #-}
137 State Map.empty [] []
140addToHeaders :: A.Region -> Name.Name -> E.PExpected Type -> State -> State
141addToHeaders region name expectation (State headers vars revCons) =
143 tipe = getType expectation
144 newHeaders = Map.insert name (A.At region tipe) headers
146 State newHeaders vars revCons
149getType :: E.PExpected Type -> Type
152 E.PNoExpectation tipe -> tipe
153 E.PFromContext _ _ tipe -> tipe
160addEntry :: A.Region -> Type -> State -> (Index.ZeroBased, Can.Pattern) -> IO State
161addEntry listRegion tipe state (index, pattern) =
164 E.PFromContext listRegion (E.PListEntry index) tipe
166 add pattern expectation state
173addTuple :: A.Region -> Can.Pattern -> Can.Pattern -> Maybe Can.Pattern -> E.PExpected Type -> State -> IO State
174addTuple region a b maybeC expectation state =
177 let aType = VarN aVar
178 let bType = VarN bVar
182 do (State headers vars revCons) <-
183 simpleAdd b bType =<<
184 simpleAdd a aType state
186 let tupleCon = CPattern region E.PTuple (TupleN aType bType Nothing) expectation
188 return $ State headers (aVar:bVar:vars) (tupleCon:revCons)
192 let cType = VarN cVar
194 (State headers vars revCons) <-
195 simpleAdd c cType =<<
196 simpleAdd b bType =<<
197 simpleAdd a aType state
199 let tupleCon = CPattern region E.PTuple (TupleN aType bType (Just cType)) expectation
201 return $ State headers (aVar:bVar:cVar:vars) (tupleCon:revCons)
204simpleAdd :: Can.Pattern -> Type -> State -> IO State
205simpleAdd pattern patternType state =
206 add pattern (E.PNoExpectation patternType) state
210-- CONSTRAIN CONSTRUCTORS
213addCtor :: A.Region -> ModuleName.Canonical -> Name.Name -> [Name.Name] -> Name.Name -> [Can.PatternCtorArg] -> E.PExpected Type -> State -> IO State
214addCtor region home typeName typeVarNames ctorName args expectation state =
215 do varPairs <- traverse (\var -> (,) var <$> nameToFlex var) typeVarNames
216 let typePairs = map (second VarN) varPairs
217 let freeVarDict = Map.fromList typePairs
219 (State headers vars revCons) <-
220 foldM (addCtorArg region ctorName freeVarDict) state args
222 let ctorType = AppN home typeName (map snd typePairs)
223 let ctorCon = CPattern region (E.PCtor ctorName) ctorType expectation
228 , _vars = map snd varPairs ++ vars
229 , _revCons = ctorCon : revCons
233addCtorArg :: A.Region -> Name.Name -> Map.Map Name.Name Type -> State -> Can.PatternCtorArg -> IO State
234addCtorArg region ctorName freeVarDict state (Can.PatternCtorArg index srcType pattern) =
235 do tipe <- Instantiate.fromSrcType freeVarDict srcType
236 let expectation = E.PFromContext region (E.PCtorArg ctorName index) tipe
237 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