@@ -22,133 +22,6 @@ import qualified Type.UnionFind as UF
25−{-| Every variable has rank less than or equal to the maxRank of the pool.
26−This sorts variables into the young and old pools accordingly.
28−generalize :: TS.Pool -> TS.Solver ()
29−generalize pool@(TS.Pool youngRank _) =
30− {-# SCC elm_compiler_type_generalize #-}
31− do youngMark <- TS.uniqueMark
33− rankTable <- liftIO $ poolToRankTable youngMark pool
35− -- get the ranks right for each entry.
36− -- start at low ranks so that we only have to pass
37− -- over the information once.
38− visitedMark <- TS.uniqueMark
39− let adjust poolRank vars =
40− F.traverse_ (adjustRank youngMark visitedMark poolRank) vars
41− liftIO $ Vector.imapM_ adjust rankTable
43− -- For variables that have rank lowerer than youngRank, register them in
44− -- the old pool if they are not redundant.
45− Vector.forM_ (Vector.unsafeInit rankTable) $ \vars ->
47− do isRedundant <- liftIO $ UF.redundant var
48− if isRedundant then return var else TS.register var
50− -- For variables with rank youngRank
51− -- If rank < youngRank: register in oldPool
52− -- otherwise generalize
53− forM_ (Vector.unsafeLast rankTable) $ \var ->
54− {-# SCC elm_compiler_type_register #-}
55− do isRedundant <- liftIO $ UF.redundant var
59− (Descriptor content rank mark copy) <- liftIO $ UF.descriptor var
62− TS.register var >> return ()
64− liftIO $ UF.setDescriptor var $ Descriptor (rigidify content) noRank mark copy
67−poolToRankTable :: Mark -> TS.Pool -> IO (Vector.Vector [Variable])
68−poolToRankTable youngMark (TS.Pool youngRank youngInhabitants) =
69− do mutableTable <- MVector.replicate (youngRank + 1) []
71− -- Sort the youngPool variables by rank.
72− forM_ youngInhabitants $ \var ->
73− do (Descriptor content rank _ copy) <- UF.descriptor var
74− UF.setDescriptor var (Descriptor content rank youngMark copy)
75− MVector.modify mutableTable (var:) rank
77− Vector.unsafeFreeze mutableTable
80−rigidify :: Content -> Content
83− Var Flex maybeSuper maybeName ->
84− Var Rigid maybeSuper maybeName
94−-- Adjust variable ranks such that ranks never increase as you move deeper.
95−-- This way the outermost rank is representative of the entire structure.
97−adjustRank :: Mark -> Mark -> Int -> Variable -> IO Int
98−adjustRank youngMark visitedMark groupRank var =
99− {-# SCC elm_compiler_type_adjust #-}
100− do (Descriptor content rank mark copy) <- UF.descriptor var
101− if mark == youngMark then
102− do -- Set the variable as marked first because it may be cyclic.
103− UF.setDescriptor var $ Descriptor content rank visitedMark copy
104− maxRank <- adjustRankContent youngMark visitedMark groupRank content
105− UF.setDescriptor var $ Descriptor content maxRank visitedMark copy
108− else if mark == visitedMark then
112− do let minRank = min groupRank rank
113− -- TODO how can minRank ever be groupRank?
114− UF.setDescriptor var $ Descriptor content minRank visitedMark copy
118−adjustRankContent :: Mark -> Mark -> Int -> Content -> IO Int
119−adjustRankContent youngMark visitedMark groupRank content =
121− go = adjustRank youngMark visitedMark groupRank
131− -- THEORY: anything in the realVar would be outermostRank
132− foldM (\rank (_, argVar) -> max rank <$> go argVar) outermostRank args
134− Structure flatType ->
137− foldM (\rank arg -> max rank <$> go arg) outermostRank args
140− max <$> go arg <*> go result
143− -- THEORY: an empty record never needs to get generalized
144− return outermostRank
146− Record1 fields extension ->
147− do extRank <- go extension
148− foldM (\rank field -> max rank <$> go field) extRank fields
@@ -281,3 +154,132 @@ occurs (name, A.A region variable) =
281 liftIO $ UF.setDescriptor variable (Descriptor (Error "∞") rank mark copy)
154 liftIO $ UF.setDescriptor variable (Descriptor (Error "∞") rank mark copy)
282 TS.addError region (Error.InfiniteType (Right name) overallType)
155 TS.addError region (Error.InfiniteType (Right name) overallType)
162+{-| Every variable has rank less than or equal to the maxRank of the pool.
163+This sorts variables into the young and old pools accordingly.
165+generalize :: TS.Pool -> TS.Solver ()
166+generalize pool@(TS.Pool youngRank _) =
167+ {-# SCC elm_compiler_type_generalize #-}
168+ do youngMark <- TS.uniqueMark
170+ rankTable <- liftIO $ poolToRankTable youngMark pool
172+ -- get the ranks right for each entry.
173+ -- start at low ranks so that we only have to pass
174+ -- over the information once.
175+ visitedMark <- TS.uniqueMark
176+ let adjust poolRank vars =
177+ F.traverse_ (adjustRank youngMark visitedMark poolRank) vars
178+ liftIO $ Vector.imapM_ adjust rankTable
180+ -- For variables that have rank lowerer than youngRank, register them in
181+ -- the old pool if they are not redundant.
182+ Vector.forM_ (Vector.unsafeInit rankTable) $ \vars ->
183+ forM_ vars $ \var ->
184+ do isRedundant <- liftIO $ UF.redundant var
185+ if isRedundant then return var else TS.register var
187+ -- For variables with rank youngRank
188+ -- If rank < youngRank: register in oldPool
189+ -- otherwise generalize
190+ forM_ (Vector.unsafeLast rankTable) $ \var ->
191+ {-# SCC elm_compiler_type_register #-}
192+ do isRedundant <- liftIO $ UF.redundant var
196+ (Descriptor content rank mark copy) <- liftIO $ UF.descriptor var
199+ TS.register var >> return ()
201+ liftIO $ UF.setDescriptor var $ Descriptor (rigidify content) noRank mark copy
204+poolToRankTable :: Mark -> TS.Pool -> IO (Vector.Vector [Variable])
205+poolToRankTable youngMark (TS.Pool youngRank youngInhabitants) =
206+ do mutableTable <- MVector.replicate (youngRank + 1) []
208+ -- Sort the youngPool variables by rank.
209+ forM_ youngInhabitants $ \var ->
210+ do (Descriptor content rank _ copy) <- UF.descriptor var
211+ UF.setDescriptor var (Descriptor content rank youngMark copy)
212+ MVector.modify mutableTable (var:) rank
214+ Vector.unsafeFreeze mutableTable
217+rigidify :: Content -> Content
220+ Var Flex maybeSuper maybeName ->
221+ Var Rigid maybeSuper maybeName
231+-- Adjust variable ranks such that ranks never increase as you move deeper.
232+-- This way the outermost rank is representative of the entire structure.
234+adjustRank :: Mark -> Mark -> Int -> Variable -> IO Int
235+adjustRank youngMark visitedMark groupRank var =
236+ {-# SCC elm_compiler_type_adjust #-}
237+ do (Descriptor content rank mark copy) <- UF.descriptor var
238+ if mark == youngMark then
239+ do -- Set the variable as marked first because it may be cyclic.
240+ UF.setDescriptor var $ Descriptor content rank visitedMark copy
241+ maxRank <- adjustRankContent youngMark visitedMark groupRank content
242+ UF.setDescriptor var $ Descriptor content maxRank visitedMark copy
245+ else if mark == visitedMark then
249+ do let minRank = min groupRank rank
250+ -- TODO how can minRank ever be groupRank?
251+ UF.setDescriptor var $ Descriptor content minRank visitedMark copy
255+adjustRankContent :: Mark -> Mark -> Int -> Content -> IO Int
256+adjustRankContent youngMark visitedMark groupRank content =
258+ go = adjustRank youngMark visitedMark groupRank
268+ -- THEORY: anything in the realVar would be outermostRank
269+ foldM (\rank (_, argVar) -> max rank <$> go argVar) outermostRank args
271+ Structure flatType ->
274+ foldM (\rank arg -> max rank <$> go arg) outermostRank args
277+ max <$> go arg <*> go result
280+ -- THEORY: an empty record never needs to get generalized
281+ return outermostRank
283+ Record1 fields extension ->
284+ do extRank <- go extension
285+ foldM (\rank field -> max rank <$> go field) extRank fields