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
33import Type.Type as Type
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 = Type.nextMark noMark -- 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 Mark
156 Solver $ \(SS env savedEnv pool mark errors) ->
157 return ( mark, SS env savedEnv pool (Type.nextMark mark) 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 ()
186 {-# SCC elm_compiler_type_introduce #-}
187 Solver $ \(SS env savedEnv (Pool maxRank inhabitants) mark errors) ->
188 do let toMaxRank (Descriptor c _ m cp) = Descriptor c maxRank m cp
189 mapM_ (\var -> UF.modifyDescriptor var toMaxRank) variables
190 let newPool = Pool maxRank (variables ++ inhabitants)
191 return ( (), SS env savedEnv newPool mark errors )
198flatten :: Type -> Solver Variable
200 {-# SCC elm_compiler_type_flatten #-}
201 do maxRank <- getMaxRank
202 flattenHelp maxRank Map.empty term
205flattenHelp :: Int -> Map.Map Text Variable -> Type -> Solver Variable
206flattenHelp maxRank aliasDict termN =
209 return (aliasDict ! name)
211 AliasN name args realType ->
212 do flatArgs <- mapM (traverse (flattenHelp maxRank aliasDict)) args
213 flatVar <- flattenHelp maxRank (Map.fromList flatArgs) realType
214 makeFlatType maxRank (Alias name flatArgs flatVar)
220 do flatArgs <- traverse (flattenHelp maxRank aliasDict) args
221 makeFlatType maxRank (Structure (App1 name flatArgs))
224 do flatA <- flattenHelp maxRank aliasDict a
225 flatB <- flattenHelp maxRank aliasDict b
226 makeFlatType maxRank (Structure (Fun1 flatA flatB))
229 makeFlatType maxRank (Structure EmptyRecord1)
231 RecordN fields ext ->
232 do flatFields <- traverse (flattenHelp maxRank aliasDict) fields
233 flatExt <- flattenHelp maxRank aliasDict ext
234 makeFlatType maxRank (Structure (Record1 flatFields flatExt))
237makeFlatType :: Int -> Content -> Solver Variable
238makeFlatType maxRank content =
239 register =<< liftIO (UF.fresh (Descriptor content maxRank noMark Nothing))
246copy :: Variable -> Solver Variable
248 {-# SCC elm_compiler_type_copy #-}
249 do maxRank <- getMaxRank
250 copyVar <- copyHelp maxRank var
255copyHelp :: Int -> Variable -> Solver Variable
256copyHelp maxRank variable =
257 do (Descriptor content rank _mark maybeCopy) <- liftIO $ UF.descriptor variable
259 Just copiedVariable ->
260 return copiedVariable
263 if rank /= noRank then
267 do let mkCopyDesc cont = Descriptor cont maxRank noMark Nothing
268 newVar <- liftIO $ UF.fresh $ mkCopyDesc content
271 -- Link the original variable to the new variable. This lets us
272 -- avoid making multiple copies of the variable we are instantiating.
274 -- Need to do this before recursively copying the content of
275 -- the variable to avoid looping on cyclic terms.
276 liftIO $ UF.setDescriptor variable $
277 Descriptor content rank noMark (Just newVar)
279 -- Now we recursively copy the content of the variable.
280 -- We have already marked the variable as copied, so we
281 -- will not repeat this work or crawl this variable again.
284 do newTerm <- traverseFlatType (copyHelp maxRank) term
285 liftIO $ UF.setDescriptor newVar $ mkCopyDesc (Structure newTerm)
287 Var Rigid maybeSuper maybeName ->
288 liftIO $ UF.setDescriptor newVar $ mkCopyDesc $ Var Flex maybeSuper maybeName
293 Alias name args realType ->
294 do newArgs <- mapM (traverse (copyHelp maxRank)) args
295 newRealType <- copyHelp maxRank realType
296 liftIO $ UF.setDescriptor newVar $ mkCopyDesc (Alias name newArgs newRealType)
308restore :: Variable -> Solver Variable
310 do (Descriptor content _rank _mark maybeCopy) <- liftIO $ UF.descriptor variable
316 do restoredContent <- restoreContent content
317 liftIO $ UF.setDescriptor variable $
318 Descriptor restoredContent noRank noMark Nothing
322restoreContent :: Content -> Solver Content
323restoreContent content =
326 Structure <$> traverseFlatType restore term
331 Alias name args var ->
333 <$> mapM (traverse restore) args
344traverseFlatType :: (Variable -> Solver Variable) -> FlatType -> Solver FlatType
345traverseFlatType f flatType =
348 liftM (App1 name) (traverse f args)
351 liftM2 Fun1 (f a) (f b)
356 Record1 fields ext ->
357 liftM2 Record1 (traverse f fields) (f ext)
364instance Functor Solver where
366 fmap f (Solver solver) =
368 fmap (\(a, s2) -> (f a, s2)) (solver s1)
371instance Applicative Solver where
374 Solver $ \s -> return (a, s)
377 Solver solverFunc <*> Solver solverValue =
379 do (f, s2) <- solverFunc s1
380 (x, s3) <- solverValue s2
384instance Monad Solver where
386 Solver solver >>= k =
388 do (a, s2) <- solver s1
389 (b, s3) <- _solve (k a) s2
394 Solver $ \_ -> fail msg
397instance MonadIO Solver where
398 {-# 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