1{-# OPTIONS_GHC -Wall #-}
24import Control.Monad (liftM, liftM2)
25import Control.Monad.Trans (MonadIO, liftIO)
26import qualified Data.Map as Map
28import Data.Text (Text)
30import qualified Reporting.Annotation as A
31import qualified Reporting.Error.Type as Error
32import qualified Reporting.Region as R
34import qualified Type.UnionFind as UF
42 Solver { _solve :: State -> IO (a, State) }
49run :: Solver () -> IO State
51 do (_, state) <- solver initialState
59 , sSavedEnv = Map.empty
60 , sPool = Pool outermostRank []
61 , sMark = noMark + 1 -- The mark must never be equal to noMark!
76 , sError :: [A.Located Error.Error]
80{-| A pool holds a bunch of variables
81The rank of each variable is less than or equal to the pool's "maxRank"
82The young pool exists to make it possible to identify these vars in constant time.
87 , _inhabitants :: [Variable]
91type Env = Map.Map Text (A.Located Variable)
98{-# INLINE modifyEnv #-}
99modifyEnv :: (Env -> Env) -> Solver ()
102 return ( (), state { sEnv = f (sEnv state) } )
105{-# INLINE modifyPool #-}
106modifyPool :: (Pool -> Pool) -> Solver ()
109 return ( (), state { sPool = f (sPool state) } )
112{-# INLINE addError #-}
113addError :: R.Region -> Error.Error -> Solver ()
116 return ( (), state { sError = A.A region err : sError state } )
119{-# INLINE switchToPool #-}
120switchToPool :: Pool -> Solver ()
122 modifyPool (\_ -> pool)
125{-# INLINE getPool #-}
126getPool :: Solver Pool
129 return ( sPool state, state )
132{-# INLINE getMaxRank #-}
133getMaxRank :: Solver Int
135 Solver $ \state@(SS _ _ (Pool maxRank _) _ _) ->
136 return ( maxRank, state )
143 return ( sEnv state, state )
146{-# INLINE saveLocalEnv #-}
147saveLocalEnv :: Solver ()
150 return ( (), state { sSavedEnv = sEnv state } )
153{-# INLINE uniqueMark #-}
154uniqueMark :: Solver Int
156 Solver $ \(SS env savedEnv pool mark errors) ->
157 return ( mark, SS env savedEnv pool (mark + 1) errors )
160{-# INLINE nextRankPool #-}
161nextRankPool :: Solver Pool
163 Solver $ \state@(SS _ _ (Pool maxRank _) _ _) ->
164 return ( Pool (maxRank + 1) [], state )
171{-# INLINE register #-}
172register :: Variable -> Solver Variable
174 {-# SCC elm_compiler_type_register #-}
177 (Pool maxRank inhabitants) =
180 return ( variable, state { sPool = Pool maxRank (variable : inhabitants) } )
183{-# INLINE introduce #-}
184introduce :: Variable -> Solver Variable
186 {-# SCC elm_compiler_type_introduce #-}
187 Solver $ \(SS env savedEnv (Pool maxRank inhabitants) mark errors) ->
188 do UF.modifyDescriptor variable $ \(Descriptor c _ m cp) -> Descriptor c maxRank m cp
189 let newPool = Pool maxRank (variable : inhabitants)
190 return ( variable, SS env savedEnv newPool mark errors )
197flatten :: Type -> Solver Variable
199 {-# SCC elm_compiler_type_flatten #-}
200 do maxRank <- getMaxRank
201 flattenHelp maxRank Map.empty term
204flattenHelp :: Int -> Map.Map Text Variable -> Type -> Solver Variable
205flattenHelp maxRank aliasDict termN =
208 return (aliasDict ! name)
210 AliasN name args realType ->
211 do flatArgs <- mapM (traverse (flattenHelp maxRank aliasDict)) args
212 flatVar <- flattenHelp maxRank (Map.fromList flatArgs) realType
213 makeFlatType maxRank (Alias name flatArgs flatVar)
219 do flatArgs <- traverse (flattenHelp maxRank aliasDict) args
220 makeFlatType maxRank (Structure (App1 name flatArgs))
223 do flatA <- flattenHelp maxRank aliasDict a
224 flatB <- flattenHelp maxRank aliasDict b
225 makeFlatType maxRank (Structure (Fun1 flatA flatB))
228 makeFlatType maxRank (Structure EmptyRecord1)
230 RecordN fields ext ->
231 do flatFields <- traverse (flattenHelp maxRank aliasDict) fields
232 flatExt <- flattenHelp maxRank aliasDict ext
233 makeFlatType maxRank (Structure (Record1 flatFields flatExt))
236makeFlatType :: Int -> Content -> Solver Variable
237makeFlatType maxRank content =
238 register =<< liftIO (UF.fresh (Descriptor content maxRank noMark Nothing))
245copy :: Variable -> Solver Variable
247 {-# SCC elm_compiler_type_copy #-}
248 do maxRank <- getMaxRank
249 copyVar <- copyHelp maxRank var
254copyHelp :: Int -> Variable -> Solver Variable
255copyHelp maxRank variable =
256 do (Descriptor content rank _mark maybeCopy) <- liftIO $ UF.descriptor variable
258 Just copiedVariable ->
259 return copiedVariable
262 if rank /= noRank then
266 do let mkCopyDesc cont = Descriptor cont maxRank noMark Nothing
267 newVar <- liftIO $ UF.fresh $ mkCopyDesc content
270 -- Link the original variable to the new variable. This lets us
271 -- avoid making multiple copies of the variable we are instantiating.
273 -- Need to do this before recursively copying the content of
274 -- the variable to avoid looping on cyclic terms.
275 liftIO $ UF.setDescriptor variable $
276 Descriptor content rank noMark (Just newVar)
278 -- Now we recursively copy the content of the variable.
279 -- We have already marked the variable as copied, so we
280 -- will not repeat this work or crawl this variable again.
283 do newTerm <- traverseFlatType (copyHelp maxRank) term
284 liftIO $ UF.setDescriptor newVar $ mkCopyDesc (Structure newTerm)
286 Var Rigid maybeSuper maybeName ->
287 liftIO $ UF.setDescriptor newVar $ mkCopyDesc $ Var Flex maybeSuper maybeName
292 Alias name args realType ->
293 do newArgs <- mapM (traverse (copyHelp maxRank)) args
294 newRealType <- copyHelp maxRank realType
295 liftIO $ UF.setDescriptor newVar $ mkCopyDesc (Alias name newArgs newRealType)
307restore :: Variable -> Solver Variable
309 do (Descriptor content _rank _mark maybeCopy) <- liftIO $ UF.descriptor variable
315 do restoredContent <- restoreContent content
316 liftIO $ UF.setDescriptor variable $
317 Descriptor restoredContent noRank noMark Nothing
321restoreContent :: Content -> Solver Content
322restoreContent content =
325 Structure <$> traverseFlatType restore term
330 Alias name args var ->
332 <$> mapM (traverse restore) args
343traverseFlatType :: (Variable -> Solver Variable) -> FlatType -> Solver FlatType
344traverseFlatType f flatType =
347 liftM (App1 name) (traverse f args)
350 liftM2 Fun1 (f a) (f b)
355 Record1 fields ext ->
356 liftM2 Record1 (traverse f fields) (f ext)
363instance Functor Solver where
365 fmap f (Solver solver) =
367 fmap (\(a, s2) -> (f a, s2)) (solver s1)
370instance Applicative Solver where
373 Solver $ \s -> return (a, s)
376 Solver solverFunc <*> Solver solverValue =
378 do (f, s2) <- solverFunc s1
379 (x, s3) <- solverValue s2
383instance Monad Solver where
385 Solver solver >>= k =
387 do (a, s2) <- solver s1
388 (b, s3) <- _solve (k a) s2
393 Solver $ \_ -> fail msg
396instance MonadIO Solver where
397 {-# 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