1{-# OPTIONS_GHC -Wall #-}
24import qualified Control.Monad.State as State
25import qualified Data.Map as Map
27import Data.Text (Text)
28import qualified Data.UnionFind.IO as UF
30import qualified Reporting.Annotation as A
31import qualified Reporting.Error.Type as Error
32import qualified Reporting.Region as R
39type Solver = State.StateT SolverState IO
42run :: Solver () -> IO SolverState
44 State.execStateT solver $
47 , sSavedEnv = Map.empty
48 , sPool = Pool outermostRank []
49 , sMark = noMark + 1 -- The mark must never be equal to noMark!
64 , sError :: [A.Located Error.Error]
68{-| A pool holds a bunch of variables
69The rank of each variable is less than or equal to the pool's "maxRank"
70The young pool exists to make it possible to identify these vars in constant time.
75 , inhabitants :: [Variable]
79type Env = Map.Map Text (A.Located Variable)
86modifyEnv :: (Env -> Env) -> Solver ()
88 State.modify $ \state -> state { sEnv = f (sEnv state) }
91modifyPool :: (Pool -> Pool) -> Solver ()
93 State.modify $ \state -> state { sPool = f (sPool state) }
96addError :: R.Region -> Error.Error -> Solver ()
98 State.modify $ \state -> state { sError = A.A region err : sError state }
101switchToPool :: Pool -> Solver ()
103 modifyPool (\_ -> pool)
106getPool :: Solver Pool
116saveLocalEnv :: Solver ()
118 do currentEnv <- getEnv
119 State.modify $ \state -> state { sSavedEnv = currentEnv }
122uniqueMark :: Solver Int
124 do state <- State.get
125 let mark = sMark state
126 State.put $ state { sMark = mark + 1 }
130nextRankPool :: Solver Pool
133 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
136register :: Variable -> Solver Variable
138 do modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
142introduce :: Variable -> Solver Variable
145 State.liftIO $ UF.modifyDescriptor variable (\desc -> desc { _rank = maxRank pool })
149flatten :: Type -> Solver Variable
151 flattenHelp Map.empty term
154flattenHelp :: Map.Map Text Variable -> Type -> Solver Variable
155flattenHelp aliasDict termN =
158 return (aliasDict ! name)
160 AliasN name args realType ->
161 do flatArgs <- mapM (traverse (flattenHelp aliasDict)) args
162 flatVar <- flattenHelp (Map.fromList flatArgs) realType
165 State.liftIO . UF.fresh $ Descriptor
166 { _content = Alias name flatArgs flatVar
167 , _rank = maxRank pool
177 do variableTerm <- traverseTerm (flattenHelp aliasDict) term1
180 State.liftIO . UF.fresh $ Descriptor
181 { _content = Structure variableTerm
182 , _rank = maxRank pool
189makeInstance :: Variable -> Solver Variable
191 do alreadyCopiedMark <- uniqueMark
192 freshVar <- makeCopy alreadyCopiedMark var
193 _ <- restore alreadyCopiedMark var
197makeCopy :: Int -> Variable -> Solver Variable
198makeCopy alreadyCopiedMark variable =
199 do desc <- State.liftIO $ UF.descriptor variable
200 makeCopyHelp desc alreadyCopiedMark variable
203makeCopyHelp :: Descriptor -> Int -> Variable -> Solver Variable
204makeCopyHelp (Descriptor content rank mark copy) alreadyCopiedMark variable =
205 if mark == alreadyCopiedMark then
207 Just copiedVariable ->
208 return copiedVariable
212 "Error copying type variable. This should be impossible.\
213 \ Please report this at <https://github.com/elm-lang/elm-compiler/issues>\
214 \ with a <http://sscce.org> and information on your OS, how you installed,\
215 \ and any other configuration information that might be helpful."
217 else if rank /= noRank || not (needsCopy content) then
223 State.liftIO $ UF.fresh $ Descriptor
224 { _content = content -- place holder!
225 , _rank = maxRank pool
231 -- Link the original variable to the new variable. This lets us
232 -- avoid making multiple copies of the variable we are instantiating.
234 -- Need to do this before recursively copying the content of
235 -- the variable to avoid looping on cyclic terms.
236 State.liftIO $ UF.modifyDescriptor variable $ \desc ->
237 desc { _mark = alreadyCopiedMark, _copy = Just newVar }
240 let setContent newContent =
241 State.liftIO $ UF.modifyDescriptor newVar $ \desc ->
242 desc { _content = newContent }
244 -- Now we recursively copy the content of the variable.
245 -- We have already marked the variable as copied, so we
246 -- will not repeat this work or crawl this variable again.
249 do newTerm <- traverseTerm (makeCopy alreadyCopiedMark) term
250 setContent (Structure newTerm)
255 Var Rigid maybeSuper maybeName ->
256 setContent (Var Flex maybeSuper maybeName)
261 Alias name args realType ->
264 <$> mapM (traverse (makeCopy alreadyCopiedMark)) args
265 <*> makeCopy alreadyCopiedMark realType
274needsCopy :: Content -> Bool
294restore :: Int -> Variable -> Solver Variable
295restore alreadyCopiedMark variable =
296 do desc <- State.liftIO $ UF.descriptor variable
297 if _mark desc /= alreadyCopiedMark
302 do restoredContent <-
303 restoreContent alreadyCopiedMark (_content desc)
304 State.liftIO $ UF.setDescriptor variable $ Descriptor
305 { _content = restoredContent
314restoreContent :: Int -> Content -> Solver Content
315restoreContent alreadyCopiedMark content =
317 go = restore alreadyCopiedMark
321 Structure <$> traverseTerm go term
329 Alias name args var ->
331 <$> mapM (traverse go) args
342traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
354 Record1 fields ext ->
355 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