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 let mark = _mark descriptor
270 if mark == occursMark
275 do liftIO $ UF.modifyDescriptor variable (\desc -> desc { _mark = occursMark })
276 srcType <- contentToSrcType variable (_content descriptor)
277 liftIO $ UF.modifyDescriptor variable (\desc -> desc { _mark = mark })
281contentToSrcType :: Variable -> Content -> StateT NameState IO T.Canonical
282contentToSrcType variable content =
290 Var _ _ (Just name) ->
293 Var flex maybeSuper Nothing ->
294 do freshName <- getFreshName maybeSuper
295 liftIO $ UF.modifyDescriptor variable $ \desc ->
296 desc { _content = Var flex maybeSuper (Just freshName) }
297 return (T.Var freshName)
299 Alias name args realVariable ->
300 do srcArgs <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType tvar) args
301 srcType <- variableToSrcType realVariable
302 return (T.Aliased name srcArgs (T.Filled srcType))
308termToSrcType :: Term1 Variable -> StateT NameState IO T.Canonical
312 do srcFunc <- variableToSrcType func
313 srcArg <- variableToSrcType arg
316 return (T.App f (args ++ [srcArg]))
319 return (T.App srcFunc [srcArg])
323 <$> variableToSrcType a
324 <*> variableToSrcType b
327 return $ T.Record [] Nothing
329 Record1 fields extension ->
330 do srcFields <- Map.toList <$> Traverse.traverse variableToSrcType fields
331 srcExt <- T.iteratedDealias <$> variableToSrcType extension
334 T.Record subFields subExt ->
335 T.Record (subFields ++ srcFields) subExt
338 T.Record srcFields (Just srcExt)
341 error "Used toSrcType on a type that is not well-formed"
345-- MANAGE FRESH VARIABLE NAMES
348data NameState = NameState
349 { _freeNames :: [String]
350 , _numberPrimes :: Int
351 , _comparablePrimes :: Int
352 , _appendablePrimes :: Int
353 , _compAppendPrimes :: Int
357makeNameState :: Set.Set String -> NameState
358makeNameState usedNames =
361 map (:suffix) ['a'..'z']
364 concatMap makeName ("" : map show [ (1 :: Int) .. ])
367 filter (\name -> Set.notMember name usedNames) allNames
369 NameState freeNames 0 0 0 0
372getFreshName :: (Monad m) => Maybe Super -> StateT NameState m String
373getFreshName maybeSuper =
376 do names <- State.gets _freeNames
377 State.modify (\state -> state { _freeNames = tail names })
381 do primes <- State.gets _numberPrimes
382 State.modify (\state -> state { _numberPrimes = primes + 1 })
383 return ("number" ++ replicate primes '\'')
386 do primes <- State.gets _comparablePrimes
387 State.modify (\state -> state { _comparablePrimes = primes + 1 })
388 return ("comparable" ++ replicate primes '\'')
391 do primes <- State.gets _appendablePrimes
392 State.modify (\state -> state { _appendablePrimes = primes + 1 })
393 return ("appendable" ++ replicate primes '\'')
396 do primes <- State.gets _compAppendPrimes
397 State.modify (\state -> state { _compAppendPrimes = primes + 1 })
398 return ("compappend" ++ replicate primes '\'')
402-- GET ALL VARIABLE NAMES
405getVarNames :: Variable -> IO (Set.Set String)
407 do desc <- UF.descriptor var
408 if _mark desc == getVarNamesMark
413 do UF.setDescriptor var (desc { _mark = getVarNamesMark })
414 getVarNamesHelp (_content desc)
417getVarNamesHelp :: Content -> IO (Set.Set String)
418getVarNamesHelp content =
420 Var _ _ (Just name) ->
421 return (Set.singleton name)
429 Alias _name args realVar ->
430 do let argSet = Set.fromList (map fst args)
431 realSet <- getVarNames realVar
432 sets <- mapM (getVarNames . snd) args
433 return (Set.unions (realSet : argSet : sets))
442getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
443getVarNamesTerm term =
444 let go = getVarNames in
447 Set.union <$> go a <*> go b
450 Set.union <$> go a <*> go b
455 Record1 fields extension ->
456 do fieldVars <- Set.unions <$> mapM go (Map.elems fields)
457 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