@@ -3,15 +3,17 @@ module Type.State where
4import Type.Type
4import Type.Type
5import qualified Data.Map as Map
5import qualified Data.Map as Map
6+import qualified Data.List as List
6import qualified Type.Environment as Env
7import qualified Type.Environment as Env
7import qualified Data.UnionFind.IO as UF
8import qualified Data.UnionFind.IO as UF
8import Control.Monad.State
9import Control.Monad.State
9import Control.Applicative ((<$>),(<*>), Applicative)
10import Control.Applicative ((<$>),(<*>), Applicative)
10import qualified Data.Traversable as Traversable
11import qualified Data.Traversable as Traversable
11−
12+import Text.PrettyPrint as P
13import SourceSyntax.PrettyPrint
13import SourceSyntax.PrettyPrint
15+debug e = {-- liftIO e --} return ()
16-- Holds a bunch of variables
18-- Holds a bunch of variables
17-- The rank of each variable is less than or equal to the pool's "maxRank"
19-- The rank of each variable is less than or equal to the pool's "maxRank"
@@ -25,14 +27,23 @@ data Pool = Pool {
25emptyPool = Pool { maxRank = 0, inhabitants = [] }
27emptyPool = Pool { maxRank = 0, inhabitants = [] }
27-- Keeps track of the environment, type variable pool, and a list of errors
29-- Keeps track of the environment, type variable pool, and a list of errors
28−type SolverState = (Map.Map String Variable, Pool, Int, [String])
30+type SolverState = (Map.Map String Variable, Pool, Int, [P.Doc])
30-- The mark must never be equal to noMark!
32-- The mark must never be equal to noMark!
31initialState = (Map.empty, emptyPool, noMark + 1, [])
33initialState = (Map.empty, emptyPool, noMark + 1, [])
33modifyEnv f = modify $ \(env, pool, mark, errors) -> (f env, pool, mark, errors)
35modifyEnv f = modify $ \(env, pool, mark, errors) -> (f env, pool, mark, errors)
34modifyPool f = modify $ \(env, pool, mark, errors) -> (env, f pool, mark, errors)
36modifyPool f = modify $ \(env, pool, mark, errors) -> (env, f pool, mark, errors)
35−addError err = modify $ \(env, pool, mark, errors) -> (env, pool, mark, err:errors)
37+addError message t1 t2 = modify $ \(env, pool, mark, errors) -> (env, pool, mark, err:errors)
39+ msg = P.fsep . map P.text $ words message
40+ width = maximum . map length . lines $ render msg
41+ err = P.vcat [ P.text $ "Type error on line ???"
42+ , P.text (List.replicate width '-')
44+ , P.text " Expected Type:" <+> pretty t1
45+ , P.text " Actual Type:" <+> pretty t2 <> P.text "\n"
37switchToPool pool = modifyPool (\_ -> pool)
48switchToPool pool = modifyPool (\_ -> pool)
@@ -87,23 +98,30 @@ flatten term =
88makeInstance :: Variable -> StateT SolverState IO Variable
99makeInstance :: Variable -> StateT SolverState IO Variable
89makeInstance var = do
100makeInstance var = do
101+-- liftIO $ putStrLn ""
102+-- liftIO $ print $ pretty var
90 alreadyCopied <- uniqueMark
103 alreadyCopied <- uniqueMark
91 freshVar <- makeCopy alreadyCopied var
104 freshVar <- makeCopy alreadyCopied var
92 restore alreadyCopied var
105 restore alreadyCopied var
106+-- liftIO $ print $ pretty freshVar
93 return freshVar
107 return freshVar
95makeCopy :: Int -> Variable -> StateT SolverState IO Variable
109makeCopy :: Int -> Variable -> StateT SolverState IO Variable
96makeCopy alreadyCopied variable = do
110makeCopy alreadyCopied variable = do
111+-- liftIO $ putStr "Copying: "
97 desc <- liftIO $ UF.descriptor variable
112 desc <- liftIO $ UF.descriptor variable
98 if | mark desc == alreadyCopied ->
113 if | mark desc == alreadyCopied ->
114+ do debug $ putStrLn "Already Copied"
99 case copy desc of
115 case copy desc of
100 Just v -> return v
116 Just v -> return v
101 Nothing -> error "This should be impossible."
117 Nothing -> error "This should be impossible."
103− | mark desc /= noRank || flex desc == Constant ->
119+ | rank desc /= noRank || flex desc == Constant ->
120+ do debug $ putStr "did not make a copy: " >> print (mark desc, noRank, flex desc)
104− return variable
121+ return variable
106 | otherwise -> do
123 | otherwise -> do
124+ debug $ print "no problems!"
107 pool <- getPool
125 pool <- getPool
108 newVar <- liftIO $ UF.fresh $ Descriptor {
126 newVar <- liftIO $ UF.fresh $ Descriptor {
109 structure = Nothing,
127 structure = Nothing,
@@ -118,12 +136,17 @@ makeCopy alreadyCopied variable = do
119 register newVar
137 register newVar
121− -- Link the original variable to the new variable
139+ -- Link the original variable to the new variable. This lets us
140+ -- avoid making multiple copies of the variable we are instantiating.
122− -- Need to do this before recursively copying to
142+ -- Need to do this before recursively copying the structure of
123− -- avoid looping on cyclic terms.
143+ -- the variable to avoid looping on cyclic terms.
124 liftIO $ UF.modifyDescriptor variable $ \desc ->
144 liftIO $ UF.modifyDescriptor variable $ \desc ->
125 desc { mark = alreadyCopied, copy = Just newVar }
145 desc { mark = alreadyCopied, copy = Just newVar }
147+ -- Now we recursively copy the structure of the variable.
148+ -- We have already marked the variable as copied, so we
149+ -- will not repeat this work or crawl this variable again.
127 case structure desc of
150 case structure desc of
128 Nothing -> return newVar
151 Nothing -> return newVar
129 Just term -> do
152 Just term -> do
@@ -134,13 +157,19 @@ makeCopy alreadyCopied variable = do
135restore :: Int -> Variable -> StateT SolverState IO Variable
158restore :: Int -> Variable -> StateT SolverState IO Variable
136restore alreadyCopied variable = do
159restore alreadyCopied variable = do
160+ debug $ putStr "Restoring: "
137 desc <- liftIO $ UF.descriptor variable
161 desc <- liftIO $ UF.descriptor variable
138− if mark desc /= alreadyCopied then return variable else do
162+ if mark desc /= alreadyCopied
164+ debug $ putStrLn "not copied, no need to do anything"
167+ debug $ putStrLn "restoring"
139 restoredStructure <-
168 restoredStructure <-
140 case structure desc of
169 case structure desc of
141 Nothing -> return Nothing
170 Nothing -> return Nothing
142 Just term -> Just <$> traverseTerm (restore alreadyCopied) term
171 Just term -> Just <$> traverseTerm (restore alreadyCopied) term
143− liftIO $ UF.modifyDescriptor variable $ \desc ->
172+ debug $ UF.modifyDescriptor variable $ \desc ->
144 desc { mark = noMark, rank = noRank, structure = restoredStructure }
173 desc { mark = noMark, rank = noRank, structure = restoredStructure }
145 return variable
174 return variable