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.Annotation as A
17import qualified Reporting.Error.Type as Error
18import qualified Reporting.Region as R
19import Type.PrettyPrint
24type Type = TermN Variable
26type Variable = UF.Point Descriptor
28type TypeConstraint = Constraint Type Variable
30type TypeScheme = Scheme Type Variable
32type Alias a = Maybe (Var.Canonical, [(String,a)])
42 | Record1 (Map.Map String [a]) a
47 | VarN (Alias (TermN a)) a
48 | TermN (Alias (TermN a)) (Term1 (TermN a))
56termN :: (Term1 (TermN a)) -> TermN a
61record :: Map.Map String [TermN a] -> TermN a -> TermN a
63 termN (Record1 fs rec)
68data Descriptor = Descriptor
69 { structure :: Maybe (Term1 Variable)
72 , name :: Maybe TypeName
73 , copy :: Maybe Variable
75 , alias :: Alias Variable
110 | CEqual Error.Hint R.Region a a
111 | CAnd [Constraint a b]
112 | CLet [Scheme a b] (Constraint a b)
113 | CInstance R.Region SchemeName a
115type SchemeName = String
117type TypeName = Var.Canonical
119data Scheme a b = Scheme
120 { rigidQuantifiers :: [b]
121 , flexibleQuantifiers :: [b]
122 , constraint :: Constraint a b
123 , header :: Map.Map String (A.Located a)
131(==>) :: Type -> Type -> Type
136(<|) :: TermN a -> TermN a -> TermN a
143namedVar :: Flex -> Var.Canonical -> IO Variable
144namedVar flex name = UF.fresh $ Descriptor
145 { structure = Nothing
155variable :: Flex -> IO Variable
157 UF.fresh (descriptor flex)
160descriptor :: Flex -> Descriptor
163 { structure = Nothing
175monoscheme :: Map.Map String (A.Located a) -> Scheme a b
177 Scheme [] [] CTrue headers
182(/\) :: Constraint a b -> Constraint a b -> Constraint a b
190-- ex qs constraint == exists qs. constraint
191ex :: [Variable] -> TypeConstraint -> TypeConstraint
193 CLet [Scheme [] fqs constraint Map.empty] CTrue
196-- fl qs constraint == forall qs. constraint
197fl :: [Variable] -> TypeConstraint -> TypeConstraint
199 CLet [Scheme rqs [] constraint Map.empty] CTrue
202exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
204 do v <- variable Flexible
205 ex [v] <$> f (varN v)
208existsNumber :: (Type -> IO TypeConstraint) -> IO TypeConstraint
210 do v <- variable (Is Number)
211 ex [v] <$> f (varN v)
214-- TYPES TO PRETTY STRINGS
216instance PrettyType a => PrettyType (UF.Point a) where
218 unsafePerformIO $ fmap (pretty when) (UF.descriptor point)
221instance PrettyType a => PrettyType (Term1 a) where
223 let prty = pretty Never in
226 parensIf needed (px <+> pretty App x)
235 parensIf needed (pretty Fn arg <+> P.text "->" <+> prty body)
248 Record1 fields ext ->
249 P.braces (extend <+> commaSep prettyFields)
254 | P.render prettyExt == "{}" =
257 prettyExt <+> P.text "|"
260 P.text f <+> P.text ":" <+> prty t
263 concatMap (\(f,ts) -> map (mkPretty f) ts) (Map.toList fields)
266instance PrettyType a => PrettyType (TermN a) where
270 error "problem prettifying type, probably indicates a bigger problem"
273 either alias (pretty when x)
276 either alias (pretty when t1)
278 either maybeAlias doc =
283 (P.text (Var.toString name))
285 (P.sep (map (pretty App . snd) args))
288instance PrettyType Descriptor where
290 case (alias desc, structure desc, name desc) of
291 (Just (name, args), _, _) ->
293 (P.text (Var.toString name))
295 (P.sep (map (pretty App . snd) args))
301 | Var.isTuple name ->
302 P.parens . P.text $ replicate (read (drop 6 (Var.toString name)) - 1) ','
304 P.text (Var.toString name)
309instance (PrettyType a, PrettyType b) => PrettyType (Constraint a b) where
310 pretty _ constraint =
311 let prty = pretty Never in
317 P.text "SaveTheEnvironment!!!"
320 prty a <+> P.text "=" <+> prty b
326 P.parens . P.sep $ P.punctuate (P.text " and") (map (pretty Never) cs)
328 CLet [Scheme [] fqs constraint header] CTrue | Map.null header ->
329 P.sep [ binder, pretty Never c ]
333 CLet [Scheme [] fqs' c' _] CTrue -> mergeExists (vs ++ fqs') c'
336 (fqs', c) = mergeExists fqs constraint
342 P.text "\x2203" <+> P.hsep (map (pretty Never) fqs') <> P.text "."
344 CLet schemes constraint ->
346 [ P.hang (P.text "let") 4 (P.brackets . commaSep $ map (pretty Never) schemes)
347 , P.text "in", pretty Never constraint
350 CInstance _region name tipe ->
351 P.text name <+> P.text "<" <+> prty tipe
354instance (PrettyType a, PrettyType b) => PrettyType (Scheme a b) where
355 pretty _ (Scheme rqs fqs constraint headers) =
356 P.sep [ forall, cs, headers' ]
361 if null rqs && null fqs
363 else P.text "\x2200" <+> frees <+> rigids
365 frees = P.hsep (map prty fqs)
370 else P.braces . P.hsep $ map prty rqs
376 _ -> P.brackets (pretty Never constraint)
379 if Map.size headers > 0 then dict else P.empty
382 P.parens . commaSep . map prettyPair $ Map.toList headers
384 prettyPair (fieldName, A.A _ tipe) =
385 P.text fieldName <+> P.text ":" <+> pretty Never tipe
388-- CONVERT TO SOURCE TYPES
390-- TODO: Attach resulting type to the descriptor so that you
391-- never have to do extra work, particularly nice for aliased types
392toSrcType :: Variable -> IO T.Canonical
395 variableToSrcType variable variable
398variableToSrcType :: Variable -> Variable -> IO T.Canonical
399variableToSrcType rootVariable variable =
400 do desc <- UF.descriptor variable
401 srcType <- maybe (backupSrcType desc) (termToSrcType rootVariable) (structure desc)
408 T.Type (Var.Canonical Var.BuiltIn _) ->
412 do args' <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType rootVariable tvar) args
413 return (T.Aliased name args' (T.Filled srcType))
415 backupSrcType :: Descriptor -> IO T.Canonical
418 Just v@(Var.Canonical _ x@(c:_))
427 [ "Problem converting the following type "
428 , "from a type-checker type to a source-syntax type:"
429 , P.render (pretty Never rootVariable)
433termToSrcType :: Variable -> Term1 Variable -> IO T.Canonical
434termToSrcType rootVariable term =
435 let go = variableToSrcType rootVariable in
442 return $ T.App f (args ++ [b'])
444 return $ T.App a' [b']
447 T.Lambda <$> go a <*> go b
453 return $ T.Record [] Nothing
455 Record1 tfields extension ->
456 do fields' <- Traverse.traverse (mapM go) tfields
457 let fields = concat [ map ((,) name) ts | (name,ts) <- Map.toList fields' ]
458 ext' <- dealias <$> go extension
461 T.Record fs ext -> T.Record (fs ++ fields) ext
462 T.Var _ -> T.Record fields (Just ext')
463 _ -> error "Used toSrcType on a type that is not well-formed"
465 dealias :: T.Canonical -> T.Canonical
468 T.Aliased _ args tipe' ->
476addNames :: Variable -> IO ()
478 do usedNames <- getVarNames variable
479 let freeNames = makeFreeNames usedNames
480 State.runStateT (varAddNames variable) (NameState freeNames 0 0 0)
484makeFreeNames :: Set.Set String -> [String]
485makeFreeNames usedNames =
486 let makeName suffix =
487 map (:suffix) ['a'..'z']
490 concatMap makeName ("" : "'" : "_" : map show [ (0 :: Int) .. ])
492 filter (\name -> Set.notMember name usedNames) allNames
495data NameState = NameState
496 { freeNames :: [String]
497 , numberPrimes :: Int
498 , comparablePrimes :: Int
499 , appendablePrimes :: Int
503varAddNames :: Variable -> StateT NameState IO ()
505 do desc <- State.liftIO (UF.descriptor var)
510 Just (_name, args) ->
511 mapM_ (\(v,t) -> (,) v <$> varAddNames t) args
513 case structure desc of
521 do name' <- createName desc
522 State.liftIO $ UF.modifyDescriptor var $ \desc ->
523 desc { name = Just (Var.local name') }
526termAddNames :: Term1 Variable -> StateT NameState IO ()
543 Record1 fields extension ->
544 do mapM_ varAddNames (concat (Map.elems fields))
545 varAddNames extension
548createName :: (Monad m) => Descriptor -> StateT NameState m String
552 do primes <- State.gets numberPrimes
553 State.modify (\state -> state { numberPrimes = primes + 1 })
554 return ("number" ++ replicate primes '\'')
557 do primes <- State.gets comparablePrimes
558 State.modify (\state -> state { comparablePrimes = primes + 1 })
559 return ("comparable" ++ replicate primes '\'')
562 do primes <- State.gets appendablePrimes
563 State.modify (\state -> state { appendablePrimes = primes + 1 })
564 return ("appendable" ++ replicate primes '\'')
567 do names <- State.gets freeNames
568 State.modify (\state -> state { freeNames = tail names })
572-- GET ALL VARIABLE NAMES
574getVarNames :: Variable -> IO (Set.Set String)
576 do desc <- UF.descriptor var
580 Just var -> Set.singleton (Var.toString var)
584 case structure desc of
585 Nothing -> return Set.empty
586 Just term -> getVarNamesTerm term
593 Just (_name, args) ->
594 do let set = Set.fromList (map fst args)
595 sets <- mapM (getVarNames . snd) args
596 return (Set.unions (set : sets))
598 return (Set.unions [ baseSet, structureSet, aliasSet ])
601getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
602getVarNamesTerm term =
603 let go = getVarNames in
606 Set.union <$> go a <*> go b
609 Set.union <$> go a <*> go b
617 Record1 fields extension ->
618 do fieldVars <- Set.unions <$> mapM go (concat (Map.elems fields))
619 Set.union fieldVars <$> go extension
622-- COLLECT APPLICATIONS
630collectApps :: Variable -> IO AppStructure
635 desc <- UF.descriptor var
636 case (structure desc, vars) of
639 Just n | Var.isList n -> return (List v)
644 Just n | Var.isTuple n -> return (Tuple vs)
649 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