1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE MultiParamTypeClasses #-}
5import Control.Applicative ((<|>))
6import Control.Monad.State
8import qualified Data.Map as Map
9import qualified Data.Traversable as Traversable
10import qualified Data.UnionFind.IO as UF
12import qualified Reporting.Annotation as A
13import qualified Reporting.Error.Type as Error
14import qualified Reporting.Region as R
19-- Holds a bunch of variables
20-- The rank of each variable is less than or equal to the pool's "maxRank"
21-- The young pool exists to make it possible to identify these vars in constant time.
25 , inhabitants :: [Variable]
32 { maxRank = outermostRank
37type Env = Map.Map String (A.Located Variable)
40-- Keeps track of the environment, type variable pool, and a list of errors
46 , sError :: [A.Located Error.Error]
50initialState :: SolverState
54 , sSavedEnv = Map.empty
56 , sMark = noMark + 1 -- The mark must never be equal to noMark!
61modifyEnv :: (MonadState SolverState m) => (Env -> Env) -> m ()
63 modify $ \state -> state { sEnv = f (sEnv state) }
66modifyPool :: (MonadState SolverState m) => (Pool -> Pool) -> m ()
68 modify $ \state -> state { sPool = f (sPool state) }
71addError :: R.Region -> Error.Error -> StateT SolverState IO ()
73 modify $ \state -> state { sError = A.A region err : sError state }
76switchToPool :: (MonadState SolverState m) => Pool -> m ()
78 modifyPool (\_ -> pool)
81getPool :: StateT SolverState IO Pool
86getEnv :: StateT SolverState IO Env
91saveLocalEnv :: StateT SolverState IO ()
93 do currentEnv <- getEnv
94 modify $ \state -> state { sSavedEnv = currentEnv }
97uniqueMark :: StateT SolverState IO Int
100 let mark = sMark state
101 put $ state { sMark = mark + 1 }
105nextRankPool :: StateT SolverState IO Pool
108 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
111register :: Variable -> StateT SolverState IO Variable
113 do modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
117introduce :: Variable -> StateT SolverState IO Variable
120 liftIO $ UF.modifyDescriptor variable (\desc -> desc { rank = maxRank pool })
124flatten :: Type -> StateT SolverState IO Variable
126 flattenHelp Map.empty term
129flattenHelp :: Map.Map String Variable -> Type -> StateT SolverState IO Variable
130flattenHelp aliasDict term =
133 return (aliasDict ! name)
136 do maybeAlias' <- Traversable.traverse flattenAlias maybeAlias
137 liftIO $ UF.modifyDescriptor v $ \desc ->
138 desc { alias = maybeAlias' <|> alias desc }
141 TermN maybeAlias subTerm ->
142 do maybeAlias' <- Traversable.traverse flattenAlias maybeAlias
143 let localDict = maybe aliasDict (Map.fromList . snd) maybeAlias'
144 flatStructure <- traverseTerm (flattenHelp localDict) subTerm
147 liftIO . UF.fresh $ Descriptor
148 { structure = Just flatStructure
149 , rank = maxRank pool
154 , alias = maybeAlias'
158 flattenAlias (name, args) =
159 let flattenPair (arg, subTerm) =
160 (,) arg <$> flattenHelp aliasDict subTerm
162 (,) name <$> mapM flattenPair args
167makeInstance :: Variable -> StateT SolverState IO Variable
169 do alreadyCopied <- uniqueMark
170 freshVar <- makeCopy alreadyCopied var
171 restore alreadyCopied var
175makeCopy :: Int -> Variable -> StateT SolverState IO Variable
176makeCopy alreadyCopied variable = do
177 desc <- liftIO $ UF.descriptor variable
179 () | mark desc == alreadyCopied ->
185 "Error copying type variable. This should be impossible." ++
186 " Please report an error to the github repo!"
188 | rank desc /= noRank || flex desc == Constant ->
194 liftIO $ UF.fresh $ Descriptor
195 { structure = Nothing
196 , rank = maxRank pool
211 -- Link the original variable to the new variable. This lets us
212 -- avoid making multiple copies of the variable we are instantiating.
214 -- Need to do this before recursively copying the structure of
215 -- the variable to avoid looping on cyclic terms.
216 liftIO $ UF.modifyDescriptor variable $ \desc ->
217 desc { mark = alreadyCopied, copy = Just newVar }
219 -- Now we recursively copy the structure of the variable.
220 -- We have already marked the variable as copied, so we
221 -- will not repeat this work or crawl this variable again.
222 case structure desc of
227 do newTerm <- traverseTerm (makeCopy alreadyCopied) term
228 liftIO $ UF.modifyDescriptor newVar $ \desc ->
229 desc { structure = Just newTerm }
233restore :: Int -> Variable -> StateT SolverState IO Variable
234restore alreadyCopied variable =
235 do desc <- liftIO $ UF.descriptor variable
236 case mark desc /= alreadyCopied of
237 True -> return variable
239 do restoredStructure <-
240 Traversable.traverse (traverseTerm (restore alreadyCopied)) (structure desc)
241 liftIO $ UF.modifyDescriptor variable $ \desc ->
242 desc { mark = noMark, rank = noRank, structure = restoredStructure }
246traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
261 Record1 fields ext ->
263 <$> 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