1{-# OPTIONS_GHC -Wall #-}
4import Control.Monad.State (StateT)
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
118 | CEqual Error.Hint R.Region a a
119 | CAnd [Constraint a b]
120 | CLet [Scheme a b] (Constraint a b)
121 | CInstance R.Region SchemeName a
124type SchemeName = String
127data Scheme a b = Scheme
128 { _rigidQuantifiers :: [b]
129 , _flexibleQuantifiers :: [b]
130 , _constraint :: Constraint a b
131 , _header :: Map.Map String (A.Located a)
142(==>) :: Type -> Type -> Type
147(<|) :: TermN a -> TermN a -> TermN a
156mkDescriptor :: Content -> Descriptor
157mkDescriptor content =
166mkAtom :: Var.Canonical -> IO Variable
168 UF.fresh $ mkDescriptor (Atom name)
171mkVar :: Maybe Super -> IO Variable
173 UF.fresh $ mkDescriptor (Var Flex maybeSuper Nothing)
176mkNamedVar :: String -> IO Variable
178 UF.fresh $ mkDescriptor (Var Flex (toSuper name) Nothing)
181mkRigid :: String -> IO Variable
183 UF.fresh $ mkDescriptor (Var Rigid (toSuper name) (Just name))
186toSuper :: String -> Maybe Super
188 if List.isPrefixOf "number" name then
191 else if List.isPrefixOf "comparable" name then
194 else if List.isPrefixOf "appendable" name then
205monoscheme :: Map.Map String (A.Located a) -> Scheme a b
207 Scheme [] [] CTrue headers
212(/\) :: Constraint a b -> Constraint a b -> Constraint a b
220-- ex qs constraint == exists qs. constraint
221ex :: [Variable] -> TypeConstraint -> TypeConstraint
223 CLet [Scheme [] fqs constraint Map.empty] CTrue
226-- fl qs constraint == forall qs. constraint
227fl :: [Variable] -> TypeConstraint -> TypeConstraint
229 CLet [Scheme rqs [] constraint Map.empty] CTrue
232exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
234 do v <- mkVar Nothing
235 ex [v] <$> f (VarN v)
238existsNumber :: (Type -> IO TypeConstraint) -> IO TypeConstraint
240 do v <- mkVar (Just Number)
241 ex [v] <$> f (VarN v)
245-- CONVERT TO SOURCE TYPES
248-- TODO: Attach resulting type to the descriptor so that you
249-- never have to do extra work, particularly nice for aliased types
250toSrcType :: Variable -> IO T.Canonical
252 do usedNames <- getVarNames variable
253 State.evalStateT (variableToSrcType variable) (makeNameState usedNames)
256variableToSrcType :: Variable -> StateT NameState IO T.Canonical
257variableToSrcType variable =
258 do descriptor <- State.liftIO (UF.descriptor variable)
259 case _content descriptor of
266 Var _ _ (Just name) ->
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)
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))
284termToSrcType :: Term1 Variable -> StateT NameState IO T.Canonical
288 do srcFunc <- variableToSrcType func
289 srcArg <- variableToSrcType arg
292 return (T.App f (args ++ [srcArg]))
295 return (T.App srcFunc [srcArg])
299 <$> variableToSrcType a
300 <*> variableToSrcType b
303 return $ T.Record [] Nothing
305 Record1 fields extension ->
306 do srcFields <- Map.toList <$> Traverse.traverse variableToSrcType fields
307 srcExt <- T.iteratedDealias <$> variableToSrcType extension
310 T.Record subFields subExt ->
311 T.Record (subFields ++ srcFields) subExt
314 T.Record srcFields (Just srcExt)
317 error "Used toSrcType on a type that is not well-formed"
321-- MANAGE FRESH VARIABLE NAMES
324data NameState = NameState
325 { _freeNames :: [String]
326 , _numberPrimes :: Int
327 , _comparablePrimes :: Int
328 , _appendablePrimes :: Int
329 , _compAppendPrimes :: Int
333makeNameState :: Set.Set String -> NameState
334makeNameState usedNames =
337 map (:suffix) ['a'..'z']
340 concatMap makeName ("" : map show [ (1 :: Int) .. ])
343 filter (\name -> Set.notMember name usedNames) allNames
345 NameState freeNames 0 0 0 0
348getFreshName :: (Monad m) => Maybe Super -> StateT NameState m String
349getFreshName maybeSuper =
352 do names <- State.gets _freeNames
353 State.modify (\state -> state { _freeNames = tail names })
357 do primes <- State.gets _numberPrimes
358 State.modify (\state -> state { _numberPrimes = primes + 1 })
359 return ("number" ++ replicate primes '\'')
362 do primes <- State.gets _comparablePrimes
363 State.modify (\state -> state { _comparablePrimes = primes + 1 })
364 return ("comparable" ++ replicate primes '\'')
367 do primes <- State.gets _appendablePrimes
368 State.modify (\state -> state { _appendablePrimes = primes + 1 })
369 return ("appendable" ++ replicate primes '\'')
372 do primes <- State.gets _compAppendPrimes
373 State.modify (\state -> state { _compAppendPrimes = primes + 1 })
374 return ("compappend" ++ replicate primes '\'')
378-- GET ALL VARIABLE NAMES
381getVarNames :: Variable -> IO (Set.Set String)
383 do desc <- UF.descriptor var
385 case _content desc of
386 Var _ _ (Just name) ->
387 return (Set.singleton name)
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))
408getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
409getVarNamesTerm term =
410 let go = getVarNames in
413 Set.union <$> go a <*> go b
416 Set.union <$> go a <*> go b
421 Record1 fields extension ->
422 do fieldVars <- Set.unions <$> mapM go (Map.elems fields)
423 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