1{-# OPTIONS_GHC -Wall #-}
4import qualified Control.Monad.State as State
5import qualified Data.Map as Map
8import qualified Data.UnionFind.IO as UF
10import qualified Reporting.Annotation as A
11import qualified Reporting.Error.Type as Error
12import qualified Reporting.Region as R
17-- Holds a bunch of variables
18-- The rank of each variable is less than or equal to the pool's "maxRank"
19-- The young pool exists to make it possible to identify these vars in constant time.
24 , inhabitants :: [Variable]
31 { maxRank = outermostRank
36type Env = Map.Map Text (A.Located Variable)
39type Solver = State.StateT SolverState IO
42-- Keeps track of the environment, type variable pool, and a list of errors
49 , sError :: [A.Located Error.Error]
53initialState :: SolverState
57 , sSavedEnv = Map.empty
59 , sMark = noMark + 1 -- The mark must never be equal to noMark!
64modifyEnv :: (Env -> Env) -> Solver ()
66 State.modify $ \state -> state { sEnv = f (sEnv state) }
69modifyPool :: (Pool -> Pool) -> Solver ()
71 State.modify $ \state -> state { sPool = f (sPool state) }
74addError :: R.Region -> Error.Error -> Solver ()
76 State.modify $ \state -> state { sError = A.A region err : sError state }
79switchToPool :: Pool -> Solver ()
81 modifyPool (\_ -> pool)
94saveLocalEnv :: Solver ()
96 do currentEnv <- getEnv
97 State.modify $ \state -> state { sSavedEnv = currentEnv }
100uniqueMark :: Solver Int
102 do state <- State.get
103 let mark = sMark state
104 State.put $ state { sMark = mark + 1 }
108nextRankPool :: Solver Pool
111 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
114register :: Variable -> Solver Variable
116 do modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
120introduce :: Variable -> Solver Variable
123 State.liftIO $ UF.modifyDescriptor variable (\desc -> desc { _rank = maxRank pool })
127flatten :: Type -> Solver Variable
129 flattenHelp Map.empty term
132flattenHelp :: Map.Map Text Variable -> Type -> Solver Variable
133flattenHelp aliasDict termN =
136 return (aliasDict ! name)
138 AliasN name args realType ->
139 do flatArgs <- mapM (traverse (flattenHelp aliasDict)) args
140 flatVar <- flattenHelp (Map.fromList flatArgs) realType
143 State.liftIO . UF.fresh $ Descriptor
144 { _content = Alias name flatArgs flatVar
145 , _rank = maxRank pool
155 do variableTerm <- traverseTerm (flattenHelp aliasDict) term1
158 State.liftIO . UF.fresh $ Descriptor
159 { _content = Structure variableTerm
160 , _rank = maxRank pool
167makeInstance :: Variable -> Solver Variable
169 do alreadyCopiedMark <- uniqueMark
170 freshVar <- makeCopy alreadyCopiedMark var
171 _ <- restore alreadyCopiedMark var
175makeCopy :: Int -> Variable -> Solver Variable
176makeCopy alreadyCopiedMark variable =
177 do desc <- State.liftIO $ UF.descriptor variable
178 makeCopyHelp desc alreadyCopiedMark variable
181makeCopyHelp :: Descriptor -> Int -> Variable -> Solver Variable
182makeCopyHelp descriptor alreadyCopiedMark variable =
183 if _mark descriptor == alreadyCopiedMark then
184 case _copy descriptor of
185 Just copiedVariable ->
186 return copiedVariable
190 "Error copying type variable. This should be impossible.\
191 \ Please report this at <https://github.com/elm-lang/elm-compiler/issues>\
192 \ with a <http://sscce.org> and information on your OS, how you installed,\
193 \ and any other configuration information that might be helpful."
195 else if _rank descriptor /= noRank || not (needsCopy (_content descriptor)) then
201 State.liftIO $ UF.fresh $ Descriptor
202 { _content = error "will be filled in soon!"
203 , _rank = maxRank pool
209 -- Link the original variable to the new variable. This lets us
210 -- avoid making multiple copies of the variable we are instantiating.
212 -- Need to do this before recursively copying the content of
213 -- the variable to avoid looping on cyclic terms.
214 State.liftIO $ UF.modifyDescriptor variable $ \desc ->
215 desc { _mark = alreadyCopiedMark, _copy = Just newVar }
217 -- Now we recursively copy the content of the variable.
218 -- We have already marked the variable as copied, so we
219 -- will not repeat this work or crawl this variable again.
220 let oldContent = _content descriptor
224 Structure <$> traverseTerm (makeCopy alreadyCopiedMark) term
229 Var Rigid maybeSuper maybeName ->
230 return (Var Flex maybeSuper maybeName)
235 Alias name args realType ->
237 <$> mapM (traverse (makeCopy alreadyCopiedMark)) args
238 <*> makeCopy alreadyCopiedMark realType
243 State.liftIO $ UF.modifyDescriptor newVar $ \desc ->
244 desc { _content = newContent }
249needsCopy :: Content -> Bool
269restore :: Int -> Variable -> Solver Variable
270restore alreadyCopiedMark variable =
271 do desc <- State.liftIO $ UF.descriptor variable
272 if _mark desc /= alreadyCopiedMark
277 do restoredContent <-
278 restoreContent alreadyCopiedMark (_content desc)
279 State.liftIO $ UF.setDescriptor variable $ Descriptor
280 { _content = restoredContent
289restoreContent :: Int -> Content -> Solver Content
290restoreContent alreadyCopiedMark content =
292 go = restore alreadyCopiedMark
296 Structure <$> traverseTerm go term
304 Alias name args var ->
306 <$> mapM (traverse go) args
317traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
329 Record1 fields ext ->
330 Record1 <$> traverse f fields <*> f ext
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