3import qualified Data.Char as Char
4import qualified Data.List as List
5import qualified Data.Map as Map
6import qualified Data.UnionFind.IO as UF
8import Text.PrettyPrint as P
10import Control.Applicative ((<$>),(<*>))
11import Control.Monad.State (StateT, get, put, execStateT, runStateT)
12import Control.Monad.Error (ErrorT, Error, liftIO)
13import Data.Traversable (traverse)
15import qualified AST.PrettyPrint as PP
16import qualified AST.Type as T
17import qualified AST.Variable as Var
24 | Record1 (Map.Map String [a]) a
28 = VarN (Maybe Var.Canonical) a
29 | TermN (Maybe Var.Canonical) (Term1 (TermN a))
35termN :: (Term1 (TermN a)) -> TermN a
38record :: Map.Map String [TermN a] -> TermN a -> TermN a
39record fs rec = termN (Record1 fs rec)
41type Type = TermN Variable
42type Variable = UF.Point Descriptor
44type SchemeName = String
45type TypeName = Var.Canonical
47type Constraint a b = Located (BasicConstraint a b)
48data BasicConstraint a b
52 | CAnd [Constraint a b]
53 | CLet [Scheme a b] (Constraint a b)
54 | CInstance SchemeName a
57data Scheme a b = Scheme {
58 rigidQuantifiers :: [b],
59 flexibleQuantifiers :: [b],
60 constraint :: Constraint a b,
61 header :: Map.Map String a
64type TypeConstraint = Constraint Type Variable
65type TypeScheme = Scheme Type Variable
67monoscheme :: Map.Map String a -> Scheme a b
68monoscheme headers = Scheme [] [] (noneNoDocs CTrue) headers
72(/\) :: Constraint a b -> Constraint a b -> Constraint a b
73a@(A _ c1) /\ b@(A _ c2) =
77 _ -> mergeOldDocs a b (CAnd [a,b])
80(==>) :: Type -> Type -> Type
81a ==> b = termN (Fun1 a b)
83(<|) :: TermN a -> TermN a -> TermN a
84f <| a = termN (App1 f a)
86data Descriptor = Descriptor
87 { structure :: Maybe (Term1 Variable)
90 , name :: Maybe TypeName
91 , copy :: Maybe Variable
93 , alias :: Maybe Var.Canonical
108data Flex = Rigid | Flexible | Constant | Is SuperType
111data SuperType = Number | Comparable | Appendable
114namedVar :: Flex -> Var.Canonical -> IO Variable
115namedVar flex name = UF.fresh $ Descriptor
116 { structure = Nothing
125variable :: Flex -> IO Variable
126variable flex = UF.fresh $ Descriptor
127 { structure = Nothing
137-- ex qs constraint == exists qs. constraint
138ex :: [Variable] -> TypeConstraint -> TypeConstraint
139ex fqs constraint@(A ann _) =
140 A ann $ CLet [Scheme [] fqs constraint Map.empty] (A ann CTrue)
142-- fl qs constraint == forall qs. constraint
143fl :: [Variable] -> TypeConstraint -> TypeConstraint
144fl rqs constraint@(A ann _) =
145 A ann $ CLet [Scheme rqs [] constraint Map.empty] (A ann CTrue)
147exists :: Error e => (Type -> ErrorT e IO TypeConstraint) -> ErrorT e IO TypeConstraint
149 v <- liftIO $ variable Flexible
150 ex [v] <$> f (varN v)
152existsNumber :: Error e => (Type -> ErrorT e IO TypeConstraint) -> ErrorT e IO TypeConstraint
154 v <- liftIO $ variable (Is Number)
155 ex [v] <$> f (varN v)
158instance Show a => Show (UF.Point a) where
159 show point = unsafePerformIO $ fmap show (UF.descriptor point)
162instance PrettyType a => PrettyType (UF.Point a) where
163 pretty when point = unsafePerformIO $ fmap (pretty when) (UF.descriptor point)
166instance PrettyType t => PrettyType (Annotated a t) where
167 pretty when (A _ e) = pretty when e
170instance PrettyType a => PrettyType (Term1 a) where
172 let prty = pretty Never in
175 parensIf needed (px <+> pretty App x)
178 needed = case when of
183 parensIf needed (pretty Fn arg <+> P.text "->" <+> prty body)
185 needed = case when of
191 EmptyRecord1 -> P.braces P.empty
193 Record1 fields ext -> P.braces (extend <+> commaSep prettyFields)
196 extend | P.render prettyExt == "{}" = P.empty
197 | otherwise = prettyExt <+> P.text "|"
198 mkPretty f t = P.text f <+> P.text ":" <+> prty t
199 prettyFields = concatMap (\(f,ts) -> map (mkPretty f) ts) (Map.toList fields)
202instance PrettyType a => PrettyType (TermN a) where
205 VarN alias x -> either alias (pretty when x)
206 TermN alias t1 -> either alias (pretty when t1)
208 either maybeAlias doc =
210 Just alias -> PP.pretty alias
213instance PrettyType Descriptor where
214 pretty when desc = do
215 case (alias desc, structure desc, name desc) of
216 (Just name, _, _) -> PP.pretty name
217 (_, Just term, _) -> pretty when term
219 | Var.isTuple name ->
220 P.parens . P.text $ replicate (read (drop 6 (Var.toString name)) - 1) ','
222 P.text (Var.toString name)
227instance (PrettyType a, PrettyType b) => PrettyType (BasicConstraint a b) where
228 pretty _ constraint =
229 let prty = pretty Never in
231 CTrue -> P.text "True"
232 CSaveEnv -> P.text "SaveTheEnvironment!!!"
233 CEqual a b -> prty a <+> P.text "=" <+> prty b
234 CAnd [] -> P.text "True"
237 P.parens . P.sep $ P.punctuate (P.text " and") (map (pretty Never) cs)
239 CLet [Scheme [] fqs constraint header] (A _ CTrue) | Map.null header ->
240 P.sep [ binder, pretty Never c ]
242 mergeExists vs (A _ c) =
244 CLet [Scheme [] fqs' c' _] (A _ CTrue) -> mergeExists (vs ++ fqs') c'
247 (fqs', c) = mergeExists fqs constraint
249 binder = if null fqs' then P.empty else
250 P.text "\x2203" <+> P.hsep (map (pretty Never) fqs') <> P.text "."
252 CLet schemes constraint ->
253 P.fsep [ P.hang (P.text "let") 4 (P.brackets . commaSep $ map (pretty Never) schemes)
254 , P.text "in", pretty Never constraint ]
256 CInstance name tipe ->
257 P.text name <+> P.text "<" <+> prty tipe
259instance (PrettyType a, PrettyType b) => PrettyType (Scheme a b) where
260 pretty _ (Scheme rqs fqs (A _ constraint) headers) =
261 P.sep [ forall, cs, headers' ]
265 forall = if null rqs && null fqs then P.empty else
266 P.text "\x2200" <+> frees <+> rigids
268 frees = P.hsep $ map prty fqs
269 rigids = if null rqs then P.empty else P.braces . P.hsep $ map prty rqs
271 cs = case constraint of
274 _ -> P.brackets (pretty Never constraint)
276 headers' = if Map.size headers > 0 then dict else P.empty
277 dict = P.parens . commaSep . map prettyPair $ Map.toList headers
278 prettyPair (n,t) = P.text n <+> P.text ":" <+> pretty Never t
281extraPretty :: (PrettyType t, Crawl t) => t -> IO Doc
282extraPretty t = pretty Never <$> addNames t
284addNames :: (Crawl t) => t -> IO t
286 (rawVars, _, _, _) <- execStateT (crawl getNames value) ([], 0, 0, 0)
287 let vars = map head . List.group $ List.sort rawVars
288 suffix s = map (++s) (map (:[]) ['a'..'z'])
289 allVars = concatMap suffix $ ["","'","_"] ++ map show [ (0 :: Int) .. ]
290 okayVars = filter (`notElem` vars) allVars
291 runStateT (crawl rename value) (okayVars, 0, 0, 0)
294 getNames desc state@(vars, a, b, c) =
295 let name' = name desc in
297 Just (Var.Canonical _ var) -> (name', (var:vars, a, b, c))
300 rename desc state@(vars, a, b, c) =
302 Just var -> (Just var, state)
305 Is Number -> (local $ "number" ++ replicate a '\'', (vars, a+1, b, c))
306 Is Comparable -> (local $ "comparable" ++ replicate b '\'', (vars, a, b+1, c))
307 Is Appendable -> (local $ "appendable" ++ replicate c '\'', (vars, a, b, c+1))
308 _ -> (local $ head vars, (tail vars, a, b, c))
310 local v = Just (Var.local v)
312type CrawlState = ([String], Int, Int, Int)
314-- Code for traversing all the type data-structures and giving
315-- names to the variables embedded deep in there.
317 crawl :: (Descriptor -> CrawlState -> (Maybe TypeName, CrawlState))
319 -> StateT CrawlState IO t
321instance Crawl e => Crawl (Annotated a e) where
322 crawl nextState (A ann e) = A ann <$> crawl nextState e
324instance (Crawl t, Crawl v) => Crawl (BasicConstraint t v) where
325 crawl nextState constraint =
326 let rnm = crawl nextState in
328 CTrue -> return CTrue
329 CSaveEnv -> return CSaveEnv
330 CEqual a b -> CEqual <$> rnm a <*> rnm b
331 CAnd cs -> CAnd <$> crawl nextState cs
332 CLet schemes c -> CLet <$> crawl nextState schemes <*> crawl nextState c
333 CInstance name tipe -> CInstance name <$> rnm tipe
335instance Crawl a => Crawl [a] where
336 crawl nextState list = mapM (crawl nextState) list
338instance (Crawl t, Crawl v) => Crawl (Scheme t v) where
339 crawl nextState (Scheme rqs fqs c headers) =
340 let rnm = crawl nextState in
341 Scheme <$> rnm rqs <*> rnm fqs <*> crawl nextState c <*> return headers
343instance Crawl t => Crawl (TermN t) where
344 crawl nextState tipe =
346 VarN a x -> VarN a <$> crawl nextState x
347 TermN a term -> TermN a <$> crawl nextState term
349instance Crawl t => Crawl (Term1 t) where
350 crawl nextState term =
351 let rnm = crawl nextState in
353 App1 a b -> App1 <$> rnm a <*> rnm b
354 Fun1 a b -> Fun1 <$> rnm a <*> rnm b
355 Var1 a -> Var1 <$> rnm a
356 EmptyRecord1 -> return EmptyRecord1
357 Record1 fields ext ->
358 Record1 <$> traverse (mapM rnm) fields <*> rnm ext
360instance Crawl a => Crawl (UF.Point a) where
361 crawl nextState point = do
362 desc <- liftIO $ UF.descriptor point
363 desc' <- crawl nextState desc
364 liftIO $ UF.setDescriptor point desc'
367instance Crawl Descriptor where
368 crawl nextState desc = do
370 let (name', state') = nextState desc state
371 structure' <- traverse (crawl nextState) (structure desc)
373 return $ desc { name = name', structure = structure' }
376toSrcType :: Variable -> IO T.CanonicalType
381 desc <- UF.descriptor v
382 srcType <- maybe (backupSrcType desc) termToSrcType (structure desc)
383 return $ maybe srcType (\name -> T.Aliased name srcType) (alias desc)
387 Just v@(Var.Canonical _ x@(c:_))
388 | Char.isLower c -> return (T.Var x)
389 | otherwise -> return $ T.Type v
392 [ "Problem converting the following type "
393 , "from a type-checker type to a source-syntax type:"
394 , P.render (pretty Never var) ]
402 T.App f args -> return $ T.App f (args ++ [b'])
403 _ -> return $ T.App a' [b']
405 Fun1 a b -> T.Lambda <$> go a <*> go b
409 EmptyRecord1 -> return $ T.Record [] Nothing
411 Record1 tfields extension -> do
412 fields' <- traverse (mapM go) tfields
413 let fields = concat [ map ((,) name) ts | (name,ts) <- Map.toList fields' ]
414 ext' <- dealias <$> go extension
415 return $ case ext' of
416 T.Record fs ext -> T.Record (fs ++ fields) ext
417 T.Var _ -> T.Record fields (Just ext')
418 _ -> error "Used toSrcType on a type that is not well-formed"
420 dealias :: T.CanonicalType -> T.CanonicalType
427data AppStructure = List Variable | Tuple [Variable] | Other
429collectApps :: Variable -> IO AppStructure
430collectApps var = go [] var
433 desc <- UF.descriptor var
434 case (structure desc, vars) of
435 (Nothing, [v]) -> case name desc of
436 Just n | Var.isList n -> return (List v)
438 (Nothing, vs) -> case name desc of
439 Just n | Var.isTuple n -> return (Tuple vs)
441 (Just term, _) -> case term of
442 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