1{-# OPTIONS_GHC -Wall #-}
4import qualified Control.Monad.State as State
6import qualified Data.Map as Map
7import qualified Data.UnionFind.IO as UF
9import qualified Reporting.Annotation as A
10import qualified Reporting.Error.Type as Error
11import qualified Reporting.Region as R
16-- Holds a bunch of variables
17-- The rank of each variable is less than or equal to the pool's "maxRank"
18-- The young pool exists to make it possible to identify these vars in constant time.
22 , inhabitants :: [Variable]
29 { maxRank = outermostRank
34type Env = Map.Map String (A.Located Variable)
37type Solver = State.StateT SolverState IO
40-- Keeps track of the environment, type variable pool, and a list of errors
46 , sError :: [A.Located Error.Error]
50initialState :: SolverState
54 , sSavedEnv = Map.empty
56 , sMark = noMark + 1 -- The mark must never be equal to noMark!
61modifyEnv :: (Env -> Env) -> Solver ()
63 State.modify $ \state -> state { sEnv = f (sEnv state) }
66modifyPool :: (Pool -> Pool) -> Solver ()
68 State.modify $ \state -> state { sPool = f (sPool state) }
71addError :: R.Region -> Error.Error -> Solver ()
73 State.modify $ \state -> state { sError = A.A region err : sError state }
76switchToPool :: Pool -> Solver ()
78 modifyPool (\_ -> pool)
91saveLocalEnv :: Solver ()
93 do currentEnv <- getEnv
94 State.modify $ \state -> state { sSavedEnv = currentEnv }
97uniqueMark :: Solver Int
100 let mark = sMark state
101 State.put $ state { sMark = mark + 1 }
105nextRankPool :: Solver Pool
108 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
111register :: Variable -> Solver Variable
113 do modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
117introduce :: Variable -> Solver Variable
120 State.liftIO $ UF.modifyDescriptor variable (\desc -> desc { _rank = maxRank pool })
124flatten :: Type -> Solver Variable
126 flattenHelp Map.empty term
129flattenHelp :: Map.Map String Variable -> Type -> Solver Variable
130flattenHelp aliasDict termN =
133 return (aliasDict ! name)
135 AliasN name args realType ->
136 do flatArgs <- mapM (traverse (flattenHelp aliasDict)) args
137 flatVar <- flattenHelp (Map.fromList flatArgs) realType
140 State.liftIO . UF.fresh $ Descriptor
141 { _content = Alias name flatArgs flatVar
142 , _rank = maxRank pool
152 do variableTerm <- traverseTerm (flattenHelp aliasDict) term1
155 State.liftIO . UF.fresh $ Descriptor
156 { _content = Structure variableTerm
157 , _rank = maxRank pool
164makeInstance :: Variable -> Solver Variable
166 do alreadyCopiedMark <- uniqueMark
167 freshVar <- makeCopy alreadyCopiedMark var
168 _ <- restore alreadyCopiedMark var
172makeCopy :: Int -> Variable -> Solver Variable
173makeCopy alreadyCopiedMark variable =
174 do desc <- State.liftIO $ UF.descriptor variable
175 makeCopyHelp desc alreadyCopiedMark variable
178makeCopyHelp :: Descriptor -> Int -> Variable -> Solver Variable
179makeCopyHelp descriptor alreadyCopiedMark variable =
180 if _mark descriptor == alreadyCopiedMark then
181 case _copy descriptor of
182 Just copiedVariable ->
183 return copiedVariable
187 "Error copying type variable. This should be impossible.\
188 \ Please report this at <https://github.com/elm-lang/elm-compiler/issues>\
189 \ with a <http://sscce.org> and information on your OS, how you installed,\
190 \ and any other configuration information that might be helpful."
192 else if _rank descriptor /= noRank || not (needsCopy (_content descriptor)) then
198 State.liftIO $ UF.fresh $ Descriptor
199 { _content = error "will be filled in soon!"
200 , _rank = maxRank pool
206 -- Link the original variable to the new variable. This lets us
207 -- avoid making multiple copies of the variable we are instantiating.
209 -- Need to do this before recursively copying the content of
210 -- the variable to avoid looping on cyclic terms.
211 State.liftIO $ UF.modifyDescriptor variable $ \desc ->
212 desc { _mark = alreadyCopiedMark, _copy = Just newVar }
214 -- Now we recursively copy the content of the variable.
215 -- We have already marked the variable as copied, so we
216 -- will not repeat this work or crawl this variable again.
217 let oldContent = _content descriptor
221 Structure <$> traverseTerm (makeCopy alreadyCopiedMark) term
226 Var Rigid maybeSuper _ ->
227 return (Var Flex maybeSuper Nothing)
232 Alias name args realType ->
234 <$> mapM (traverse (makeCopy alreadyCopiedMark)) args
235 <*> makeCopy alreadyCopiedMark realType
240 State.liftIO $ UF.modifyDescriptor newVar $ \desc ->
241 desc { _content = newContent }
246needsCopy :: Content -> Bool
266restore :: Int -> Variable -> Solver Variable
267restore alreadyCopiedMark variable =
268 do desc <- State.liftIO $ UF.descriptor variable
269 if _mark desc /= alreadyCopiedMark
274 do restoredContent <-
275 restoreContent alreadyCopiedMark (_content desc)
276 State.liftIO $ UF.setDescriptor variable $ Descriptor
277 { _content = restoredContent
286restoreContent :: Int -> Content -> Solver Content
287restoreContent alreadyCopiedMark content =
289 go = restore alreadyCopiedMark
293 Structure <$> traverseTerm go term
301 Alias name args var ->
303 <$> mapM (traverse go) args
314traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
326 Record1 fields ext ->
327 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