@@ -1,7 +1,7 @@
11{-# OPTIONS_GHC -Wall #-}
22module Type.Type where
33
4−import Control.Monad.State (StateT)
4+import Control.Monad.State (StateT, liftIO)
55import qualified Control.Monad.State as State
66import qualified Data.List as List
77import qualified Data.Map as Map
@@ -108,6 +108,16 @@ initialMark :: Int
108108initialMark = 1
109109
110110
111+occursMark :: Int
112+occursMark =
113+ -1
114+
115+
116+getVarNamesMark :: Int
117+getVarNamesMark =
118+ -2
119+
120+
111121
112122-- CONSTRAINTS
113123
@@ -255,30 +265,43 @@ toSrcType variable =
255265
256266variableToSrcType :: Variable -> StateT NameState IO T.Canonical
257267variableToSrcType variable =
258− do descriptor <- State.liftIO (UF.descriptor variable)
259− case _content descriptor of
260− Structure term ->
261− termToSrcType term
268+ do descriptor <- liftIO $ UF.descriptor variable
269+ if _mark descriptor == occursMark
270+ then
271+ return (T.Var "∞")
272+
273+ else
274+ do liftIO $ UF.setDescriptor variable (descriptor { _mark = occursMark })
275+ srcType <- contentToSrcType variable (_content descriptor)
276+ liftIO $ UF.setDescriptor variable descriptor
277+ return srcType
278+
262279
263− Atom name ->
264− return (T.Type name)
280+contentToSrcType :: Variable -> Content -> StateT NameState IO T.Canonical
281+contentToSrcType variable content =
282+ case content of
283+ Structure term ->
284+ termToSrcType term
265285
266− Var _ _ (Just name) ->
267− return (T.Var name)
286+ Atom name ->
287+ return (T.Type name)
268288
269− Var flex maybeSuper Nothing ->
270− do freshName <- getFreshName maybeSuper
271− State.liftIO $ UF.modifyDescriptor variable $ \desc ->
272− desc { _content = Var flex maybeSuper (Just freshName) }
273− return (T.Var freshName)
289+ Var _ _ (Just name) ->
290+ return (T.Var name)
274291
275− Alias name args realVariable ->
276− do srcArgs <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType tvar) args
277− srcType <- variableToSrcType realVariable
278− return (T.Aliased name srcArgs (T.Filled srcType))
292+ Var flex maybeSuper Nothing ->
293+ do freshName <- getFreshName maybeSuper
294+ liftIO $ UF.modifyDescriptor variable $ \desc ->
295+ desc { _content = Var flex maybeSuper (Just freshName) }
296+ return (T.Var freshName)
279297
280− Error ->
281− return (T.Var "?")
298+ Alias name args realVariable ->
299+ do srcArgs <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType tvar) args
300+ srcType <- variableToSrcType realVariable
301+ return (T.Aliased name srcArgs (T.Filled srcType))
302+
303+ Error ->
304+ return (T.Var "?")
282305
283306
284307termToSrcType :: Term1 Variable -> StateT NameState IO T.Canonical
@@ -381,28 +404,38 @@ getFreshName maybeSuper =
381404getVarNames :: Variable -> IO (Set.Set String)
382405getVarNames var =
383406 do desc <- UF.descriptor var
407+ if _mark desc == getVarNamesMark
408+ then
409+ return Set.empty
410+
411+ else
412+ do UF.setDescriptor var (desc { _mark = getVarNamesMark })
413+ getVarNamesHelp (_content desc)
414+
384415
385− case _content desc of
386− Var _ _ (Just name) ->
387− return (Set.singleton name)
416+getVarNamesHelp :: Content -> IO (Set.Set String)
417+getVarNamesHelp content =
418+ case content of
419+ Var _ _ (Just name) ->
420+ return (Set.singleton name)
388421
389− Var _ _ Nothing ->
390− return Set.empty
422+ Var _ _ Nothing ->
423+ return Set.empty
391424
392− Structure term ->
393− getVarNamesTerm term
425+ Structure term ->
426+ getVarNamesTerm term
394427
395− Alias _name args realVar ->
396− do let argSet = Set.fromList (map fst args)
397− realSet <- getVarNames realVar
398− sets <- mapM (getVarNames . snd) args
399− return (Set.unions (realSet : argSet : sets))
428+ Alias _name args realVar ->
429+ do let argSet = Set.fromList (map fst args)
430+ realSet <- getVarNames realVar
431+ sets <- mapM (getVarNames . snd) args
432+ return (Set.unions (realSet : argSet : sets))
400433
401− Atom _ ->
402− return Set.empty
434+ Atom _ ->
435+ return Set.empty
403436
404− Error ->
405− return Set.empty
437+ Error ->
438+ return Set.empty
406439
407440
408441getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)