@@ -1,14 +1,16 @@
1module Type.Solve (solve) where
1module Type.Solve (solve) where
3−import Control.Applicative ((<$>), (<*>))
3+import Control.Applicative ((<$>), (<*>), (<|>))
4import Control.Monad
4import Control.Monad
5import Control.Monad.State (StateT, execStateT, liftIO)
5import Control.Monad.State (StateT, execStateT, liftIO)
6import Control.Monad.Except (ExceptT, throwError)
6import Control.Monad.Except (ExceptT, throwError)
7+import qualified Data.Foldable as F
7import qualified Data.List as List
8import qualified Data.List as List
8import qualified Data.Map as Map
9import qualified Data.Map as Map
9−import qualified Data.Traversable as Traversable
10+import qualified Data.Traversable as T
10import qualified Data.UnionFind.IO as UF
11import qualified Data.UnionFind.IO as UF
13+import qualified AST.Type as Type
12import qualified Reporting.Annotation as A
14import qualified Reporting.Annotation as A
13import qualified Reporting.Error.Type as Error
15import qualified Reporting.Error.Type as Error
14import qualified Type.State as TS
16import qualified Type.State as TS
@@ -45,7 +47,7 @@ generalize youngPool =
45 if isRedundant then return var else TS.register var
47 if isRedundant then return var else TS.register var
47 let rankDict' = Map.delete youngRank rankDict
49 let rankDict' = Map.delete youngRank rankDict
48− Traversable.traverse (mapM registerIfNotRedundant) rankDict'
50+ T.traverse (mapM registerIfNotRedundant) rankDict'
50 -- For variables with rank youngRank
52 -- For variables with rank youngRank
51 -- If rank < youngRank: register in oldPool
53 -- If rank < youngRank: register in oldPool
@@ -159,8 +161,9 @@ actuallySolve constraint =
159 do env <- TS.getEnv
161 do env <- TS.getEnv
160 freshCopy <-
162 freshCopy <-
161 case Map.lookup name env of
163 case Map.lookup name env of
162− Just tipe ->
164+ Just (A.A _ tipe) ->
163 TS.makeInstance tipe
165 TS.makeInstance tipe
164 Nothing ->
167 Nothing ->
165 if List.isPrefixOf "Native." name
168 if List.isPrefixOf "Native." name
166 then liftIO (variable Flexible)
169 then liftIO (variable Flexible)
@@ -170,12 +173,18 @@ actuallySolve constraint =
170 unify Error.None region freshCopy t
173 unify Error.None region freshCopy t
173−solveScheme :: TypeScheme -> StateT TS.SolverState IO (Map.Map String Variable)
178+ -> StateT TS.SolverState IO (Map.Map String (A.Located Variable))
174solveScheme scheme =
179solveScheme scheme =
181+ flatten (A.A region term) =
182+ A.A region <$> TS.flatten term
175 case scheme of
184 case scheme of
176 Scheme [] [] constraint header ->
185 Scheme [] [] constraint header ->
177 do actuallySolve constraint
186 do actuallySolve constraint
178− Traversable.traverse TS.flatten header
187+ T.traverse flatten header
180 Scheme rigidQuantifiers flexibleQuantifiers constraint header ->
189 Scheme rigidQuantifiers flexibleQuantifiers constraint header ->
181 do let quantifiers = rigidQuantifiers ++ flexibleQuantifiers
190 do let quantifiers = rigidQuantifiers ++ flexibleQuantifiers
@@ -185,7 +194,7 @@ solveScheme scheme =
185 freshPool <- TS.nextRankPool
194 freshPool <- TS.nextRankPool
186 TS.switchToPool freshPool
195 TS.switchToPool freshPool
187 mapM TS.introduce quantifiers
196 mapM TS.introduce quantifiers
188− header' <- Traversable.traverse TS.flatten header
197+ header' <- T.traverse flatten header
189 actuallySolve constraint
198 actuallySolve constraint
191 allDistinct rigidQuantifiers
200 allDistinct rigidQuantifiers
@@ -234,46 +243,53 @@ crash msg =
234 ++ "<https://github.com/elm-lang/elm-compiler/issues>"
243 ++ "<https://github.com/elm-lang/elm-compiler/issues>"
237−occurs :: (String, Variable) -> StateT TS.SolverState IO ()
246+occurs :: (String, A.Located Variable) -> StateT TS.SolverState IO ()
238−occurs (_name, variable) =
247+occurs (name, A.A region variable) =
239− do vars <- liftIO $ infiniteVars [] variable
248+ do maybePair <- liftIO $ occursHelp [] variable
240− case vars of
249+ case maybePair of
241− [] ->
250+ Nothing ->
242− return ()
251+ return ()
244− var : _ ->
253+ Just (t1, t2) ->
245− do desc <- liftIO $ UF.descriptor var
254+ let
246− let region = error "TODO:occurs"
255+ info = Error.InfiniteTypeInfo name t1 t2
247− case structure desc of
249− TS.addError region (Error.InfiniteType undefined (error "TODO:occurs"))
252− TS.addError region (Error.InfiniteType undefined (error "TODO:occurs"))
254− infiniteVars :: [Variable] -> Variable -> IO [Variable]
255− infiniteVars seen var =
256− let go = infiniteVars (var:seen)
257+ TS.addError region (Error.InfiniteType info)
263+ -> IO (Maybe (Type.Canonical, Type.Canonical))
264+occursHelp seen var =
258− if var `elem` seen
265+ if elem var seen then
259− then return [var]
266+ do desc <- UF.descriptor var
267+ UF.setDescriptor var (desc { structure = Nothing })
268+ var' <- UF.fresh desc
269+ srcVar <- toSrcType var
270+ srcVar' <- toSrcType var'
271+ return (Just (srcVar, srcVar'))
261− desc <- UF.descriptor var
273+ do desc <- UF.descriptor var
262 case structure desc of
274 case structure desc of
263− Nothing -> return []
275+ Nothing ->
264 Just struct ->
278 Just struct ->
279+ let go = occursHelp (var:seen)
265 case struct of
281 case struct of
266 App1 a b ->
282 App1 a b ->
267− (++) <$> go a <*> go b
283+ (<|>) <$> go a <*> go b
269 Fun1 a b ->
285 Fun1 a b ->
270− (++) <$> go a <*> go b
286+ (<|>) <$> go a <*> go b
272 Var1 a ->
288 Var1 a ->
275 EmptyRecord1 ->
291 EmptyRecord1 ->
276− return []
292+ return Nothing
278 Record1 fields ext ->
294 Record1 fields ext ->
279− concat <$> mapM go (ext : concat (Map.elems fields))
295+ F.asum <$> mapM go (ext : concat (Map.elems fields))