1{-# OPTIONS_GHC -Wall #-}
25import Control.Monad (liftM2)
26import Control.Monad.Trans (MonadIO, liftIO)
27import qualified Data.Map as Map
29import Data.Text (Text)
31import qualified Reporting.Annotation as A
32import qualified Reporting.Error.Type as Error
33import qualified Reporting.Region as R
35import qualified Type.UnionFind as UF
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
217 makeFlatType (Alias name flatArgs flatVar)
223 do flatA <- flattenHelp aliasDict a
224 flatB <- flattenHelp aliasDict b
225 makeFlatType (Structure (App1 flatA flatB))
228 do flatA <- flattenHelp aliasDict a
229 flatB <- flattenHelp aliasDict b
230 makeFlatType (Structure (Fun1 flatA flatB))
233 makeFlatType (Structure EmptyRecord1)
235 RecordN fields ext ->
236 do flatFields <- traverse (flattenHelp aliasDict) fields
237 flatExt <- flattenHelp aliasDict ext
238 makeFlatType (Structure (Record1 flatFields flatExt))
241makeFlatType :: Content -> Solver Variable
242makeFlatType content =
244 variable <- liftIO $ UF.fresh $
247 , _rank = _maxRank pool
258makeInstance :: Variable -> Solver Variable
260 do alreadyCopiedMark <- uniqueMark
261 freshVar <- makeCopy alreadyCopiedMark var
262 _ <- restore alreadyCopiedMark var
270makeCopy :: Int -> Variable -> Solver Variable
271makeCopy alreadyCopiedMark variable =
272 {-# SCC elm_compiler_type_copy #-}
273 do desc <- liftIO $ UF.descriptor variable
274 makeCopyHelp desc alreadyCopiedMark variable
277makeCopyHelp :: Descriptor -> Int -> Variable -> Solver Variable
278makeCopyHelp (Descriptor content rank mark copy) alreadyCopiedMark variable =
279 if mark == alreadyCopiedMark then
281 Just copiedVariable ->
282 return copiedVariable
286 "Error copying type variable. This should be impossible.\
287 \ Please report this at <https://github.com/elm-lang/elm-compiler/issues>\
288 \ with a <http://sscce.org> and information on your OS, how you installed,\
289 \ and any other configuration information that might be helpful."
291 else if rank /= noRank || not (needsCopy content) then
297 liftIO $ UF.fresh $ Descriptor
298 { _content = content -- place holder!
299 , _rank = _maxRank pool
305 -- Link the original variable to the new variable. This lets us
306 -- avoid making multiple copies of the variable we are instantiating.
308 -- Need to do this before recursively copying the content of
309 -- the variable to avoid looping on cyclic terms.
310 liftIO $ UF.modifyDescriptor variable $ \desc ->
311 desc { _mark = alreadyCopiedMark, _copy = Just newVar }
314 let setContent newContent =
315 liftIO $ UF.modifyDescriptor newVar $ \desc ->
316 desc { _content = newContent }
318 -- Now we recursively copy the content of the variable.
319 -- We have already marked the variable as copied, so we
320 -- will not repeat this work or crawl this variable again.
323 do newTerm <- traverseFlatType (makeCopy alreadyCopiedMark) term
324 setContent (Structure newTerm)
329 Var Rigid maybeSuper maybeName ->
330 setContent (Var Flex maybeSuper maybeName)
335 Alias name args realType ->
338 <$> mapM (traverse (makeCopy alreadyCopiedMark)) args
339 <*> makeCopy alreadyCopiedMark realType
348needsCopy :: Content -> Bool
371restore :: Int -> Variable -> Solver Variable
372restore alreadyCopiedMark variable =
373 do desc <- liftIO $ UF.descriptor variable
374 if _mark desc /= alreadyCopiedMark
379 do restoredContent <-
380 restoreContent alreadyCopiedMark (_content desc)
381 liftIO $ UF.setDescriptor variable $ Descriptor
382 { _content = restoredContent
391restoreContent :: Int -> Content -> Solver Content
392restoreContent alreadyCopiedMark content =
394 go = restore alreadyCopiedMark
398 Structure <$> traverseFlatType go term
406 Alias name args var ->
408 <$> mapM (traverse go) args
419traverseFlatType :: (Variable -> Solver Variable) -> FlatType -> Solver FlatType
420traverseFlatType f flatType =
423 liftM2 App1 (f a) (f b)
426 liftM2 Fun1 (f a) (f b)
431 Record1 fields ext ->
432 liftM2 Record1 (traverse f fields) (f ext)
439instance Functor Solver where
441 fmap f (Solver solver) =
443 fmap (\(a, s2) -> (f a, s2)) (solver s1)
446instance Applicative Solver where
449 Solver $ \s -> return (a, s)
452 Solver solverFunc <*> Solver solverValue =
454 do (f, s2) <- solverFunc s1
455 (x, s3) <- solverValue s2
459instance Monad Solver where
461 Solver solver >>= k =
463 do (a, s2) <- solver s1
464 (b, s3) <- _solve (k a) s2
469 Solver $ \_ -> fail msg
472instance MonadIO Solver where
473 {-# 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