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
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
155variable flex = UF.fresh $ Descriptor
156 { structure = Nothing
168monoscheme :: Map.Map String (A.Located a) -> Scheme a b
170 Scheme [] [] CTrue headers
175(/\) :: Constraint a b -> Constraint a b -> Constraint a b
183-- ex qs constraint == exists qs. constraint
184ex :: [Variable] -> TypeConstraint -> TypeConstraint
186 CLet [Scheme [] fqs constraint Map.empty] CTrue
189-- fl qs constraint == forall qs. constraint
190fl :: [Variable] -> TypeConstraint -> TypeConstraint
192 CLet [Scheme rqs [] constraint Map.empty] CTrue
195exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
197 do v <- variable Flexible
198 ex [v] <$> f (varN v)
201existsNumber :: (Type -> IO TypeConstraint) -> IO TypeConstraint
203 do v <- variable (Is Number)
204 ex [v] <$> f (varN v)
207-- TYPES TO PRETTY STRINGS
209instance PrettyType a => PrettyType (UF.Point a) where
211 unsafePerformIO $ fmap (pretty when) (UF.descriptor point)
214instance PrettyType a => PrettyType (Term1 a) where
216 let prty = pretty Never in
219 parensIf needed (px <+> pretty App x)
228 parensIf needed (pretty Fn arg <+> P.text "->" <+> prty body)
241 Record1 fields ext ->
242 P.braces (extend <+> commaSep prettyFields)
247 | P.render prettyExt == "{}" =
250 prettyExt <+> P.text "|"
253 P.text f <+> P.text ":" <+> prty t
256 concatMap (\(f,ts) -> map (mkPretty f) ts) (Map.toList fields)
259instance PrettyType a => PrettyType (TermN a) where
263 error "problem prettifying type, probably indicates a bigger problem"
266 either alias (pretty when x)
269 either alias (pretty when t1)
271 either maybeAlias doc =
276 (P.text (Var.toString name))
278 (P.sep (map (pretty App . snd) args))
281instance PrettyType Descriptor where
283 case (alias desc, structure desc, name desc) of
284 (Just (name, args), _, _) ->
286 (P.text (Var.toString name))
288 (P.sep (map (pretty App . snd) args))
294 | Var.isTuple name ->
295 P.parens . P.text $ replicate (read (drop 6 (Var.toString name)) - 1) ','
297 P.text (Var.toString name)
302instance (PrettyType a, PrettyType b) => PrettyType (Constraint a b) where
303 pretty _ constraint =
304 let prty = pretty Never in
310 P.text "SaveTheEnvironment!!!"
313 prty a <+> P.text "=" <+> prty b
319 P.parens . P.sep $ P.punctuate (P.text " and") (map (pretty Never) cs)
321 CLet [Scheme [] fqs constraint header] CTrue | Map.null header ->
322 P.sep [ binder, pretty Never c ]
326 CLet [Scheme [] fqs' c' _] CTrue -> mergeExists (vs ++ fqs') c'
329 (fqs', c) = mergeExists fqs constraint
335 P.text "\x2203" <+> P.hsep (map (pretty Never) fqs') <> P.text "."
337 CLet schemes constraint ->
339 [ P.hang (P.text "let") 4 (P.brackets . commaSep $ map (pretty Never) schemes)
340 , P.text "in", pretty Never constraint
343 CInstance _region name tipe ->
344 P.text name <+> P.text "<" <+> prty tipe
347instance (PrettyType a, PrettyType b) => PrettyType (Scheme a b) where
348 pretty _ (Scheme rqs fqs constraint headers) =
349 P.sep [ forall, cs, headers' ]
354 if null rqs && null fqs
356 else P.text "\x2200" <+> frees <+> rigids
358 frees = P.hsep (map prty fqs)
363 else P.braces . P.hsep $ map prty rqs
369 _ -> P.brackets (pretty Never constraint)
372 if Map.size headers > 0 then dict else P.empty
375 P.parens . commaSep . map prettyPair $ Map.toList headers
377 prettyPair (fieldName, A.A _ tipe) =
378 P.text fieldName <+> P.text ":" <+> pretty Never tipe
381-- CONVERT TO SOURCE TYPES
383-- TODO: Attach resulting type to the descriptor so that you
384-- never have to do extra work, particularly nice for aliased types
385toSrcType :: Variable -> IO T.Canonical
388 variableToSrcType variable variable
391variableToSrcType :: Variable -> Variable -> IO T.Canonical
392variableToSrcType rootVariable variable =
393 do desc <- UF.descriptor variable
394 srcType <- maybe (backupSrcType desc) (termToSrcType rootVariable) (structure desc)
401 T.Type (Var.Canonical Var.BuiltIn _) ->
405 do args' <- mapM (\(arg,tvar) -> (,) arg <$> variableToSrcType rootVariable tvar) args
406 return (T.Aliased name args' (T.Filled srcType))
408 backupSrcType :: Descriptor -> IO T.Canonical
411 Just v@(Var.Canonical _ x@(c:_))
420 [ "Problem converting the following type "
421 , "from a type-checker type to a source-syntax type:"
422 , P.render (pretty Never rootVariable)
426termToSrcType :: Variable -> Term1 Variable -> IO T.Canonical
427termToSrcType rootVariable term =
428 let go = variableToSrcType rootVariable in
435 return $ T.App f (args ++ [b'])
437 return $ T.App a' [b']
440 T.Lambda <$> go a <*> go b
446 return $ T.Record [] Nothing
448 Record1 tfields extension ->
449 do fields' <- Traverse.traverse (mapM go) tfields
450 let fields = concat [ map ((,) name) ts | (name,ts) <- Map.toList fields' ]
451 ext' <- dealias <$> go extension
454 T.Record fs ext -> T.Record (fs ++ fields) ext
455 T.Var _ -> T.Record fields (Just ext')
456 _ -> error "Used toSrcType on a type that is not well-formed"
458 dealias :: T.Canonical -> T.Canonical
461 T.Aliased _ args tipe' ->
469addNames :: Variable -> IO ()
471 do usedNames <- getVarNames variable
472 let freeNames = makeFreeNames usedNames
473 State.runStateT (varAddNames variable) (NameState freeNames 0 0 0)
477makeFreeNames :: Set.Set String -> [String]
478makeFreeNames usedNames =
479 let makeName suffix =
480 map (:suffix) ['a'..'z']
483 concatMap makeName ("" : "'" : "_" : map show [ (0 :: Int) .. ])
485 filter (\name -> Set.notMember name usedNames) allNames
488data NameState = NameState
489 { freeNames :: [String]
490 , numberPrimes :: Int
491 , comparablePrimes :: Int
492 , appendablePrimes :: Int
496varAddNames :: Variable -> StateT NameState IO ()
498 do desc <- State.liftIO (UF.descriptor var)
503 Just (_name, args) ->
504 mapM_ (\(v,t) -> (,) v <$> varAddNames t) args
506 case structure desc of
514 do name' <- createName desc
515 State.liftIO $ UF.modifyDescriptor var $ \desc ->
516 desc { name = Just (Var.local name') }
519termAddNames :: Term1 Variable -> StateT NameState IO ()
536 Record1 fields extension ->
537 do mapM_ varAddNames (concat (Map.elems fields))
538 varAddNames extension
541createName :: (Monad m) => Descriptor -> StateT NameState m String
545 do primes <- State.gets numberPrimes
546 State.modify (\state -> state { numberPrimes = primes + 1 })
547 return ("number" ++ replicate primes '\'')
550 do primes <- State.gets comparablePrimes
551 State.modify (\state -> state { comparablePrimes = primes + 1 })
552 return ("comparable" ++ replicate primes '\'')
555 do primes <- State.gets appendablePrimes
556 State.modify (\state -> state { appendablePrimes = primes + 1 })
557 return ("appendable" ++ replicate primes '\'')
560 do names <- State.gets freeNames
561 State.modify (\state -> state { freeNames = tail names })
565-- GET ALL VARIABLE NAMES
567getVarNames :: Variable -> IO (Set.Set String)
569 do desc <- UF.descriptor var
573 Just var -> Set.singleton (Var.toString var)
577 case structure desc of
578 Nothing -> return Set.empty
579 Just term -> getVarNamesTerm term
586 Just (_name, args) ->
587 do let set = Set.fromList (map fst args)
588 sets <- mapM (getVarNames . snd) args
589 return (Set.unions (set : sets))
591 return (Set.unions [ baseSet, structureSet, aliasSet ])
594getVarNamesTerm :: Term1 Variable -> IO (Set.Set String)
595getVarNamesTerm term =
596 let go = getVarNames in
599 Set.union <$> go a <*> go b
602 Set.union <$> go a <*> go b
610 Record1 fields extension ->
611 do fieldVars <- Set.unions <$> mapM go (concat (Map.elems fields))
612 Set.union fieldVars <$> go extension
615-- COLLECT APPLICATIONS
623collectApps :: Variable -> IO AppStructure
628 desc <- UF.descriptor var
629 case (structure desc, vars) of
632 Just n | Var.isList n -> return (List v)
637 Just n | Var.isTuple n -> return (Tuple vs)
642 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