4import qualified Data.Map as Map
5import qualified Data.List as List
6import qualified Type.Environment as Env
7import qualified Data.UnionFind.IO as UF
8import Control.Monad.State
9import Control.Applicative ((<$>),(<*>), Applicative)
10import qualified Data.Traversable as Traversable
11import Text.PrettyPrint as P
12import SourceSyntax.PrettyPrint
13import SourceSyntax.Location
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]
25emptyPool = Pool { maxRank = outermostRank, inhabitants = [] }
27-- Keeps track of the environment, type variable pool, and a list of errors
28data SolverState = SS {
29 sEnv :: Map.Map String Variable,
30 sSavedEnv :: Map.Map String Variable,
38 sSavedEnv = Map.empty,
40 sMark = noMark + 1, -- The mark must never be equal to noMark!
44modifyEnv f = modify $ \state -> state { sEnv = f (sEnv state) }
45modifyPool f = modify $ \state -> state { sPool = f (sPool state) }
47addError span message t1 t2 =
48 modify $ \state -> state { sErrors = err : sErrors state }
50 err = makeError <$> extraPretty t1 <*> extraPretty t2
52 location = case span of
55 if line p1 == line p2 then " on line " ++ show (line p1)
56 else " between lines " ++ show (line p1) ++ " and " ++ show (line p2)
58 display msg = if null msg then "\n"
59 else "\n" ++ unlines (map (" "++) $ lines msg)
62 NoSpan msg -> display msg
63 Span _ _ msg -> display msg
66 P.vcat [ P.text $ "Type error" ++ location ++ ":"
67 , if null message then empty else P.vcat . map P.text $ lines message
69 , P.text " Expected Type:" <+> pt1
70 , P.text " Actual Type:" <+> pt2 <> P.text "\n"
73switchToPool pool = modifyPool (\_ -> pool)
75getPool :: StateT SolverState IO Pool
76getPool = sPool <$> get
78getEnv :: StateT SolverState IO (Map.Map String Variable)
81saveLocalEnv :: StateT SolverState IO ()
84 modify $ \state -> state { sSavedEnv = env }
86uniqueMark :: StateT SolverState IO Int
89 let mark = sMark state
90 put $ state { sMark = mark + 1 }
93nextRankPool :: StateT SolverState IO Pool
96 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
98register :: Variable -> StateT SolverState IO Variable
100 modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
103introduce :: Variable -> StateT SolverState IO Variable
104introduce variable = do
106 liftIO $ UF.modifyDescriptor variable (\desc -> desc { rank = maxRank pool })
109flatten :: Type -> StateT SolverState IO Variable
114 flatStructure <- traverseTerm flatten t
116 var <- liftIO . UF.fresh $ Descriptor {
117 structure = Just flatStructure,
126makeInstance :: Variable -> StateT SolverState IO Variable
128 alreadyCopied <- uniqueMark
129 freshVar <- makeCopy alreadyCopied var
130 restore alreadyCopied var
133makeCopy :: Int -> Variable -> StateT SolverState IO Variable
134makeCopy alreadyCopied variable = do
135 desc <- liftIO $ UF.descriptor variable
137 () | mark desc == alreadyCopied ->
140 Nothing -> error "This should be impossible."
142 | rank desc /= noRank || flex desc == Constant ->
147 newVar <- liftIO $ UF.fresh $ Descriptor {
151 flex = case flex desc of
155 name = case flex desc of
161 -- Link the original variable to the new variable. This lets us
162 -- avoid making multiple copies of the variable we are instantiating.
164 -- Need to do this before recursively copying the structure of
165 -- the variable to avoid looping on cyclic terms.
166 liftIO $ UF.modifyDescriptor variable $ \desc ->
167 desc { mark = alreadyCopied, copy = Just newVar }
169 -- Now we recursively copy the structure of the variable.
170 -- We have already marked the variable as copied, so we
171 -- will not repeat this work or crawl this variable again.
172 case structure desc of
173 Nothing -> return newVar
175 newTerm <- traverseTerm (makeCopy alreadyCopied) term
176 liftIO $ UF.modifyDescriptor newVar $ \desc ->
177 desc { structure = Just newTerm }
180restore :: Int -> Variable -> StateT SolverState IO Variable
181restore alreadyCopied variable = do
182 desc <- liftIO $ UF.descriptor variable
183 if mark desc /= alreadyCopied
187 Traversable.traverse (traverseTerm (restore alreadyCopied)) (structure desc)
188 liftIO $ UF.modifyDescriptor variable $ \desc ->
189 desc { mark = noMark, rank = noRank, structure = restoredStructure }
192traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
195 App1 a b -> App1 <$> f a <*> f b
196 Fun1 a b -> Fun1 <$> f a <*> f b
197 Var1 x -> Var1 <$> f x
198 EmptyRecord1 -> return EmptyRecord1
199 Record1 fields ext ->
200 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