1{-# OPTIONS_GHC -Wall #-}
4import Control.Monad.State (StateT, liftIO)
5import qualified Control.Monad.State as State
6import qualified Data.List as List
7import qualified Data.Map as Map
8import qualified Data.Set as Set
9import qualified Data.Traversable as Traverse (traverse)
10import qualified Data.UnionFind.IO as UF
12import qualified AST.Type as T
13import qualified AST.Variable as Var
14import qualified Reporting.Annotation as A
15import qualified Reporting.Error.Type as Error
16import qualified Reporting.Region as R
32 Constraint Type Variable
47 | Record1 (Map.Map String a) a
52 | AliasN Var.Canonical [(String, TermN a)] (TermN a)
54 | TermN (Term1 (TermN a))
57record :: Map.Map String (TermN a) -> TermN a -> TermN a
59 TermN (Record1 fs rec)
66data Descriptor = Descriptor
70 , _copy :: Maybe Variable
75 = Structure (Term1 Variable)
77 | Var Flex (Maybe Super) (Maybe String)
78 | Alias Var.Canonical [(String,Variable)] Variable
116getVarNamesMark :: Int
128 | CEqual Error.Hint R.Region a a
129 | CAnd [Constraint a b]
130 | CLet [Scheme a b] (Constraint a b)
131 | CInstance R.Region SchemeName a
134type SchemeName = String
137data Scheme a b = Scheme
138 { _rigidQuantifiers :: [b]
139 , _flexibleQuantifiers :: [b]
140 , _constraint :: Constraint a b
141 , _header :: Map.Map String (A.Located a)
152(==>) :: Type -> Type -> Type
157(<|) :: TermN a -> TermN a -> TermN a
166mkDescriptor :: Content -> Descriptor
167mkDescriptor content =
176mkAtom :: Var.Canonical -> IO Variable
178 UF.fresh $ mkDescriptor (Atom name)
181mkVar :: Maybe Super -> IO Variable
183 UF.fresh $ mkDescriptor (Var Flex maybeSuper Nothing)
186mkNamedVar :: String -> IO Variable
188 UF.fresh $ mkDescriptor (Var Flex (toSuper name) Nothing)
191mkRigid :: String -> IO Variable
193 UF.fresh $ mkDescriptor (Var Rigid (toSuper name) (Just name))
196toSuper :: String -> Maybe Super
198 if List.isPrefixOf "number" name then
201 else if List.isPrefixOf "comparable" name then
204 else if List.isPrefixOf "appendable" name then
215monoscheme :: Map.Map String (A.Located a) -> Scheme a b
217 Scheme [] [] CTrue headers
222(/\) :: Constraint a b -> Constraint a b -> Constraint a b
230-- ex qs constraint == exists qs. constraint
231ex :: [Variable] -> TypeConstraint -> TypeConstraint
233 CLet [Scheme [] fqs constraint Map.empty] CTrue
236-- fl qs constraint == forall qs. constraint
237fl :: [Variable] -> TypeConstraint -> TypeConstraint
239 CLet [Scheme rqs [] constraint Map.empty] CTrue
242exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
244 do v <- mkVar Nothing
245 ex [v] <$> f (VarN v)
248existsNumber :: (Type -> IO TypeConstraint) -> IO TypeConstraint
250 do v <- mkVar (Just Number)
251 ex [v] <$> f (VarN v)
255-- CONVERT TO SOURCE TYPES
258-- TODO: Attach resulting type to the descriptor so that you
259-- never have to do extra work, particularly nice for aliased types
260toSrcType :: Variable -> IO T.Canonical
262 do usedNames <- getVarNames variable
263 State.evalStateT (variableToSrcType variable) (makeNameState usedNames)
266variableToSrcType :: Variable -> StateT NameState IO T.Canonical
267variableToSrcType variable =
268 do descriptor <- liftIO $ UF.descriptor variable
269 if _mark descriptor == occursMark
274 do liftIO $ UF.setDescriptor variable (descriptor { _mark = occursMark })
275 srcType <- contentToSrcType variable (_content descriptor)
276 liftIO $ UF.setDescriptor variable descriptor
280contentToSrcType :: Variable -> Content -> StateT NameState IO T.Canonical
281contentToSrcType variable content =
289 Var _ _ (Just name) ->
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)
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))
307termToSrcType :: Term1 Variable -> StateT NameState IO T.Canonical
311 do srcFunc <- variableToSrcType func
312 srcArg <- variableToSrcType arg
315 return (T.App f (args ++ [srcArg]))
318 return (T.App srcFunc [srcArg])
322 <$> variableToSrcType a
323 <*> variableToSrcType b
326 return $ T.Record [] Nothing
328 Record1 fields extension ->
329 do srcFields <- Map.toList <$> Traverse.traverse variableToSrcType fields
330 srcExt <- T.iteratedDealias <$> variableToSrcType extension
333 T.Record subFields subExt ->
334 T.Record (subFields ++ srcFields) subExt
337 T.Record srcFields (Just srcExt)
340 error "Used toSrcType on a type that is not well-formed"
344-- MANAGE FRESH VARIABLE NAMES
347data NameState = NameState
348 { _freeNames :: [String]
349 , _numberPrimes :: Int
350 , _comparablePrimes :: Int
351 , _appendablePrimes :: Int
352 , _compAppendPrimes :: Int
356makeNameState :: Set.Set String -> NameState
357makeNameState usedNames =
360 map (:suffix) ['a'..'z']
363 concatMap makeName ("" : map show [ (1 :: Int) .. ])
366 filter (\name -> Set.notMember name usedNames) allNames
368 NameState freeNames 0 0 0 0
371getFreshName :: (Monad m) => Maybe Super -> StateT NameState m String
372getFreshName maybeSuper =
375 do names <- State.gets _freeNames
376 State.modify (\state -> state { _freeNames = tail names })
380 do primes <- State.gets _numberPrimes
381 State.modify (\state -> state { _numberPrimes = primes + 1 })
382 return ("number" ++ replicate primes '\'')
385 do primes <- State.gets _comparablePrimes
386 State.modify (\state -> state { _comparablePrimes = primes + 1 })
387 return ("comparable" ++ replicate primes '\'')
390 do primes <- State.gets _appendablePrimes
391 State.modify (\state -> state { _appendablePrimes = primes + 1 })
392 return ("appendable" ++ replicate primes '\'')
395 do primes <- State.gets _compAppendPrimes
396 State.modify (\state -> state { _compAppendPrimes = primes + 1 })
397 return ("compappend" ++ replicate primes '\'')
401-- GET ALL VARIABLE NAMES
404getVarNames :: Variable -> IO (Set.Set String)
406 do desc <- UF.descriptor var
407 if _mark desc == getVarNamesMark
412 do UF.setDescriptor var (desc { _mark = getVarNamesMark })
413 getVarNamesHelp (_content desc)
416getVarNamesHelp :: Content -> IO (Set.Set String)
417getVarNamesHelp content =
419 Var _ _ (Just name) ->
420 return (Set.singleton name)
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))
441getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
442getVarNamesTerm term =
443 let go = getVarNames in
446 Set.union <$> go a <*> go b
449 Set.union <$> go a <*> go b
454 Record1 fields extension ->
455 do fieldVars <- Set.unions <$> mapM go (Map.elems fields)
456 Set.union fieldVars <$> go extension
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list