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
178 (Pool maxRank inhabitants) =
181 return ( variable, state { sPool = Pool maxRank (variable : inhabitants) } )
184{-# INLINE introduce #-}
185introduce :: Variable -> Solver Variable
189 (Pool maxRank inhabitants) =
192 do UF.modifyDescriptor variable (\desc -> desc { _rank = maxRank })
193 return ( variable, state { sPool = Pool maxRank (variable : inhabitants) } )
200flatten :: Type -> Solver Variable
202 flattenHelp Map.empty term
205flattenHelp :: Map.Map Text Variable -> Type -> Solver Variable
206flattenHelp aliasDict termN =
209 return (aliasDict ! name)
211 AliasN name args realType ->
212 do flatArgs <- mapM (traverse (flattenHelp aliasDict)) args
213 flatVar <- flattenHelp (Map.fromList flatArgs) realType
216 liftIO . UF.fresh $ Descriptor
217 { _content = Alias name flatArgs flatVar
218 , _rank = _maxRank pool
228 do variableTerm <- traverseTerm (flattenHelp aliasDict) term1
231 liftIO . UF.fresh $ Descriptor
232 { _content = Structure variableTerm
233 , _rank = _maxRank pool
244makeInstance :: Variable -> Solver Variable
246 do alreadyCopiedMark <- uniqueMark
247 freshVar <- makeCopy alreadyCopiedMark var
248 _ <- restore alreadyCopiedMark var
256makeCopy :: Int -> Variable -> Solver Variable
257makeCopy alreadyCopiedMark variable =
258 do desc <- liftIO $ UF.descriptor variable
259 makeCopyHelp desc alreadyCopiedMark variable
262makeCopyHelp :: Descriptor -> Int -> Variable -> Solver Variable
263makeCopyHelp (Descriptor content rank mark copy) alreadyCopiedMark variable =
264 if mark == alreadyCopiedMark then
266 Just copiedVariable ->
267 return copiedVariable
271 "Error copying type variable. This should be impossible.\
272 \ Please report this at <https://github.com/elm-lang/elm-compiler/issues>\
273 \ with a <http://sscce.org> and information on your OS, how you installed,\
274 \ and any other configuration information that might be helpful."
276 else if rank /= noRank || not (needsCopy content) then
282 liftIO $ UF.fresh $ Descriptor
283 { _content = content -- place holder!
284 , _rank = _maxRank pool
290 -- Link the original variable to the new variable. This lets us
291 -- avoid making multiple copies of the variable we are instantiating.
293 -- Need to do this before recursively copying the content of
294 -- the variable to avoid looping on cyclic terms.
295 liftIO $ UF.modifyDescriptor variable $ \desc ->
296 desc { _mark = alreadyCopiedMark, _copy = Just newVar }
299 let setContent newContent =
300 liftIO $ UF.modifyDescriptor newVar $ \desc ->
301 desc { _content = newContent }
303 -- Now we recursively copy the content of the variable.
304 -- We have already marked the variable as copied, so we
305 -- will not repeat this work or crawl this variable again.
308 do newTerm <- traverseTerm (makeCopy alreadyCopiedMark) term
309 setContent (Structure newTerm)
314 Var Rigid maybeSuper maybeName ->
315 setContent (Var Flex maybeSuper maybeName)
320 Alias name args realType ->
323 <$> mapM (traverse (makeCopy alreadyCopiedMark)) args
324 <*> makeCopy alreadyCopiedMark realType
333needsCopy :: Content -> Bool
356restore :: Int -> Variable -> Solver Variable
357restore alreadyCopiedMark variable =
358 do desc <- liftIO $ UF.descriptor variable
359 if _mark desc /= alreadyCopiedMark
364 do restoredContent <-
365 restoreContent alreadyCopiedMark (_content desc)
366 liftIO $ UF.setDescriptor variable $ Descriptor
367 { _content = restoredContent
376restoreContent :: Int -> Content -> Solver Content
377restoreContent alreadyCopiedMark content =
379 go = restore alreadyCopiedMark
383 Structure <$> traverseTerm go term
391 Alias name args var ->
393 <$> mapM (traverse go) args
404traverseTerm :: (a -> Solver b) -> Term1 a -> Solver (Term1 b)
408 liftM2 App1 (f a) (f b)
411 liftM2 Fun1 (f a) (f b)
416 Record1 fields ext ->
417 liftM2 Record1 (traverse f fields) (f ext)
424instance Functor Solver where
426 fmap f (Solver solver) = Solver $ \s1 ->
427 fmap (\(a, s2) -> (f a, s2)) (solver s1)
430instance Applicative Solver where
432 pure a = Solver $ \s -> return (a, s)
435 Solver solverFunc <*> Solver solverValue =
437 do (f, s2) <- solverFunc s1
438 (x, s3) <- solverValue s2
442instance Monad Solver where
444 Solver solver >>= k =
446 do (a, s2) <- solver s1
447 (b, s3) <- _solve (k a) s2
452 Solver $ \_ -> fail msg
455instance MonadIO Solver where
456 {-# 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