on master help sign in
Create type pools, have an organized model of state to flow through

the State Transformer during constraint solving and variable unification.

commitca62ee64a9fb827953b3a8affd5d56e33b47834f authorEvan Czaplicki <evan@Evans-MacBook-Air.local> dateTue 9 Jul 2013, 10:25 (13 years ago) parent0b2b98d
4 files changed+115−106
compiler/Type/Pool.hs−45 compiler/Type/Solve.hs+44−47 compiler/Type/State.hs+60 compiler/Type/Unify.hs+11−14
compiler/Type/Pool.hsdeleted−45
@@ -1,45 +0,0 @@
1−module Type.Pool where
2−
3−import Type.Type
4−import qualified Data.UnionFind.IO as UF
5−import Control.Arrow (first)
6−import Control.Monad.State
7−
8−-- Pool
9−-- Holds a bunch of variables
10−-- The rank of each variable is less than or equal to the pool's "maxRank"
11−-- The young pool exists to make it possible to identify these vars in constant time.
12−
13−-- inhabitants :: Pool -> [Variable]
14−
15−data Pool = Pool {
16− maxRank :: Int,
17− inhabitants :: [Variable]
18−}
19−
20−register :: Variable -> StateT (Pool,[String]) IO Variable
21−register variable = do
22− modify . first $ \pool -> pool { inhabitants = variable : inhabitants pool }
23− return variable
24−
25−introduce :: Variable -> StateT (Pool,[String]) IO Variable
26−introduce variable = do
27− (pool, _) <- get
28− liftIO $ UF.modifyDescriptor variable (\desc -> desc { rank = maxRank pool })
29− register variable
30−
31−flatten :: Type -> StateT (Pool,[String]) IO Variable
32−flatten term =
33− case term of
34− VarN v -> return v
35− TermN t -> do
36− flatStructure <- undefined -- chop t
37− (pool, _) <- get
38− var <- liftIO . UF.fresh $ Descriptor {
39− structure = Just flatStructure,
40− rank = maxRank pool,
41− flex = Flexible,
42− name = Nothing,
43− mark = 0
44− }
45− register var
compiler/Type/Solve.hs+44−47
@@ -2,33 +2,24 @@
22module Type.Solve where
33
44import Control.Monad
5+import Control.Monad.State
56import qualified Data.UnionFind.IO as UF
67import qualified Data.Array.IO as Array
7−import Data.Map as Map
8+import qualified Data.Map as Map
9+import qualified Data.Traversable as Traversable
810import qualified Data.Maybe as Maybe
911import Type.Type
1012import Type.Unify
11−import Type.Environment as Env
12−
13−-- Pool
14−-- Holds a bunch of variables
15−-- The rank of each variable is less than or equal to the pool's "number"
16−-- The young pool exists to make it possible to identify these vars in constant time.
17−
18−-- inhabitants :: Pool -> [Variable]
19−
20−data Pool = Pool {
21− maxRank :: Int,
22− inhabitants :: [Variable]
23−}
13+import qualified Type.Environment as Env
14+import qualified Type.State as TS
2415
2516register = undefined
2617
27−generalize :: Pool -> Pool -> IO [Variable]
18+generalize :: TS.Pool -> TS.Pool -> IO [Variable]
2819generalize oldPool youngPool = do
2920 let young = 0
3021 visited = 1
31− youngRank = maxRank youngPool
22+ youngRank = TS.maxRank youngPool
3223
3324 array' <- Array.newArray (0, youngRank) []
3425 let array = array' :: Array.IOArray Int [Variable]
@@ -36,7 +27,7 @@ generalize oldPool youngPool = do
3627 -- Insert all of the youngPool variables into the array.
3728 -- They are placed into a list at the index corresponding
3829 -- to their rank.
39− forM (inhabitants youngPool) $ \var -> do
30+ forM (TS.inhabitants youngPool) $ \var -> do
4031 desc <- UF.descriptor var
4132 vars <- Array.readArray array (rank desc)
4233 Array.writeArray array (rank desc) (var : vars)
@@ -86,50 +77,56 @@ traverse young visited k variable =
8677 return rank'
8778 else return (rank desc)
8879
89−success = return []
90−
91−chop = undefined
9280addTo = undefined
9381newPool = undefined
9482introduce = undefined
9583
96−solve env pool constraint =
97− case constraint of
98− CTrue -> success
84+solve :: TypeConstraint -> StateT TS.SolverState IO ()
85+solve constraint =
86+ case constraint of
87+ CTrue -> return ()
88+
89+ CEqual term1 term2 -> do
90+ t1 <- TS.flatten term1
91+ t2 <- TS.flatten term2
92+ unify t1 t2
9993
100− CEqual term1 term2 ->
101− unify (register pool) term1 term2
94+ CAnd cs -> mapM_ solve cs
10295
103− CAnd cs -> do
104− results <- mapM (solve env pool) cs
105− return (concat results)
96+ CLet [Scheme [] fqs constraint' _] CTrue -> do
97+ mapM_ introduce fqs
98+ solve constraint'
10699
107− CLet schemes constraint' -> do
108− env' <- foldM (\env' scheme -> addTo env' `liftM` solveScheme env pool scheme) env schemes
109− solve env' pool constraint'
100+ CLet schemes constraint' -> do
101+ mapM solveScheme schemes
102+ solve constraint'
110103
111− CInstance name term -> do
112− let instance' = undefined
113− inst = instance' pool (Env.get env value name)
114− t <- chop pool term
115− unify pool inst t
104+ CInstance name term -> do
105+ let instance' = undefined
106+ inst = undefined --instance' pool (Env.get env value name)
107+ t <- TS.flatten term
108+ unify inst t
116109
117−solveScheme env pool scheme =
110+solveScheme :: TypeScheme -> StateT TS.SolverState IO ()
111+solveScheme scheme =
118112 case scheme of
119113 Scheme [] [] constraint header -> do
120− solve env pool constraint
121− mapM (\(n,t) -> (,) n `liftM` chop pool t) (Map.toList header)
114+ solve constraint
115+ Traversable.traverse TS.flatten header
116+ return ()
122117
123118 Scheme rigidQuantifiers flexibleQuantifiers constraint header -> do
124119 let quantifiers = rigidQuantifiers ++ flexibleQuantifiers
125− pool' <- newPool pool
126− mapM (introduce pool') rigidQuantifiers
127− mapM (introduce pool') flexibleQuantifiers
128− header' <- mapM (\(n,t) -> (,) n `liftM` chop pool t) (Map.toList header)
129− solve env pool' constraint
130− generalize pool pool'
131− mapM isGeneric rigidQuantifiers
132− return header'
120+ globalPool <- TS.getPool
121+ localPool <- TS.newPool
122+ TS.modifyPool (\_ -> localPool)
123+ mapM TS.introduce quantifiers
124+ header' <- Traversable.traverse TS.flatten header
125+ solve constraint
126+ -- distinct variables
127+ -- generalize
128+ -- generic variables
129+ TS.modifyPool (\_ -> globalPool)
133130
134131isGeneric var =
135132 do desc <- UF.descriptor var
compiler/Type/State.hsnew file+60
@@ -0,0 +1,60 @@
1+module Type.State where
2+
3+import Type.Type
4+import qualified Type.Environment as Env
5+import qualified Data.UnionFind.IO as UF
6+import Control.Monad.State
7+
8+-- Pool
9+-- Holds a bunch of variables
10+-- The rank of each variable is less than or equal to the pool's "maxRank"
11+-- The young pool exists to make it possible to identify these vars in constant time.
12+
13+data Pool = Pool {
14+ maxRank :: Int,
15+ inhabitants :: [Variable]
16+}
17+
18+-- Keeps track of the environment, type variable pool, and a list of errors
19+type SolverState = (Env.Environment, Pool, [String])
20+
21+modifyEnv f = modify $ \(env, pool, errors) -> (f env, pool, errors)
22+modifyPool f = modify $ \(env, pool, errors) -> (env, f pool, errors)
23+addError err = modify $ \(env, pool, errors) -> (env, pool, err:errors)
24+
25+getPool :: StateT SolverState IO Pool
26+getPool = do
27+ (_, pool, _) <- get
28+ return pool
29+
30+newPool :: StateT SolverState IO Pool
31+newPool = do
32+ (_, pool, _) <- get
33+ return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
34+
35+register :: Variable -> StateT SolverState IO Variable
36+register variable = do
37+ modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
38+ return variable
39+
40+introduce :: Variable -> StateT SolverState IO Variable
41+introduce variable = do
42+ (_, pool, _) <- get
43+ liftIO $ UF.modifyDescriptor variable (\desc -> desc { rank = maxRank pool })
44+ register variable
45+
46+flatten :: Type -> StateT SolverState IO Variable
47+flatten term =
48+ case term of
49+ VarN v -> return v
50+ TermN t -> do
51+ flatStructure <- undefined -- chop t
52+ (_, pool, _) <- get
53+ var <- liftIO . UF.fresh $ Descriptor {
54+ structure = Just flatStructure,
55+ rank = maxRank pool,
56+ flex = Flexible,
57+ name = Nothing,
58+ mark = 0
59+ }
60+ register var
compiler/Type/Unify.hs+11−14
@@ -2,17 +2,17 @@ module Type.Unify (unify) where
22
33import Type.Type
44import qualified Data.UnionFind.IO as UF
5−import qualified Type.Pool as Pool
5+import qualified Type.State as TS
66import Control.Arrow (first,second)
77import Control.Monad.State
88
9−unify :: Variable -> Variable -> StateT (Pool.Pool, [String]) IO ()
9+unify :: Variable -> Variable -> StateT TS.SolverState IO ()
1010unify variable1 variable2 = do
1111 equivalent <- liftIO $ UF.equivalent variable1 variable2
1212 if equivalent then return ()
1313 else actuallyUnify variable1 variable2
1414
15−actuallyUnify :: Variable -> Variable -> StateT (Pool.Pool, [String]) IO ()
15+actuallyUnify :: Variable -> Variable -> StateT TS.SolverState IO ()
1616actuallyUnify variable1 variable2 = do
1717 desc1 <- liftIO $ UF.descriptor variable1
1818 desc2 <- liftIO $ UF.descriptor variable2
@@ -34,25 +34,22 @@ actuallyUnify variable1 variable2 = do
3434 rank' :: Int
3535 rank' = min (rank desc1) (rank desc2)
3636
37− merge1 :: StateT (Pool.Pool, [String]) IO ()
37+ merge1 :: StateT TS.SolverState IO ()
3838 merge1 = liftIO $ do
3939 UF.union variable2 variable1
4040 UF.setDescriptor variable1 (desc1 { flex = flex', name = name', rank = rank', mark = undefined })
4141
42− merge2 :: StateT (Pool.Pool, [String]) IO ()
42+ merge2 :: StateT TS.SolverState IO ()
4343 merge2 = liftIO $ do
4444 UF.union variable1 variable2
4545 UF.setDescriptor variable2 (desc2 { flex = flex', name = name', rank = rank', mark = undefined })
4646
47− fresh :: Maybe (Term1 Variable) -> StateT (Pool.Pool, [String]) IO Variable
47+ fresh :: Maybe (Term1 Variable) -> StateT TS.SolverState IO Variable
4848 fresh structure = do
4949 var <- liftIO . UF.fresh $ Descriptor {
5050 structure = structure, rank = rank', flex = flex', name = name', mark = undefined
5151 }
52− Pool.register var
53−
54− mistake :: String -> StateT (Pool.Pool, [String]) IO ()
55− mistake err = modify $ second (err:)
52+ TS.register var
5653
5754 case (structure desc1, structure desc2) of
5855 (Nothing, _) | flex desc1 == Flexible -> merge2
@@ -61,8 +58,8 @@ actuallyUnify variable1 variable2 = do
6158 (Just (Var1 v), _) -> unify v variable2
6259 (_, Just (Var1 v)) -> unify v variable1
6360
64− (Nothing, _) -> mistake "Cannot unify rigid type variable."
65− (_, Nothing) -> mistake "Cannot unify rigid type variable."
61+ (Nothing, _) -> TS.addError "Cannot unify rigid type variable."
62+ (_, Nothing) -> TS.addError "Cannot unify rigid type variable."
6663
6764 (Just type1, Just type2) ->
6865 case (type1,type2) of
@@ -79,6 +76,6 @@ actuallyUnify variable1 variable2 = do
7976 return ()
8077
8178 (Record1 fields1 ext1, Record1 fields2 ext2) ->
82− mistake "did not write record unification yet"
79+ TS.addError "did not write record unification yet"
8380
84− _ -> mistake "Could not unify types"
81+ _ -> TS.addError "Could not unify types"