3import Control.Applicative ((<$>),(<*>))
4import Control.Monad.State (StateT)
5import qualified Control.Monad.State as State
6import qualified Data.Char as Char
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
11import Text.PrettyPrint as P
12import System.IO.Unsafe
14import qualified AST.Type as T
15import qualified AST.Variable as Var
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
108 | CEqual Error.Hint R.Region a a
109 | CAnd [Constraint a b]
110 | CLet [Scheme a b] (Constraint a b)
111 | CInstance R.Region SchemeName a
113type SchemeName = String
115type TypeName = Var.Canonical
117data Scheme a b = Scheme
118 { rigidQuantifiers :: [b]
119 , flexibleQuantifiers :: [b]
120 , constraint :: Constraint a b
121 , header :: Map.Map String a
129(==>) :: Type -> Type -> Type
134(<|) :: TermN a -> TermN a -> TermN a
141namedVar :: Flex -> Var.Canonical -> IO Variable
142namedVar flex name = UF.fresh $ Descriptor
143 { structure = Nothing
153variable :: Flex -> IO Variable
154variable flex = UF.fresh $ Descriptor
155 { structure = Nothing
167monoscheme :: Map.Map String a -> Scheme a b
169 Scheme [] [] CTrue headers
174(/\) :: Constraint a b -> Constraint a b -> Constraint a b
182-- ex qs constraint == exists qs. constraint
183ex :: [Variable] -> TypeConstraint -> TypeConstraint
185 CLet [Scheme [] fqs constraint Map.empty] CTrue
188-- fl qs constraint == forall qs. constraint
189fl :: [Variable] -> TypeConstraint -> TypeConstraint
191 CLet [Scheme rqs [] constraint Map.empty] CTrue
194exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
196 do v <- variable Flexible
197 ex [v] <$> f (varN v)
200existsNumber :: (Type -> IO TypeConstraint) -> IO TypeConstraint
202 do v <- variable (Is Number)
203 ex [v] <$> f (varN v)
206-- TYPES TO PRETTY STRINGS
208instance PrettyType a => PrettyType (UF.Point a) where
210 unsafePerformIO $ fmap (pretty when) (UF.descriptor point)
213instance PrettyType a => PrettyType (Term1 a) where
215 let prty = pretty Never in
218 parensIf needed (px <+> pretty App x)
227 parensIf needed (pretty Fn arg <+> P.text "->" <+> prty body)
240 Record1 fields ext ->
241 P.braces (extend <+> commaSep prettyFields)
246 | P.render prettyExt == "{}" =
249 prettyExt <+> P.text "|"
252 P.text f <+> P.text ":" <+> prty t
255 concatMap (\(f,ts) -> map (mkPretty f) ts) (Map.toList fields)
258instance PrettyType a => PrettyType (TermN a) where
262 error "problem prettifying type, probably indicates a bigger problem"
265 either alias (pretty when x)
268 either alias (pretty when t1)
270 either maybeAlias doc =
275 (P.text (Var.toString name))
277 (P.sep (map (pretty App . snd) args))
280instance PrettyType Descriptor where
282 case (alias desc, structure desc, name desc) of
283 (Just (name, args), _, _) ->
285 (P.text (Var.toString name))
287 (P.sep (map (pretty App . snd) args))
293 | Var.isTuple name ->
294 P.parens . P.text $ replicate (read (drop 6 (Var.toString name)) - 1) ','
296 P.text (Var.toString name)
301instance (PrettyType a, PrettyType b) => PrettyType (Constraint a b) where
302 pretty _ constraint =
303 let prty = pretty Never in
309 P.text "SaveTheEnvironment!!!"
312 prty a <+> P.text "=" <+> prty b
318 P.parens . P.sep $ P.punctuate (P.text " and") (map (pretty Never) cs)
320 CLet [Scheme [] fqs constraint header] CTrue | Map.null header ->
321 P.sep [ binder, pretty Never c ]
325 CLet [Scheme [] fqs' c' _] CTrue -> mergeExists (vs ++ fqs') c'
328 (fqs', c) = mergeExists fqs constraint
334 P.text "\x2203" <+> P.hsep (map (pretty Never) fqs') <> P.text "."
336 CLet schemes constraint ->
338 [ P.hang (P.text "let") 4 (P.brackets . commaSep $ map (pretty Never) schemes)
339 , P.text "in", pretty Never constraint
342 CInstance _region name tipe ->
343 P.text name <+> P.text "<" <+> prty tipe
346instance (PrettyType a, PrettyType b) => PrettyType (Scheme a b) where
347 pretty _ (Scheme rqs fqs constraint headers) =
348 P.sep [ forall, cs, headers' ]
353 if null rqs && null fqs
355 else P.text "\x2200" <+> frees <+> rigids
357 frees = P.hsep (map prty fqs)
362 else P.braces . P.hsep $ map prty rqs
368 _ -> P.brackets (pretty Never constraint)
371 if Map.size headers > 0 then dict else P.empty
374 P.parens . commaSep . map prettyPair $ Map.toList headers
377 P.text n <+> P.text ":" <+> pretty Never t
380-- CONVERT TO SOURCE TYPES
382-- TODO: Attach resulting type to the descriptor so that you
383-- never have to do extra work, particularly nice for aliased types
384toSrcType :: Variable -> IO T.Canonical
387 variableToSrcType variable variable
390variableToSrcType :: Variable -> Variable -> IO T.Canonical
391variableToSrcType rootVariable variable =
392 do desc <- UF.descriptor variable
393 srcType <- maybe (backupSrcType desc) (termToSrcType rootVariable) (structure desc)
400 T.Type (Var.Canonical Var.BuiltIn _) ->
404 do args' <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType rootVariable tvar) args
405 return (T.Aliased name args' (T.Filled srcType))
407 backupSrcType :: Descriptor -> IO T.Canonical
410 Just v@(Var.Canonical _ x@(c:_))
419 [ "Problem converting the following type "
420 , "from a type-checker type to a source-syntax type:"
421 , P.render (pretty Never rootVariable)
425termToSrcType :: Variable -> Term1 Variable -> IO T.Canonical
426termToSrcType rootVariable term =
427 let go = variableToSrcType rootVariable in
434 return $ T.App f (args ++ [b'])
436 return $ T.App a' [b']
439 T.Lambda <$> go a <*> go b
445 return $ T.Record [] Nothing
447 Record1 tfields extension ->
448 do fields' <- Traverse.traverse (mapM go) tfields
449 let fields = concat [ map ((,) name) ts | (name,ts) <- Map.toList fields' ]
450 ext' <- dealias <$> go extension
453 T.Record fs ext -> T.Record (fs ++ fields) ext
454 T.Var _ -> T.Record fields (Just ext')
455 _ -> error "Used toSrcType on a type that is not well-formed"
457 dealias :: T.Canonical -> T.Canonical
460 T.Aliased _ args tipe' ->
468addNames :: Variable -> IO ()
470 do usedNames <- getVarNames variable
471 let freeNames = makeFreeNames usedNames
472 State.runStateT (varAddNames variable) (NameState freeNames 0 0 0)
476makeFreeNames :: Set.Set String -> [String]
477makeFreeNames usedNames =
478 let makeName suffix =
479 map (:suffix) ['a'..'z']
482 concatMap makeName ("" : "'" : "_" : map show [ (0 :: Int) .. ])
484 filter (\name -> Set.notMember name usedNames) allNames
487data NameState = NameState
488 { freeNames :: [String]
489 , numberPrimes :: Int
490 , comparablePrimes :: Int
491 , appendablePrimes :: Int
495varAddNames :: Variable -> StateT NameState IO ()
497 do desc <- State.liftIO (UF.descriptor var)
502 Just (_name, args) ->
503 mapM_ (\(v,t) -> (,) v <$> varAddNames t) args
505 case structure desc of
513 do name' <- createName desc
514 State.liftIO $ UF.modifyDescriptor var $ \desc ->
515 desc { name = Just (Var.local name') }
518termAddNames :: Term1 Variable -> StateT NameState IO ()
535 Record1 fields extension ->
536 do mapM_ varAddNames (concat (Map.elems fields))
537 varAddNames extension
540createName :: (Monad m) => Descriptor -> StateT NameState m String
544 do primes <- State.gets numberPrimes
545 State.modify (\state -> state { numberPrimes = primes + 1 })
546 return ("number" ++ replicate primes '\'')
549 do primes <- State.gets comparablePrimes
550 State.modify (\state -> state { comparablePrimes = primes + 1 })
551 return ("comparable" ++ replicate primes '\'')
554 do primes <- State.gets appendablePrimes
555 State.modify (\state -> state { appendablePrimes = primes + 1 })
556 return ("appendable" ++ replicate primes '\'')
559 do names <- State.gets freeNames
560 State.modify (\state -> state { freeNames = tail names })
564-- GET ALL VARIABLE NAMES
566getVarNames :: Variable -> IO (Set.Set String)
568 do desc <- UF.descriptor var
572 Just var -> Set.singleton (Var.toString var)
576 case structure desc of
577 Nothing -> return Set.empty
578 Just term -> getVarNamesTerm term
585 Just (_name, args) ->
586 do let set = Set.fromList (map fst args)
587 sets <- mapM (getVarNames . snd) args
588 return (Set.unions (set : sets))
590 return (Set.unions [ baseSet, structureSet, aliasSet ])
593getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
594getVarNamesTerm term =
595 let go = getVarNames in
598 Set.union <$> go a <*> go b
601 Set.union <$> go a <*> go b
609 Record1 fields extension ->
610 do fieldVars <- Set.unions <$> mapM go (concat (Map.elems fields))
611 Set.union fieldVars <$> go extension
614-- COLLECT APPLICATIONS
622collectApps :: Variable -> IO AppStructure
627 desc <- UF.descriptor var
628 case (structure desc, vars) of
631 Just n | Var.isList n -> return (List v)
636 Just n | Var.isTuple n -> return (Tuple vs)
641 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