@@ -4,7 +4,6 @@ module Type.Solve where
4import Control.Monad
4import Control.Monad
5import Control.Monad.State
5import Control.Monad.State
6import qualified Data.UnionFind.IO as UF
6import qualified Data.UnionFind.IO as UF
7−import qualified Data.Array.IO as Array
8import qualified Data.Map as Map
7import qualified Data.Map as Map
9import qualified Data.Traversable as Traversable
8import qualified Data.Traversable as Traversable
10import qualified Data.Maybe as Maybe
9import qualified Data.Maybe as Maybe
@@ -13,73 +12,78 @@ import Type.Unify
13import qualified Type.Environment as Env
12import qualified Type.Environment as Env
14import qualified Type.State as TS
13import qualified Type.State as TS
16−register = undefined
15+
17−
16+-- | Every variable has rank less than or equal to the maxRank of the pool.
17+-- This sorts variables into the young and old pools accordingly.
18−generalize :: TS.Pool -> TS.Pool -> IO [Variable]
18+generalize :: TS.Pool -> StateT TS.SolverState IO ()
19−generalize oldPool youngPool = do
19+generalize youngPool = do
22− youngRank = TS.maxRank youngPool
20+ let youngRank = TS.maxRank youngPool
23−
21+ insert dict var = do
24− array' <- Array.newArray (0, youngRank) []
22+ desc <- liftIO $ UF.descriptor var
25− let array = array' :: Array.IOArray Int [Variable]
23+ return $ Map.insertWith (++) (rank desc) [var] dict
27− -- Insert all of the youngPool variables into the array.
25+ -- Sort the youngPool variables by rank.
28− -- They are placed into a list at the index corresponding
30− forM (TS.inhabitants youngPool) $ \var -> do
26+ rankDict <- foldM insert Map.empty (TS.inhabitants youngPool)
31− desc <- UF.descriptor var
27+
32− vars <- Array.readArray array (rank desc)
33− Array.writeArray array (rank desc) (var : vars)
35− -- get the ranks right for each entry
28+ -- get the ranks right for each entry.
36− forM [0 .. youngRank] $ \i -> do
29+ -- start at low ranks so that we only have to pass
37− vars <- Array.readArray array i
30+ -- over the information once.
38− mapM (traverse young visited i) vars
31+ youngMark <- TS.uniqueMark
39−
32+ visitedMark <- TS.uniqueMark
40− -- do not need to work with variables that have become redundant
33+ Traversable.traverse (mapM (adjustRank youngMark visitedMark youngRank)) rankDict
41− vars <- Array.readArray array youngRank
34+
42− forM vars $ \var -> do
35+ -- Move variables out of the young pool if they do not have a young rank.
36+ -- We should not generalize things we cannot use.
37+ let youngVars = (Map.!) rankDict youngRank
39+ registerIfNotRedundant var = do
40+ isRedundant <- liftIO $ UF.redundant var
41+ if isRedundant then return var else TS.register var
43+ registerIfHigherRank var = do
43− isRedundant <- UF.redundant var
44+ isRedundant <- liftIO $ UF.redundant var
44− if isRedundant then do
45+ if isRedundant then return () else do
45− desc <- UF.descriptor var
46+ desc <- liftIO $ UF.descriptor var
46− if rank desc < youngRank
47+ if rank desc < youngRank
47− then register oldPool var
48+ then TS.register var >> return ()
48− else let flex' = if flex desc == Flexible then Rigid else flex desc
49+ else let flex' = if flex desc == Flexible then Rigid else flex desc
49− in UF.setDescriptor var (desc { rank = noRank, flex = flex' })
50+ in liftIO $ UF.setDescriptor var (desc { rank = noRank, flex = flex' })
51−
52+ Traversable.traverse (mapM registerIfNotRedundant) rankDict
53+ Traversable.traverse (mapM registerIfHigherRank) rankDict
52− return vars
55+ return ()
58+-- adjust the ranks of variables such that ranks never increase as you
59+-- move deeper into a variable. This mean the rank actually represents the
60+-- deepest variable in the whole type, and we can ignore things at a lower
61+-- rank than the current constraints.
54−traverse :: Int -> Int -> Int -> Variable -> IO Int
62+adjustRank :: Int -> Int -> Int -> Variable -> StateT TS.SolverState IO Int
55−traverse young visited k variable =
63+adjustRank youngMark visitedMark groupRank variable =
56− let f = traverse young visited k in
64+ let adjust = adjustRank youngMark visitedMark groupRank in
57− do desc <- UF.descriptor variable
65+ do desc <- liftIO $ UF.descriptor variable
58− case mark desc == young of
66+ case mark desc == youngMark of
59 True -> do
67 True -> do
60 rank' <- case structure desc of
68 rank' <- case structure desc of
61− Nothing -> return k
69+ Nothing -> return groupRank
62 Just term -> case term of
70 Just term -> case term of
63− App1 a b -> max `liftM` f a `ap` f b
71+ App1 a b -> max `liftM` adjust a `ap` adjust b
64− Fun1 a b -> max `liftM` f a `ap` f b
72+ Fun1 a b -> max `liftM` adjust a `ap` adjust b
65− Var1 x -> f x
73+ Var1 x -> adjust x
66 EmptyRecord1 -> return outermostRank
74 EmptyRecord1 -> return outermostRank
67 Record1 fields extension -> do
75 Record1 fields extension -> do
68− ranks <- mapM f (concat (Map.elems fields))
76+ ranks <- mapM adjust (concat (Map.elems fields))
69− max (maximum ranks) `liftM` f extension
77+ max (maximum ranks) `liftM` adjust extension
70− UF.setDescriptor variable (desc { mark = visited, rank = rank' })
78+ liftIO $ UF.setDescriptor variable (desc { mark = visitedMark, rank = rank' })
71 return rank'
79 return rank'
73 False -> do
81 False -> do
74− if mark desc /= visited then do
82+ if mark desc == visitedMark then return (rank desc) else do
75− let rank' = min k (rank desc)
83+ let rank' = min groupRank (rank desc)
76− UF.setDescriptor variable (desc { mark = visited, rank = rank' })
84+ liftIO $ UF.setDescriptor variable (desc { mark = visitedMark, rank = rank' })
77 return rank'
85 return rank'
78− else return (rank desc)
84solve :: TypeConstraint -> StateT TS.SolverState IO ()
88solve :: TypeConstraint -> StateT TS.SolverState IO ()
85solve constraint =
89solve constraint =
@@ -94,41 +98,67 @@ solve constraint =
94 CAnd cs -> mapM_ solve cs
98 CAnd cs -> mapM_ solve cs
96 CLet [Scheme [] fqs constraint' _] CTrue -> do
100 CLet [Scheme [] fqs constraint' _] CTrue -> do
97− mapM_ introduce fqs
101+ mapM_ TS.introduce fqs
98 solve constraint'
102 solve constraint'
100 CLet schemes constraint' -> do
104 CLet schemes constraint' -> do
101− mapM solveScheme schemes
105+ headers <- mapM solveScheme schemes
106+ TS.modifyEnv $ \env -> Map.unions (headers ++ [env])
102 solve constraint'
107 solve constraint'
104 CInstance name term -> do
109 CInstance name term -> do
105− let instance' = undefined
110+ env <- TS.getEnv
106− inst = undefined --instance' pool (Env.get env value name)
111+ freshCopy <- TS.makeInstance ((Map.!) env name)
107 t <- TS.flatten term
112 t <- TS.flatten term
108− unify inst t
113+ unify freshCopy t
110−solveScheme :: TypeScheme -> StateT TS.SolverState IO ()
115+solveScheme :: TypeScheme -> StateT TS.SolverState IO (Map.Map String Variable)
111solveScheme scheme =
116solveScheme scheme =
112 case scheme of
117 case scheme of
113 Scheme [] [] constraint header -> do
118 Scheme [] [] constraint header -> do
114 solve constraint
119 solve constraint
115 Traversable.traverse TS.flatten header
120 Traversable.traverse TS.flatten header
118 Scheme rigidQuantifiers flexibleQuantifiers constraint header -> do
122 Scheme rigidQuantifiers flexibleQuantifiers constraint header -> do
119 let quantifiers = rigidQuantifiers ++ flexibleQuantifiers
123 let quantifiers = rigidQuantifiers ++ flexibleQuantifiers
120− globalPool <- TS.getPool
124+ currentPool <- TS.getPool
121− localPool <- TS.newPool
125+
122− TS.modifyPool (\_ -> localPool)
126+ -- fill in a new pool when working on this scheme's constraints
127+ emptyPool <- TS.nextRankPool
128+ TS.switchToPool emptyPool
123 mapM TS.introduce quantifiers
129 mapM TS.introduce quantifiers
124 header' <- Traversable.traverse TS.flatten header
130 header' <- Traversable.traverse TS.flatten header
125 solve constraint
131 solve constraint
126− -- distinct variables
128− -- generic variables
129− TS.modifyPool (\_ -> globalPool)
132− do desc <- UF.descriptor var
133+ allDistinct rigidQuantifiers
134+ localPool <- TS.getPool
135+ TS.switchToPool currentPool
136+ generalize localPool
137+ mapM isGeneric rigidQuantifiers
141+-- Checks that all of the given variables belong to distinct equivalence classes.
142+-- Also checks that their structure is Nothing, so they represent a variable, not
143+-- a more complex term.
144+allDistinct :: [Variable] -> StateT TS.SolverState IO ()
145+allDistinct vars = do
146+ seen <- TS.uniqueMark
148+ desc <- liftIO $ UF.descriptor var
149+ case structure desc of
150+ Just _ -> TS.addError "Cannot generalize something that is not a type variable."
152+ if mark desc == seen
153+ then TS.addError "Duplicate variable during generalization"
155+ liftIO $ UF.setDescriptor var (desc { mark = seen })
158+-- Check that a variable has rank == noRank, meaning that it can be generalized.
159+isGeneric :: Variable -> StateT TS.SolverState IO ()
161+ desc <- liftIO $ UF.descriptor var
162+ if rank desc == noRank
164+ else TS.addError "Cannot generalize. Variable must have not have a rank."