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.Region as R
17import Type.PrettyPrint
22type Type = TermN Variable
24type Variable = UF.Point Descriptor
26type TypeConstraint = Constraint Type Variable
28type TypeScheme = Scheme Type Variable
30type Alias a = Maybe (Var.Canonical, [(String,a)])
40 | Record1 (Map.Map String [a]) a
45 | VarN (Alias (TermN a)) a
46 | TermN (Alias (TermN a)) (Term1 (TermN a))
54termN :: (Term1 (TermN a)) -> TermN a
59record :: Map.Map String [TermN a] -> TermN a -> TermN a
61 termN (Record1 fs rec)
66data Descriptor = Descriptor
67 { structure :: Maybe (Term1 Variable)
70 , name :: Maybe TypeName
71 , copy :: Maybe Variable
73 , alias :: Alias Variable
107 | CEqual R.Region a a
108 | CAnd [Constraint a b]
109 | CLet [Scheme a b] (Constraint a b)
110 | CInstance R.Region SchemeName a
112type SchemeName = String
114type TypeName = Var.Canonical
116data Scheme a b = Scheme
117 { rigidQuantifiers :: [b]
118 , flexibleQuantifiers :: [b]
119 , constraint :: Constraint a b
120 , header :: Map.Map String a
128(==>) :: Type -> Type -> Type
133(<|) :: TermN a -> TermN a -> TermN a
140namedVar :: Flex -> Var.Canonical -> IO Variable
141namedVar flex name = UF.fresh $ Descriptor
142 { structure = Nothing
152variable :: Flex -> IO Variable
153variable flex = UF.fresh $ Descriptor
154 { structure = Nothing
166monoscheme :: Map.Map String a -> Scheme a b
168 Scheme [] [] CTrue headers
173(/\) :: Constraint a b -> Constraint a b -> Constraint a b
181-- ex qs constraint == exists qs. constraint
182ex :: [Variable] -> TypeConstraint -> TypeConstraint
184 CLet [Scheme [] fqs constraint Map.empty] CTrue
187-- fl qs constraint == forall qs. constraint
188fl :: [Variable] -> TypeConstraint -> TypeConstraint
190 CLet [Scheme rqs [] constraint Map.empty] CTrue
193exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
195 do v <- variable Flexible
196 ex [v] <$> f (varN v)
199existsNumber :: (Type -> IO TypeConstraint) -> IO TypeConstraint
201 do v <- variable (Is Number)
202 ex [v] <$> f (varN v)
205-- TYPES TO PRETTY STRINGS
207instance PrettyType a => PrettyType (UF.Point a) where
209 unsafePerformIO $ fmap (pretty when) (UF.descriptor point)
212instance PrettyType a => PrettyType (Term1 a) where
214 let prty = pretty Never in
217 parensIf needed (px <+> pretty App x)
226 parensIf needed (pretty Fn arg <+> P.text "->" <+> prty body)
239 Record1 fields ext ->
240 P.braces (extend <+> commaSep prettyFields)
245 | P.render prettyExt == "{}" =
248 prettyExt <+> P.text "|"
251 P.text f <+> P.text ":" <+> prty t
254 concatMap (\(f,ts) -> map (mkPretty f) ts) (Map.toList fields)
257instance PrettyType a => PrettyType (TermN a) where
261 error "problem prettifying type, probably indicates a bigger problem"
264 either alias (pretty when x)
267 either alias (pretty when t1)
269 either maybeAlias doc =
274 (P.text (Var.toString name))
276 (P.sep (map (pretty App . snd) args))
279instance PrettyType Descriptor where
281 case (alias desc, structure desc, name desc) of
282 (Just (name, args), _, _) ->
284 (P.text (Var.toString name))
286 (P.sep (map (pretty App . snd) args))
292 | Var.isTuple name ->
293 P.parens . P.text $ replicate (read (drop 6 (Var.toString name)) - 1) ','
295 P.text (Var.toString name)
300instance (PrettyType a, PrettyType b) => PrettyType (Constraint a b) where
301 pretty _ constraint =
302 let prty = pretty Never in
308 P.text "SaveTheEnvironment!!!"
310 CEqual _region a b ->
311 prty a <+> P.text "=" <+> prty b
317 P.parens . P.sep $ P.punctuate (P.text " and") (map (pretty Never) cs)
319 CLet [Scheme [] fqs constraint header] CTrue | Map.null header ->
320 P.sep [ binder, pretty Never c ]
324 CLet [Scheme [] fqs' c' _] CTrue -> mergeExists (vs ++ fqs') c'
327 (fqs', c) = mergeExists fqs constraint
333 P.text "\x2203" <+> P.hsep (map (pretty Never) fqs') <> P.text "."
335 CLet schemes constraint ->
337 [ P.hang (P.text "let") 4 (P.brackets . commaSep $ map (pretty Never) schemes)
338 , P.text "in", pretty Never constraint
341 CInstance _region name tipe ->
342 P.text name <+> P.text "<" <+> prty tipe
345instance (PrettyType a, PrettyType b) => PrettyType (Scheme a b) where
346 pretty _ (Scheme rqs fqs constraint headers) =
347 P.sep [ forall, cs, headers' ]
352 if null rqs && null fqs
354 else P.text "\x2200" <+> frees <+> rigids
356 frees = P.hsep (map prty fqs)
361 else P.braces . P.hsep $ map prty rqs
367 _ -> P.brackets (pretty Never constraint)
370 if Map.size headers > 0 then dict else P.empty
373 P.parens . commaSep . map prettyPair $ Map.toList headers
376 P.text n <+> P.text ":" <+> pretty Never t
379-- CONVERT TO SOURCE TYPES
381-- TODO: Attach resulting type to the descriptor so that you
382-- never have to do extra work, particularly nice for aliased types
383toSrcType :: Variable -> IO T.Canonical
386 variableToSrcType variable variable
389variableToSrcType :: Variable -> Variable -> IO T.Canonical
390variableToSrcType rootVariable variable =
391 do desc <- UF.descriptor variable
392 srcType <- maybe (backupSrcType desc) (termToSrcType rootVariable) (structure desc)
399 T.Type (Var.Canonical Var.BuiltIn _) ->
403 do args' <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType rootVariable tvar) args
404 return (T.Aliased name args' (T.Filled srcType))
406 backupSrcType :: Descriptor -> IO T.Canonical
409 Just v@(Var.Canonical _ x@(c:_))
418 [ "Problem converting the following type "
419 , "from a type-checker type to a source-syntax type:"
420 , P.render (pretty Never rootVariable)
424termToSrcType :: Variable -> Term1 Variable -> IO T.Canonical
425termToSrcType rootVariable term =
426 let go = variableToSrcType rootVariable in
433 return $ T.App f (args ++ [b'])
435 return $ T.App a' [b']
438 T.Lambda <$> go a <*> go b
444 return $ T.Record [] Nothing
446 Record1 tfields extension ->
447 do fields' <- Traverse.traverse (mapM go) tfields
448 let fields = concat [ map ((,) name) ts | (name,ts) <- Map.toList fields' ]
449 ext' <- dealias <$> go extension
452 T.Record fs ext -> T.Record (fs ++ fields) ext
453 T.Var _ -> T.Record fields (Just ext')
454 _ -> error "Used toSrcType on a type that is not well-formed"
456 dealias :: T.Canonical -> T.Canonical
459 T.Aliased _ args tipe' ->
467addNames :: Variable -> IO ()
469 do usedNames <- getVarNames variable
470 let freeNames = makeFreeNames usedNames
471 State.runStateT (varAddNames variable) (NameState freeNames 0 0 0)
475makeFreeNames :: Set.Set String -> [String]
476makeFreeNames usedNames =
477 let makeName suffix =
478 map (:suffix) ['a'..'z']
481 concatMap makeName ("" : "'" : "_" : map show [ (0 :: Int) .. ])
483 filter (\name -> Set.notMember name usedNames) allNames
486data NameState = NameState
487 { freeNames :: [String]
488 , numberPrimes :: Int
489 , comparablePrimes :: Int
490 , appendablePrimes :: Int
494varAddNames :: Variable -> StateT NameState IO ()
496 do desc <- State.liftIO (UF.descriptor var)
501 Just (_name, args) ->
502 mapM_ (\(v,t) -> (,) v <$> varAddNames t) args
504 case structure desc of
512 do name' <- createName desc
513 State.liftIO $ UF.modifyDescriptor var $ \desc ->
514 desc { name = Just (Var.local name') }
517termAddNames :: Term1 Variable -> StateT NameState IO ()
534 Record1 fields extension ->
535 do mapM_ varAddNames (concat (Map.elems fields))
536 varAddNames extension
539createName :: (Monad m) => Descriptor -> StateT NameState m String
543 do primes <- State.gets numberPrimes
544 State.modify (\state -> state { numberPrimes = primes + 1 })
545 return ("number" ++ replicate primes '\'')
548 do primes <- State.gets comparablePrimes
549 State.modify (\state -> state { comparablePrimes = primes + 1 })
550 return ("comparable" ++ replicate primes '\'')
553 do primes <- State.gets appendablePrimes
554 State.modify (\state -> state { appendablePrimes = primes + 1 })
555 return ("appendable" ++ replicate primes '\'')
558 do names <- State.gets freeNames
559 State.modify (\state -> state { freeNames = tail names })
563-- GET ALL VARIABLE NAMES
565getVarNames :: Variable -> IO (Set.Set String)
567 do desc <- UF.descriptor var
571 Just var -> Set.singleton (Var.toString var)
575 case structure desc of
576 Nothing -> return Set.empty
577 Just term -> getVarNamesTerm term
584 Just (_name, args) ->
585 do let set = Set.fromList (map fst args)
586 sets <- mapM (getVarNames . snd) args
587 return (Set.unions (set : sets))
589 return (Set.unions [ baseSet, structureSet, aliasSet ])
592getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
593getVarNamesTerm term =
594 let go = getVarNames in
597 Set.union <$> go a <*> go b
600 Set.union <$> go a <*> go b
608 Record1 fields extension ->
609 do fieldVars <- Set.unions <$> mapM go (concat (Map.elems fields))
610 Set.union fieldVars <$> go extension
613-- COLLECT APPLICATIONS
621collectApps :: Variable -> IO AppStructure
626 desc <- UF.descriptor var
627 case (structure desc, vars) of
630 Just n | Var.isList n -> return (List v)
635 Just n | Var.isTuple n -> return (Tuple vs)
640 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