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.Module.Name as ModuleName
13import qualified AST.Type as T
14import qualified AST.Variable as Var
15import qualified Reporting.Annotation as A
16import qualified Reporting.Error.Type as Error
17import qualified Reporting.Region as R
33 Constraint Type Variable
48 | Record1 (Map.Map String a) a
53 | AliasN Var.Canonical [(String, TermN a)] (TermN a)
55 | TermN (Term1 (TermN a))
58record :: Map.Map String (TermN a) -> TermN a -> TermN a
60 TermN (Record1 fs rec)
67data Descriptor = Descriptor
71 , _copy :: Maybe Variable
76 = Structure (Term1 Variable)
78 | Var Flex (Maybe Super) (Maybe String)
79 | Alias Var.Canonical [(String,Variable)] Variable
117getVarNamesMark :: Int
129 | CEqual Error.Hint R.Region a a
130 | CAnd [Constraint a b]
131 | CLet [Scheme a b] (Constraint a b)
132 | CInstance R.Region SchemeName a
135type SchemeName = String
138data Scheme a b = Scheme
139 { _rigidQuantifiers :: [b]
140 , _flexibleQuantifiers :: [b]
141 , _constraint :: Constraint a b
142 , _header :: Map.Map String (A.Located a)
153(==>) :: Type -> Type -> Type
158(<|) :: TermN a -> TermN a -> TermN a
167mkDescriptor :: Content -> Descriptor
168mkDescriptor content =
177mkAtom :: Var.Canonical -> IO Variable
179 UF.fresh $ mkDescriptor (Atom name)
182mkVar :: Maybe Super -> IO Variable
184 UF.fresh $ mkDescriptor (Var Flex maybeSuper Nothing)
187mkNamedVar :: String -> IO Variable
189 UF.fresh $ mkDescriptor (Var Flex (toSuper name) Nothing)
192mkRigid :: String -> IO Variable
194 UF.fresh $ mkDescriptor (Var Rigid (toSuper name) (Just name))
197toSuper :: String -> Maybe Super
199 if List.isPrefixOf "number" name then
202 else if List.isPrefixOf "comparable" name then
205 else if List.isPrefixOf "appendable" name then
216monoscheme :: Map.Map String (A.Located a) -> Scheme a b
218 Scheme [] [] CTrue headers
223(/\) :: Constraint a b -> Constraint a b -> Constraint a b
231-- ex qs constraint == exists qs. constraint
232ex :: [Variable] -> TypeConstraint -> TypeConstraint
234 CLet [Scheme [] fqs constraint Map.empty] CTrue
237-- fl qs constraint == forall qs. constraint
238fl :: [Variable] -> TypeConstraint -> TypeConstraint
240 CLet [Scheme rqs [] constraint Map.empty] CTrue
243exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
245 do v <- mkVar Nothing
246 ex [v] <$> f (VarN v)
249existsNumber :: (Type -> IO TypeConstraint) -> IO TypeConstraint
251 do v <- mkVar (Just Number)
252 ex [v] <$> f (VarN v)
256-- CONVERT TO SOURCE TYPES
259-- TODO: Attach resulting type to the descriptor so that you
260-- never have to do extra work, particularly nice for aliased types
261toSrcType :: Variable -> IO T.Canonical
263 do usedNames <- getVarNames variable
264 State.evalStateT (variableToSrcType variable) (makeNameState usedNames)
267variableToSrcType :: Variable -> StateT NameState IO T.Canonical
268variableToSrcType variable =
269 do descriptor <- liftIO $ UF.descriptor variable
270 let mark = _mark descriptor
271 if mark == occursMark
276 do liftIO $ UF.modifyDescriptor variable (\desc -> desc { _mark = occursMark })
277 srcType <- contentToSrcType variable (_content descriptor)
278 liftIO $ UF.modifyDescriptor variable (\desc -> desc { _mark = mark })
282contentToSrcType :: Variable -> Content -> StateT NameState IO T.Canonical
283contentToSrcType variable content =
291 Var _ _ (Just name) ->
294 Var flex maybeSuper Nothing ->
295 do freshName <- getFreshName maybeSuper
296 liftIO $ UF.modifyDescriptor variable $ \desc ->
297 desc { _content = Var flex maybeSuper (Just freshName) }
298 return (T.Var freshName)
300 Alias name args realVariable ->
301 do srcArgs <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType tvar) args
302 srcType <- variableToSrcType realVariable
303 return (T.Aliased name srcArgs (T.Filled srcType))
309termToSrcType :: Term1 Variable -> StateT NameState IO T.Canonical
313 do srcFunc <- variableToSrcType func
314 srcArg <- variableToSrcType arg
317 return (T.App f (args ++ [srcArg]))
320 return (T.App srcFunc [srcArg])
324 <$> variableToSrcType a
325 <*> variableToSrcType b
328 return $ T.Record [] Nothing
330 Record1 fields extension ->
331 do srcFields <- Map.toList <$> Traverse.traverse variableToSrcType fields
332 srcExt <- T.iteratedDealias <$> variableToSrcType extension
335 T.Record subFields subExt ->
336 T.Record (subFields ++ srcFields) subExt
339 T.Record srcFields (Just srcExt)
342 error "Used toSrcType on a type that is not well-formed"
346-- MANAGE FRESH VARIABLE NAMES
349data NameState = NameState
350 { _freeNames :: [String]
351 , _numberPrimes :: Int
352 , _comparablePrimes :: Int
353 , _appendablePrimes :: Int
354 , _compAppendPrimes :: Int
358makeNameState :: Set.Set String -> NameState
359makeNameState usedNames =
362 map (:suffix) ['a'..'z']
365 concatMap makeName ("" : map show [ (1 :: Int) .. ])
368 filter (\name -> Set.notMember name usedNames) allNames
370 NameState freeNames 0 0 0 0
373getFreshName :: (Monad m) => Maybe Super -> StateT NameState m String
374getFreshName maybeSuper =
377 do names <- State.gets _freeNames
378 State.modify (\state -> state { _freeNames = tail names })
382 do primes <- State.gets _numberPrimes
383 State.modify (\state -> state { _numberPrimes = primes + 1 })
384 return ("number" ++ replicate primes '\'')
387 do primes <- State.gets _comparablePrimes
388 State.modify (\state -> state { _comparablePrimes = primes + 1 })
389 return ("comparable" ++ replicate primes '\'')
392 do primes <- State.gets _appendablePrimes
393 State.modify (\state -> state { _appendablePrimes = primes + 1 })
394 return ("appendable" ++ replicate primes '\'')
397 do primes <- State.gets _compAppendPrimes
398 State.modify (\state -> state { _compAppendPrimes = primes + 1 })
399 return ("compappend" ++ replicate primes '\'')
403-- GET ALL VARIABLE NAMES
406getVarNames :: Variable -> IO (Set.Set String)
408 do desc <- UF.descriptor var
409 if _mark desc == getVarNamesMark
414 do UF.setDescriptor var (desc { _mark = getVarNamesMark })
415 getVarNamesHelp (_content desc)
418getVarNamesHelp :: Content -> IO (Set.Set String)
419getVarNamesHelp content =
421 Var _ _ (Just name) ->
422 return (Set.singleton name)
430 Alias _name args realVar ->
431 do let argSet = Set.fromList (map fst args)
432 realSet <- getVarNames realVar
433 sets <- mapM (getVarNames . snd) args
434 return (Set.unions (realSet : argSet : sets))
443getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
444getVarNamesTerm term =
445 let go = getVarNames in
448 Set.union <$> go a <*> go b
451 Set.union <$> go a <*> go b
456 Record1 fields extension ->
457 do fieldVars <- Set.unions <$> mapM go (Map.elems fields)
458 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