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
12import Data.Traversable (traverse)
13import SourceSyntax.Location
14import SourceSyntax.Helpers (isTuple)
15import qualified SourceSyntax.Type as Src
22 | Record1 (Map.Map String [a]) a
27 | TermN (Term1 (TermN a))
30record :: Map.Map String [TermN a] -> TermN a -> TermN a
31record fs rec = TermN (Record1 fs rec)
33type Type = TermN Variable
34type Variable = UF.Point Descriptor
36type SchemeName = String
39type Constraint a b = Located (BasicConstraint a b)
40data BasicConstraint a b
44 | CAnd [Constraint a b]
45 | CLet [Scheme a b] (Constraint a b)
46 | CInstance SchemeName a
49data Scheme a b = Scheme {
50 rigidQuantifiers :: [b],
51 flexibleQuantifiers :: [b],
52 constraint :: Constraint a b,
53 header :: Map.Map String a
56type TypeConstraint = Constraint Type Variable
57type TypeScheme = Scheme Type Variable
59monoscheme headers = Scheme [] [] (noneNoDocs CTrue) headers
63(/\) :: Constraint a b -> Constraint a b -> Constraint a b
64a@(L s1 c1) /\ b@(L s2 c2) =
68 _ -> mergeOldDocs a b (CAnd [a,b])
71(==>) :: Type -> Type -> Type
72a ==> b = TermN (Fun1 a b)
74f <| a = TermN (App1 f a)
76data Descriptor = Descriptor {
77 structure :: Maybe (Term1 Variable),
80 name :: Maybe TypeName,
81 copy :: Maybe Variable,
86outermostRank = 0 :: Int
91data Flex = Rigid | Flexible | Constant | Is SuperType
94data SuperType = Number | Comparable | Appendable
97namedVar flex name = UF.fresh $ Descriptor {
106var flex = UF.fresh $ Descriptor {
115structuredVar structure = UF.fresh $ Descriptor {
116 structure = Just structure,
125-- ex qs constraint == exists qs. constraint
126ex :: [Variable] -> TypeConstraint -> TypeConstraint
127ex fqs constraint@(L s _) = L s $ CLet [Scheme [] fqs constraint Map.empty] (L s CTrue)
129-- fl qs constraint == forall qs. constraint
130fl :: [Variable] -> TypeConstraint -> TypeConstraint
131fl rqs constraint@(L s _) = L s $ CLet [Scheme rqs [] constraint Map.empty] (L s CTrue)
133exists :: (Type -> IO TypeConstraint) -> IO TypeConstraint
136 ex [v] <$> f (VarN v)
139instance Show a => Show (UF.Point a) where
140 show point = unsafePerformIO $ fmap show (UF.descriptor point)
143instance PrettyType a => PrettyType (UF.Point a) where
144 pretty when point = unsafePerformIO $ fmap (pretty when) (UF.descriptor point)
147instance PrettyType a => PrettyType (Located a) where
148 pretty when (L _ e) = pretty when e
151instance PrettyType a => PrettyType (Term1 a) where
153 let prty = pretty Never in
155 App1 f x | P.render px == "_List" -> P.brackets (pretty Never x)
156 | otherwise -> parensIf needed (px <+> pretty App x)
159 needed = case when of
164 parensIf needed (pretty Fn arg <+> P.text "->" <+> prty body)
166 needed = case when of
172 EmptyRecord1 -> P.braces P.empty
174 Record1 fields ext -> P.braces (extend <+> commaSep prettyFields)
177 extend | P.render prettyExt == "{}" = P.empty
178 | otherwise = prettyExt <+> P.text "|"
179 mkPretty f t = P.text f <+> P.text ":" <+> prty t
180 prettyFields = concatMap (\(f,ts) -> map (mkPretty f) ts) (Map.toList fields)
183instance PrettyType a => PrettyType (TermN a) where
186 VarN x -> pretty when x
187 TermN t1 -> pretty when t1
190instance PrettyType Descriptor where
192 case (structure desc, name desc) of
193 (Just term, _) -> pretty when term
194 (_, Just name) -> if not (isTuple name) then P.text name else
195 P.parens . P.text $ replicate (read (drop 6 name) - 1) ','
199instance (PrettyType a, PrettyType b) => PrettyType (BasicConstraint a b) where
200 pretty _ constraint =
201 let prty = pretty Never in
203 CTrue -> P.text "True"
204 CSaveEnv -> P.text "SaveTheEnvironment!!!"
205 CEqual a b -> prty a <+> P.text "=" <+> prty b
206 CAnd [] -> P.text "True"
209 P.parens . P.sep $ P.punctuate (P.text " and") (map (pretty Never) cs)
211 CLet [Scheme [] fqs constraint header] (L _ CTrue) | Map.null header ->
212 P.sep [ binder, pretty Never c ]
214 mergeExists vs (L _ c) =
216 CLet [Scheme [] fqs' c' _] (L _ CTrue) -> mergeExists (vs ++ fqs') c'
219 (fqs', c) = mergeExists fqs constraint
221 binder = if null fqs' then P.empty else
222 P.text "\x2203" <+> P.hsep (map (pretty Never) fqs') <> P.text "."
224 CLet schemes constraint ->
225 P.fsep [ P.hang (P.text "let") 4 (P.brackets . commaSep $ map (pretty Never) schemes)
226 , P.text "in", pretty Never constraint ]
228 CInstance name tipe ->
229 P.text name <+> P.text "<" <+> prty tipe
231instance (PrettyType a, PrettyType b) => PrettyType (Scheme a b) where
232 pretty _ (Scheme rqs fqs (L _ constraint) headers) =
233 P.sep [ forall, cs, headers' ]
237 forall = if null rqs && null fqs then P.empty else
238 P.text "\x2200" <+> frees <+> rigids
240 frees = P.hsep $ map prty fqs
241 rigids = if null rqs then P.empty else P.braces . P.hsep $ map prty rqs
243 cs = case constraint of
246 _ -> P.brackets (pretty Never constraint)
248 headers' = if Map.size headers > 0 then dict else P.empty
249 dict = P.parens . commaSep . map prettyPair $ Map.toList headers
250 prettyPair (n,t) = P.text n <+> P.text ":" <+> pretty Never t
253extraPretty :: (PrettyType t, Crawl t) => t -> IO Doc
254extraPretty t = pretty Never <$> addNames t
256addNames :: (Crawl t) => t -> IO t
258 (rawVars, _, _, _) <- execStateT (crawl getNames value) ([], 0, 0, 0)
259 let vars = map head . List.group $ List.sort rawVars
260 suffix s = map (++s) (map (:[]) ['a'..'z'])
261 allVars = concatMap suffix $ ["","'","_"] ++ map show [0..]
262 okayVars = filter (`notElem` vars) allVars
263 runStateT (crawl rename value) (okayVars, 0, 0, 0)
266 getNames desc state@(vars, a, b, c) =
267 let name' = name desc in
269 Just var -> (name', (var:vars, a, b, c))
270 Nothing -> (name', state)
272 rename desc state@(vars, a, b, c) =
274 Just var -> (Just var, state)
277 Is Number -> (Just $ "number" ++ replicate a '\'', (vars, a+1, b, c))
278 Is Comparable -> (Just $ "comparable" ++ replicate b '\'', (vars, a, b+1, c))
279 Is Appendable -> (Just $ "appendable" ++ replicate c '\'', (vars, a, b, c+1))
280 _ -> (Just $ head vars, (tail vars, a, b, c))
283type CrawlState = ([String], Int, Int, Int)
285-- Code for traversing all the type data-structures and giving
286-- names to the variables embedded deep in there.
288 crawl :: (Descriptor -> CrawlState -> (Maybe TypeName, CrawlState))
290 -> StateT CrawlState IO t
292instance Crawl a => Crawl (Located a) where
293 crawl nextState (L s e) = L s <$> crawl nextState e
295instance (Crawl t, Crawl v) => Crawl (BasicConstraint t v) where
296 crawl nextState constraint =
297 let rnm = crawl nextState in
299 CTrue -> return CTrue
300 CSaveEnv -> return CSaveEnv
301 CEqual a b -> CEqual <$> rnm a <*> rnm b
302 CAnd cs -> CAnd <$> crawl nextState cs
303 CLet schemes c -> CLet <$> crawl nextState schemes <*> crawl nextState c
304 CInstance name tipe -> CInstance name <$> rnm tipe
306instance Crawl a => Crawl [a] where
307 crawl nextState list = mapM (crawl nextState) list
309instance (Crawl t, Crawl v) => Crawl (Scheme t v) where
310 crawl nextState (Scheme rqs fqs c headers) =
311 let rnm = crawl nextState in
312 Scheme <$> rnm rqs <*> rnm fqs <*> crawl nextState c <*> return headers
314instance Crawl t => Crawl (TermN t) where
315 crawl nextState tipe =
317 VarN x -> VarN <$> crawl nextState x
318 TermN term -> TermN <$> crawl nextState term
320instance Crawl t => Crawl (Term1 t) where
321 crawl nextState term =
322 let rnm = crawl nextState in
324 App1 a b -> App1 <$> rnm a <*> rnm b
325 Fun1 a b -> Fun1 <$> rnm a <*> rnm b
326 Var1 a -> Var1 <$> rnm a
327 EmptyRecord1 -> return EmptyRecord1
328 Record1 fields ext ->
329 Record1 <$> traverse (mapM rnm) fields <*> rnm ext
331instance Crawl a => Crawl (UF.Point a) where
332 crawl nextState point = do
333 desc <- liftIO $ UF.descriptor point
334 desc' <- crawl nextState desc
335 liftIO $ UF.setDescriptor point desc'
338instance Crawl Descriptor where
339 crawl nextState desc = do
341 let (name', state') = nextState desc state
342 structure' <- traverse (crawl nextState) (structure desc)
344 return $ desc { name = name', structure = structure' }
347toSrcType :: Variable -> IO Src.Type
348toSrcType variable = do
349 desc <- UF.descriptor =<< addNames variable
350 case structure desc of
354 Src.Data name ts <- toSrcType a
356 return (Src.Data name (ts ++ [b']))
357 Fun1 a b -> Src.Lambda <$> toSrcType a <*> toSrcType b
358 Var1 a -> toSrcType a
359 EmptyRecord1 -> return Src.EmptyRecord
361 fs' <- traverse (mapM toSrcType) fs
362 let fs'' = concat [ map ((,) name) ts | (name,ts) <- Map.toList fs' ]
363 Src.Record fs'' <$> toSrcType ext
366 Just x@(c:cs) | Char.isLower c -> return (Src.Var x)
367 | otherwise -> return (Src.Data x [])
370 [ "Problem converting the following type "
371 , "from a type-checker type to a source-syntax type:"
372 , P.render (pretty Never variable) ]
375data AppStructure = List Variable | Tuple [Variable] | Other
377collectApps :: Variable -> IO AppStructure
378collectApps variable = go [] variable
380 go vars variable = do
381 desc <- UF.descriptor variable
382 case (structure desc, vars) of
383 (Nothing, [v] ) -> case name desc of
384 Just "_List" -> return (List v)
386 (Nothing, vs ) -> case name desc of
387 Just ctor | isTuple ctor -> return (Tuple vs)
389 (Just term, vs) -> case term of
390 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