3import Control.Monad.State (StateT)
4import qualified Control.Monad.State as State
5import qualified Data.Char as Char
6import qualified Data.Map as Map
7import qualified Data.Set as Set
8import qualified Data.Traversable as Traverse (traverse)
9import qualified Data.UnionFind.IO as UF
10import Text.PrettyPrint as P
11import System.IO.Unsafe
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
18import Type.PrettyPrint
23type Type = TermN Variable
25type Variable = UF.Point Descriptor
27type TypeConstraint = Constraint Type Variable
29type TypeScheme = Scheme Type Variable
31type Alias a = Maybe (Var.Canonical, [(String,a)])
41 | Record1 (Map.Map String [a]) a
46 | VarN (Alias (TermN a)) a
47 | TermN (Alias (TermN a)) (Term1 (TermN a))
55termN :: (Term1 (TermN a)) -> TermN a
60record :: Map.Map String [TermN a] -> TermN a -> TermN a
62 termN (Record1 fs rec)
67data Descriptor = Descriptor
68 { structure :: Maybe (Term1 Variable)
71 , name :: Maybe TypeName
72 , copy :: Maybe Variable
74 , alias :: Alias Variable
109 | CEqual Error.Hint R.Region a a
110 | CAnd [Constraint a b]
111 | CLet [Scheme a b] (Constraint a b)
112 | CInstance R.Region SchemeName a
114type SchemeName = String
116type TypeName = Var.Canonical
118data Scheme a b = Scheme
119 { rigidQuantifiers :: [b]
120 , flexibleQuantifiers :: [b]
121 , constraint :: Constraint a b
122 , header :: Map.Map String (A.Located a)
130(==>) :: Type -> Type -> Type
135(<|) :: TermN a -> TermN a -> TermN a
142namedVar :: Flex -> Var.Canonical -> IO Variable
143namedVar flex name = UF.fresh $ Descriptor
144 { structure = Nothing
154variable :: Flex -> IO Variable
156 UF.fresh (descriptor flex)
159descriptor :: Flex -> Descriptor
162 { structure = Nothing
174monoscheme :: Map.Map String (A.Located a) -> Scheme a b
176 Scheme [] [] CTrue headers
181(/\) :: Constraint a b -> Constraint a b -> Constraint a b
189-- ex qs constraint == exists qs. constraint
190ex :: [Variable] -> TypeConstraint -> TypeConstraint
192 CLet [Scheme [] fqs constraint Map.empty] CTrue
195-- fl qs constraint == forall qs. constraint
196fl :: [Variable] -> TypeConstraint -> TypeConstraint
198 CLet [Scheme rqs [] constraint Map.empty] CTrue
201exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
203 do v <- variable Flexible
204 ex [v] <$> f (varN v)
207existsNumber :: (Type -> IO TypeConstraint) -> IO TypeConstraint
209 do v <- variable (Is Number)
210 ex [v] <$> f (varN v)
213-- TYPES TO PRETTY STRINGS
215instance PrettyType a => PrettyType (UF.Point a) where
217 unsafePerformIO $ fmap (pretty when) (UF.descriptor point)
220instance PrettyType a => PrettyType (Term1 a) where
222 let prty = pretty Never in
225 parensIf needed (px <+> pretty App x)
234 parensIf needed (pretty Fn arg <+> P.text "->" <+> prty body)
247 Record1 fields ext ->
248 P.braces (extend <+> commaSep prettyFields)
253 | P.render prettyExt == "{}" =
256 prettyExt <+> P.text "|"
259 P.text f <+> P.text ":" <+> prty t
262 concatMap (\(f,ts) -> map (mkPretty f) ts) (Map.toList fields)
265instance PrettyType a => PrettyType (TermN a) where
269 error "problem prettifying type, probably indicates a bigger problem"
272 either alias (pretty when x)
275 either alias (pretty when t1)
277 either maybeAlias doc =
282 (P.text (Var.toString name))
284 (P.sep (map (pretty App . snd) args))
287instance PrettyType Descriptor where
289 case (alias desc, structure desc, name desc) of
290 (Just (name, args), _, _) ->
292 (P.text (Var.toString name))
294 (P.sep (map (pretty App . snd) args))
300 | Var.isTuple name ->
301 P.parens . P.text $ replicate (read (drop 6 (Var.toString name)) - 1) ','
303 P.text (Var.toString name)
308instance (PrettyType a, PrettyType b) => PrettyType (Constraint a b) where
309 pretty _ constraint =
310 let prty = pretty Never in
316 P.text "SaveTheEnvironment!!!"
319 prty a <+> P.text "=" <+> prty b
325 P.parens . P.sep $ P.punctuate (P.text " and") (map (pretty Never) cs)
327 CLet [Scheme [] fqs constraint header] CTrue | Map.null header ->
328 P.sep [ binder, pretty Never c ]
332 CLet [Scheme [] fqs' c' _] CTrue -> mergeExists (vs ++ fqs') c'
335 (fqs', c) = mergeExists fqs constraint
341 P.text "\x2203" <+> P.hsep (map (pretty Never) fqs') <> P.text "."
343 CLet schemes constraint ->
345 [ P.hang (P.text "let") 4 (P.brackets . commaSep $ map (pretty Never) schemes)
346 , P.text "in", pretty Never constraint
349 CInstance _region name tipe ->
350 P.text name <+> P.text "<" <+> prty tipe
353instance (PrettyType a, PrettyType b) => PrettyType (Scheme a b) where
354 pretty _ (Scheme rqs fqs constraint headers) =
355 P.sep [ forall, cs, headers' ]
360 if null rqs && null fqs
362 else P.text "\x2200" <+> frees <+> rigids
364 frees = P.hsep (map prty fqs)
369 else P.braces . P.hsep $ map prty rqs
375 _ -> P.brackets (pretty Never constraint)
378 if Map.size headers > 0 then dict else P.empty
381 P.parens . commaSep . map prettyPair $ Map.toList headers
383 prettyPair (fieldName, A.A _ tipe) =
384 P.text fieldName <+> P.text ":" <+> pretty Never tipe
387-- CONVERT TO SOURCE TYPES
389-- TODO: Attach resulting type to the descriptor so that you
390-- never have to do extra work, particularly nice for aliased types
391toSrcType :: Variable -> IO T.Canonical
394 variableToSrcType variable variable
397variableToSrcType :: Variable -> Variable -> IO T.Canonical
398variableToSrcType rootVariable variable =
399 do desc <- UF.descriptor variable
400 srcType <- maybe (backupSrcType desc) (termToSrcType rootVariable) (structure desc)
407 T.Type (Var.Canonical Var.BuiltIn _) ->
411 do args' <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType rootVariable tvar) args
412 return (T.Aliased name args' (T.Filled srcType))
414 backupSrcType :: Descriptor -> IO T.Canonical
417 Just v@(Var.Canonical _ x@(c:_))
426 [ "Problem converting the following type "
427 , "from a type-checker type to a source-syntax type:"
428 , P.render (pretty Never rootVariable)
432termToSrcType :: Variable -> Term1 Variable -> IO T.Canonical
433termToSrcType rootVariable term =
434 let go = variableToSrcType rootVariable in
441 return $ T.App f (args ++ [b'])
443 return $ T.App a' [b']
446 T.Lambda <$> go a <*> go b
452 return $ T.Record [] Nothing
454 Record1 tfields extension ->
455 do fields' <- Traverse.traverse (mapM go) tfields
456 let fields = concat [ map ((,) name) ts | (name,ts) <- Map.toList fields' ]
457 ext' <- dealias <$> go extension
460 T.Record fs ext -> T.Record (fs ++ fields) ext
461 T.Var _ -> T.Record fields (Just ext')
462 _ -> error "Used toSrcType on a type that is not well-formed"
464 dealias :: T.Canonical -> T.Canonical
467 T.Aliased _ args tipe' ->
475addNames :: Variable -> IO ()
477 do usedNames <- getVarNames variable
478 let freeNames = makeFreeNames usedNames
479 State.runStateT (varAddNames variable) (NameState freeNames 0 0 0)
483makeFreeNames :: Set.Set String -> [String]
484makeFreeNames usedNames =
485 let makeName suffix =
486 map (:suffix) ['a'..'z']
489 concatMap makeName ("" : "'" : "_" : map show [ (0 :: Int) .. ])
491 filter (\name -> Set.notMember name usedNames) allNames
494data NameState = NameState
495 { freeNames :: [String]
496 , numberPrimes :: Int
497 , comparablePrimes :: Int
498 , appendablePrimes :: Int
502varAddNames :: Variable -> StateT NameState IO ()
504 do desc <- State.liftIO (UF.descriptor var)
509 Just (_name, args) ->
510 mapM_ (\(v,t) -> (,) v <$> varAddNames t) args
512 case structure desc of
520 do name' <- createName desc
521 State.liftIO $ UF.modifyDescriptor var $ \desc ->
522 desc { name = Just (Var.local name') }
525termAddNames :: Term1 Variable -> StateT NameState IO ()
542 Record1 fields extension ->
543 do mapM_ varAddNames (concat (Map.elems fields))
544 varAddNames extension
547createName :: (Monad m) => Descriptor -> StateT NameState m String
551 do primes <- State.gets numberPrimes
552 State.modify (\state -> state { numberPrimes = primes + 1 })
553 return ("number" ++ replicate primes '\'')
556 do primes <- State.gets comparablePrimes
557 State.modify (\state -> state { comparablePrimes = primes + 1 })
558 return ("comparable" ++ replicate primes '\'')
561 do primes <- State.gets appendablePrimes
562 State.modify (\state -> state { appendablePrimes = primes + 1 })
563 return ("appendable" ++ replicate primes '\'')
566 do names <- State.gets freeNames
567 State.modify (\state -> state { freeNames = tail names })
571-- GET ALL VARIABLE NAMES
573getVarNames :: Variable -> IO (Set.Set String)
575 do desc <- UF.descriptor var
579 Just var -> Set.singleton (Var.toString var)
583 case structure desc of
584 Nothing -> return Set.empty
585 Just term -> getVarNamesTerm term
592 Just (_name, args) ->
593 do let set = Set.fromList (map fst args)
594 sets <- mapM (getVarNames . snd) args
595 return (Set.unions (set : sets))
597 return (Set.unions [ baseSet, structureSet, aliasSet ])
600getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
601getVarNamesTerm term =
602 let go = getVarNames in
605 Set.union <$> go a <*> go b
608 Set.union <$> go a <*> go b
616 Record1 fields extension ->
617 do fieldVars <- Set.unions <$> mapM go (concat (Map.elems fields))
618 Set.union fieldVars <$> go extension
621-- COLLECT APPLICATIONS
629collectApps :: Variable -> IO AppStructure
634 desc <- UF.descriptor var
635 case (structure desc, vars) of
638 Just n | Var.isList n -> return (List v)
643 Just n | Var.isTuple n -> return (Tuple vs)
648 App1 a b -> go (vars ++ [b]) a
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