1{-# LANGUAGE FlexibleContexts #-}
4import Control.Applicative ( Applicative, (<$>), (<*>), (<|>) )
5import Control.Monad.State
7import qualified Data.Map as Map
8import qualified Data.Traversable as Traversable
9import qualified Data.UnionFind.IO as UF
11import qualified Reporting.Annotation as A
12import qualified Reporting.Error.Type as Error
13import qualified Reporting.Region as R
18-- Holds a bunch of variables
19-- The rank of each variable is less than or equal to the pool's "maxRank"
20-- The young pool exists to make it possible to identify these vars in constant time.
24 , inhabitants :: [Variable]
31 { maxRank = outermostRank
36type Env = Map.Map String (A.Located Variable)
39-- Keeps track of the environment, type variable pool, and a list of errors
45 , sError :: [A.Located Error.Error]
49initialState :: SolverState
53 , sSavedEnv = Map.empty
55 , sMark = noMark + 1 -- The mark must never be equal to noMark!
60modifyEnv :: (MonadState SolverState m) => (Env -> Env) -> m ()
62 modify $ \state -> state { sEnv = f (sEnv state) }
65modifyPool :: (MonadState SolverState m) => (Pool -> Pool) -> m ()
67 modify $ \state -> state { sPool = f (sPool state) }
70addError :: R.Region -> Error.Error -> StateT SolverState IO ()
72 modify $ \state -> state { sError = A.A region err : sError state }
75switchToPool :: (MonadState SolverState m) => Pool -> m ()
77 modifyPool (\_ -> pool)
80getPool :: StateT SolverState IO Pool
85getEnv :: StateT SolverState IO Env
90saveLocalEnv :: StateT SolverState IO ()
92 do currentEnv <- getEnv
93 modify $ \state -> state { sSavedEnv = currentEnv }
96uniqueMark :: StateT SolverState IO Int
99 let mark = sMark state
100 put $ state { sMark = mark + 1 }
104nextRankPool :: StateT SolverState IO Pool
107 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
110register :: Variable -> StateT SolverState IO Variable
112 do modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
116introduce :: Variable -> StateT SolverState IO Variable
119 liftIO $ UF.modifyDescriptor variable (\desc -> desc { rank = maxRank pool })
123flatten :: Type -> StateT SolverState IO Variable
125 flattenHelp Map.empty term
128flattenHelp :: Map.Map String Variable -> Type -> StateT SolverState IO Variable
129flattenHelp aliasDict term =
132 return (aliasDict ! name)
135 do maybeAlias' <- Traversable.traverse flattenAlias maybeAlias
136 liftIO $ UF.modifyDescriptor v $ \desc ->
137 desc { alias = maybeAlias' <|> alias desc }
140 TermN maybeAlias subTerm ->
141 do maybeAlias' <- Traversable.traverse flattenAlias maybeAlias
142 let localDict = maybe aliasDict (Map.fromList . snd) maybeAlias'
143 flatStructure <- traverseTerm (flattenHelp localDict) subTerm
146 liftIO . UF.fresh $ Descriptor
147 { structure = Just flatStructure
148 , rank = maxRank pool
153 , alias = maybeAlias'
157 flattenAlias (name, args) =
158 let flattenPair (arg, subTerm) =
159 (,) arg <$> flattenHelp aliasDict subTerm
161 (,) name <$> mapM flattenPair args
166makeInstance :: Variable -> StateT SolverState IO Variable
168 do alreadyCopied <- uniqueMark
169 freshVar <- makeCopy alreadyCopied var
170 restore alreadyCopied var
174makeCopy :: Int -> Variable -> StateT SolverState IO Variable
175makeCopy alreadyCopied variable = do
176 desc <- liftIO $ UF.descriptor variable
178 () | mark desc == alreadyCopied ->
184 "Error copying type variable. This should be impossible." ++
185 " Please report an error to the github repo!"
187 | rank desc /= noRank || flex desc == Constant ->
193 liftIO $ UF.fresh $ Descriptor
194 { structure = Nothing
195 , rank = maxRank pool
210 -- Link the original variable to the new variable. This lets us
211 -- avoid making multiple copies of the variable we are instantiating.
213 -- Need to do this before recursively copying the structure of
214 -- the variable to avoid looping on cyclic terms.
215 liftIO $ UF.modifyDescriptor variable $ \desc ->
216 desc { mark = alreadyCopied, copy = Just newVar }
218 -- Now we recursively copy the structure of the variable.
219 -- We have already marked the variable as copied, so we
220 -- will not repeat this work or crawl this variable again.
221 case structure desc of
226 do newTerm <- traverseTerm (makeCopy alreadyCopied) term
227 liftIO $ UF.modifyDescriptor newVar $ \desc ->
228 desc { structure = Just newTerm }
232restore :: Int -> Variable -> StateT SolverState IO Variable
233restore alreadyCopied variable =
234 do desc <- liftIO $ UF.descriptor variable
235 case mark desc /= alreadyCopied of
236 True -> return variable
238 do restoredStructure <-
239 Traversable.traverse (traverseTerm (restore alreadyCopied)) (structure desc)
240 liftIO $ UF.modifyDescriptor variable $ \desc ->
241 desc { mark = noMark, rank = noRank, structure = restoredStructure }
245traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
260 Record1 fields ext ->
262 <$> Traversable.traverse (mapM f) fields
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