1{-# OPTIONS_GHC -Wall #-}
25import Control.Monad (liftM2)
26import Control.Monad.Trans (MonadIO, liftIO)
27import qualified Data.Map as Map
29import Data.Text (Text)
30import qualified Data.UnionFind.IO as UF
32import qualified Reporting.Annotation as A
33import qualified Reporting.Error.Type as Error
34import qualified Reporting.Region as R
43 Solver { _solve :: State -> IO (a, State) }
50run :: Solver () -> IO State
52 do (_, state) <- solver initialState
60 , sSavedEnv = Map.empty
61 , sPool = Pool outermostRank []
62 , sMark = noMark + 1 -- The mark must never be equal to noMark!
77 , sError :: [A.Located Error.Error]
81{-| A pool holds a bunch of variables
82The rank of each variable is less than or equal to the pool's "maxRank"
83The young pool exists to make it possible to identify these vars in constant time.
88 , _inhabitants :: [Variable]
92type Env = Map.Map Text (A.Located Variable)
99{-# INLINE modifyEnv #-}
100modifyEnv :: (Env -> Env) -> Solver ()
103 return ( (), state { sEnv = f (sEnv state) } )
106{-# INLINE modifyPool #-}
107modifyPool :: (Pool -> Pool) -> Solver ()
110 return ( (), state { sPool = f (sPool state) } )
113{-# INLINE addError #-}
114addError :: R.Region -> Error.Error -> Solver ()
117 return ( (), state { sError = A.A region err : sError state } )
120{-# INLINE switchToPool #-}
121switchToPool :: Pool -> Solver ()
123 modifyPool (\_ -> pool)
126{-# INLINE getPool #-}
127getPool :: Solver Pool
130 return ( sPool state, state )
137 return ( sEnv state, state )
140{-# INLINE saveLocalEnv #-}
141saveLocalEnv :: Solver ()
144 return ( (), state { sSavedEnv = sEnv state } )
147{-# INLINE uniqueMark #-}
148uniqueMark :: Solver Int
155 return ( mark, state { sMark = mark + 1 } )
158{-# INLINE nextRankPool #-}
159nextRankPool :: Solver Pool
166 return ( Pool (maxRank + 1) [], state )
173{-# INLINE register #-}
174register :: Variable -> Solver Variable
176 {-# SCC elm_compiler_type_register #-}
179 (Pool maxRank inhabitants) =
182 return ( variable, state { sPool = Pool maxRank (variable : inhabitants) } )
185{-# INLINE introduce #-}
186introduce :: Variable -> Solver Variable
188 {-# SCC elm_compiler_type_introduce #-}
191 (Pool maxRank inhabitants) =
194 do UF.modifyDescriptor variable (\desc -> desc { _rank = maxRank })
195 return ( variable, state { sPool = Pool maxRank (variable : inhabitants) } )
202flatten :: Type -> Solver Variable
204 {-# SCC elm_compiler_type_flatten #-}
205 flattenHelp Map.empty term
208flattenHelp :: Map.Map Text Variable -> Type -> Solver Variable
209flattenHelp aliasDict termN =
212 return (aliasDict ! name)
214 AliasN name args realType ->
215 do flatArgs <- mapM (traverse (flattenHelp aliasDict)) args
216 flatVar <- flattenHelp (Map.fromList flatArgs) realType
219 liftIO $ UF.fresh $ Descriptor
220 { _content = Alias name flatArgs flatVar
221 , _rank = _maxRank pool
231 do variableTerm <- traverseTerm (flattenHelp aliasDict) term1
234 liftIO $ UF.fresh $ Descriptor
235 { _content = Structure variableTerm
236 , _rank = _maxRank pool
247makeInstance :: Variable -> Solver Variable
249 do alreadyCopiedMark <- uniqueMark
250 freshVar <- makeCopy alreadyCopiedMark var
251 _ <- restore alreadyCopiedMark var
259makeCopy :: Int -> Variable -> Solver Variable
260makeCopy alreadyCopiedMark variable =
261 {-# SCC elm_compiler_type_copy #-}
262 do desc <- liftIO $ UF.descriptor variable
263 makeCopyHelp desc alreadyCopiedMark variable
266makeCopyHelp :: Descriptor -> Int -> Variable -> Solver Variable
267makeCopyHelp (Descriptor content rank mark copy) alreadyCopiedMark variable =
268 if mark == alreadyCopiedMark then
270 Just copiedVariable ->
271 return copiedVariable
275 "Error copying type variable. This should be impossible.\
276 \ Please report this at <https://github.com/elm-lang/elm-compiler/issues>\
277 \ with a <http://sscce.org> and information on your OS, how you installed,\
278 \ and any other configuration information that might be helpful."
280 else if rank /= noRank || not (needsCopy content) then
286 liftIO $ UF.fresh $ Descriptor
287 { _content = content -- place holder!
288 , _rank = _maxRank pool
294 -- Link the original variable to the new variable. This lets us
295 -- avoid making multiple copies of the variable we are instantiating.
297 -- Need to do this before recursively copying the content of
298 -- the variable to avoid looping on cyclic terms.
299 liftIO $ UF.modifyDescriptor variable $ \desc ->
300 desc { _mark = alreadyCopiedMark, _copy = Just newVar }
303 let setContent newContent =
304 liftIO $ UF.modifyDescriptor newVar $ \desc ->
305 desc { _content = newContent }
307 -- Now we recursively copy the content of the variable.
308 -- We have already marked the variable as copied, so we
309 -- will not repeat this work or crawl this variable again.
312 do newTerm <- traverseTerm (makeCopy alreadyCopiedMark) term
313 setContent (Structure newTerm)
318 Var Rigid maybeSuper maybeName ->
319 setContent (Var Flex maybeSuper maybeName)
324 Alias name args realType ->
327 <$> mapM (traverse (makeCopy alreadyCopiedMark)) args
328 <*> makeCopy alreadyCopiedMark realType
337needsCopy :: Content -> Bool
360restore :: Int -> Variable -> Solver Variable
361restore alreadyCopiedMark variable =
362 do desc <- liftIO $ UF.descriptor variable
363 if _mark desc /= alreadyCopiedMark
368 do restoredContent <-
369 restoreContent alreadyCopiedMark (_content desc)
370 liftIO $ UF.setDescriptor variable $ Descriptor
371 { _content = restoredContent
380restoreContent :: Int -> Content -> Solver Content
381restoreContent alreadyCopiedMark content =
383 go = restore alreadyCopiedMark
387 Structure <$> traverseTerm go term
395 Alias name args var ->
397 <$> mapM (traverse go) args
408traverseTerm :: (a -> Solver b) -> Term1 a -> Solver (Term1 b)
412 liftM2 App1 (f a) (f b)
415 liftM2 Fun1 (f a) (f b)
420 Record1 fields ext ->
421 liftM2 Record1 (traverse f fields) (f ext)
428instance Functor Solver where
430 fmap f (Solver solver) =
432 fmap (\(a, s2) -> (f a, s2)) (solver s1)
435instance Applicative Solver where
438 Solver $ \s -> return (a, s)
441 Solver solverFunc <*> Solver solverValue =
443 do (f, s2) <- solverFunc s1
444 (x, s3) <- solverValue s2
448instance Monad Solver where
450 Solver solver >>= k =
452 do (a, s2) <- solver s1
453 (b, s3) <- _solve (k a) s2
458 Solver $ \_ -> fail msg
461instance MonadIO Solver where
462 {-# INLINE liftIO #-}
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