1{-# LANGUAGE FlexibleContexts #-}
4import Control.Applicative ( (<$>), (<*>), Applicative, (<|>) )
5import Control.Monad.State
6import qualified Data.Map as Map
7import qualified Data.Traversable as Traversable
8import qualified Data.UnionFind.IO as UF
10import qualified Type.Hint as Hint
15-- Holds a bunch of variables
16-- The rank of each variable is less than or equal to the pool's "maxRank"
17-- The young pool exists to make it possible to identify these vars in constant time.
21 , inhabitants :: [Variable]
28 { maxRank = outermostRank
33type Env = Map.Map String Variable
36-- Keeps track of the environment, type variable pool, and a list of errors
42 , sHint :: [Hint.Hint]
46initialState :: SolverState
50 , sSavedEnv = Map.empty
52 , sMark = noMark + 1 -- The mark must never be equal to noMark!
57modifyEnv :: (MonadState SolverState m) => (Env -> Env) -> m ()
59 modify $ \state -> state { sEnv = f (sEnv state) }
62modifyPool :: (MonadState SolverState m) => (Pool -> Pool) -> m ()
64 modify $ \state -> state { sPool = f (sPool state) }
67addHint :: Hint.Hint -> StateT SolverState IO ()
69 modify $ \state -> state { sHint = hint : sHint state }
72switchToPool :: (MonadState SolverState m) => Pool -> m ()
74 modifyPool (\_ -> pool)
77getPool :: StateT SolverState IO Pool
82getEnv :: StateT SolverState IO Env
87saveLocalEnv :: StateT SolverState IO ()
89 do currentEnv <- getEnv
90 modify $ \state -> state { sSavedEnv = currentEnv }
93uniqueMark :: StateT SolverState IO Int
96 let mark = sMark state
97 put $ state { sMark = mark + 1 }
101nextRankPool :: StateT SolverState IO Pool
104 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
107register :: Variable -> StateT SolverState IO Variable
109 do modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
113introduce :: Variable -> StateT SolverState IO Variable
116 liftIO $ UF.modifyDescriptor variable (\desc -> desc { rank = maxRank pool })
120flatten :: Type -> StateT SolverState IO Variable
124 do liftIO $ UF.modifyDescriptor v $ \desc -> desc { alias = maybeAlias <|> alias desc }
127 TermN maybeAlias t ->
128 do flatStructure <- traverseTerm flatten t
130 var <- liftIO . UF.fresh $ Descriptor
131 { structure = Just flatStructure
132 , rank = maxRank pool
142makeInstance :: Variable -> StateT SolverState IO Variable
144 do alreadyCopied <- uniqueMark
145 freshVar <- makeCopy alreadyCopied var
146 restore alreadyCopied var
150makeCopy :: Int -> Variable -> StateT SolverState IO Variable
151makeCopy alreadyCopied variable = do
152 desc <- liftIO $ UF.descriptor variable
154 () | mark desc == alreadyCopied ->
157 Nothing -> error $ "Error copying type variable. This should be impossible." ++
158 " Please report an error to the github repo!"
160 | rank desc /= noRank || flex desc == Constant ->
165 newVar <- liftIO $ UF.fresh $ Descriptor
166 { structure = Nothing
167 , rank = maxRank pool
169 , flex = case flex desc of
173 , name = case flex desc of
180 -- Link the original variable to the new variable. This lets us
181 -- avoid making multiple copies of the variable we are instantiating.
183 -- Need to do this before recursively copying the structure of
184 -- the variable to avoid looping on cyclic terms.
185 liftIO $ UF.modifyDescriptor variable $ \desc ->
186 desc { mark = alreadyCopied, copy = Just newVar }
188 -- Now we recursively copy the structure of the variable.
189 -- We have already marked the variable as copied, so we
190 -- will not repeat this work or crawl this variable again.
191 case structure desc of
192 Nothing -> return newVar
194 newTerm <- traverseTerm (makeCopy alreadyCopied) term
195 liftIO $ UF.modifyDescriptor newVar $ \desc ->
196 desc { structure = Just newTerm }
200restore :: Int -> Variable -> StateT SolverState IO Variable
201restore alreadyCopied variable =
202 do desc <- liftIO $ UF.descriptor variable
203 case mark desc /= alreadyCopied of
204 True -> return variable
206 do restoredStructure <-
207 Traversable.traverse (traverseTerm (restore alreadyCopied)) (structure desc)
208 liftIO $ UF.modifyDescriptor variable $ \desc ->
209 desc { mark = noMark, rank = noRank, structure = restoredStructure }
213traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
216 App1 a b -> App1 <$> f a <*> f b
217 Fun1 a b -> Fun1 <$> f a <*> f b
218 Var1 x -> Var1 <$> f x
219 EmptyRecord1 -> return EmptyRecord1
220 Record1 fields ext ->
221 Record1 <$> Traversable.traverse (mapM f) fields <*> f ext
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