1{-# OPTIONS_GHC -Wall #-}
4import qualified Control.Monad.State as State
6import qualified Data.Map as Map
7import qualified Data.UnionFind.IO as UF
9import qualified Reporting.Annotation as A
10import qualified Reporting.Error.Type as Error
11import qualified Reporting.Region as R
16-- Holds a bunch of variables
17-- The rank of each variable is less than or equal to the pool's "maxRank"
18-- The young pool exists to make it possible to identify these vars in constant time.
22 , inhabitants :: [Variable]
29 { maxRank = outermostRank
34type Env = Map.Map String (A.Located Variable)
37type Solver = State.StateT SolverState IO
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 :: (Env -> Env) -> Solver ()
63 State.modify $ \state -> state { sEnv = f (sEnv state) }
66modifyPool :: (Pool -> Pool) -> Solver ()
68 State.modify $ \state -> state { sPool = f (sPool state) }
71addError :: R.Region -> Error.Error -> Solver ()
73 State.modify $ \state -> state { sError = A.A region err : sError state }
76switchToPool :: Pool -> Solver ()
78 modifyPool (\_ -> pool)
91saveLocalEnv :: Solver ()
93 do currentEnv <- getEnv
94 State.modify $ \state -> state { sSavedEnv = currentEnv }
97uniqueMark :: Solver Int
100 let mark = sMark state
101 State.put $ state { sMark = mark + 1 }
105nextRankPool :: Solver Pool
108 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
111register :: Variable -> Solver Variable
113 do modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
117introduce :: Variable -> Solver Variable
120 State.liftIO $ UF.modifyDescriptor variable (\desc -> desc { _rank = maxRank pool })
124flatten :: Type -> Solver Variable
126 flattenHelp Map.empty term
129flattenHelp :: Map.Map String Variable -> Type -> Solver Variable
130flattenHelp aliasDict termN =
133 return (aliasDict ! name)
135 AliasN name args realType ->
136 do flatArgs <- mapM (traverse (flattenHelp aliasDict)) args
137 flatVar <- flattenHelp (Map.fromList flatArgs) realType
140 State.liftIO . UF.fresh $ Descriptor
141 { _content = Alias name flatArgs flatVar
142 , _rank = maxRank pool
152 do variableTerm <- traverseTerm (flattenHelp aliasDict) term1
155 State.liftIO . UF.fresh $ Descriptor
156 { _content = Structure variableTerm
157 , _rank = maxRank pool
164makeInstance :: Variable -> Solver Variable
166 do alreadyCopiedMark <- uniqueMark
167 freshVar <- makeCopy alreadyCopiedMark var
168 _ <- restore alreadyCopiedMark var
172makeCopy :: Int -> Variable -> Solver Variable
173makeCopy alreadyCopiedMark variable =
174 do desc <- State.liftIO $ UF.descriptor variable
175 makeCopyHelp desc alreadyCopiedMark variable
178makeCopyHelp :: Descriptor -> Int -> Variable -> Solver Variable
179makeCopyHelp descriptor alreadyCopiedMark variable =
180 if _mark descriptor == alreadyCopiedMark then
181 case _copy descriptor of
182 Just copiedVariable ->
183 return copiedVariable
187 "Error copying type variable. This should be impossible." ++
188 " Please report an error to the github repo!"
190 else if _rank descriptor /= noRank || not (needsCopy (_content descriptor)) then
196 State.liftIO $ UF.fresh $ Descriptor
197 { _content = error "will be filled in soon!"
198 , _rank = maxRank pool
204 -- Link the original variable to the new variable. This lets us
205 -- avoid making multiple copies of the variable we are instantiating.
207 -- Need to do this before recursively copying the content of
208 -- the variable to avoid looping on cyclic terms.
209 State.liftIO $ UF.modifyDescriptor variable $ \desc ->
210 desc { _mark = alreadyCopiedMark, _copy = Just newVar }
212 -- Now we recursively copy the content of the variable.
213 -- We have already marked the variable as copied, so we
214 -- will not repeat this work or crawl this variable again.
215 let oldContent = _content descriptor
219 Structure <$> traverseTerm (makeCopy alreadyCopiedMark) term
224 Var Rigid maybeSuper _ ->
225 return (Var Flex maybeSuper Nothing)
230 Alias name args realType ->
232 <$> mapM (traverse (makeCopy alreadyCopiedMark)) args
233 <*> makeCopy alreadyCopiedMark realType
238 State.liftIO $ UF.modifyDescriptor newVar $ \desc ->
239 desc { _content = newContent }
244needsCopy :: Content -> Bool
264restore :: Int -> Variable -> Solver Variable
265restore alreadyCopiedMark variable =
266 do desc <- State.liftIO $ UF.descriptor variable
267 if _mark desc /= alreadyCopiedMark
272 do restoredContent <-
273 restoreContent alreadyCopiedMark (_content desc)
274 State.liftIO $ UF.setDescriptor variable $ Descriptor
275 { _content = restoredContent
284restoreContent :: Int -> Content -> Solver Content
285restoreContent alreadyCopiedMark content =
287 go = restore alreadyCopiedMark
291 Structure <$> traverseTerm go term
299 Alias name args var ->
301 <$> mapM (traverse go) args
312traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
324 Record1 fields ext ->
325 Record1 <$> traverse 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