[project @ 1996-06-05 06:44:31 by partain]
[ghc-hetmet.git] / ghc / compiler / main / MkIface.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
3 %
4 \section[MkIface]{Print an interface for a module}
5
6 \begin{code}
7 #include "HsVersions.h"
8
9 module MkIface (
10         startIface, endIface,
11         ifaceUsages,
12         ifaceVersions,
13         ifaceExportList,
14         ifaceFixities,
15         ifaceInstanceModules,
16         ifaceDecls,
17         ifaceInstances,
18         ifacePragmas
19     ) where
20
21 IMP_Ubiq(){-uitous-}
22
23 import Bag              ( emptyBag, snocBag, bagToList )
24 import Class            ( GenClass(..){-instance NamedThing-}, GenClassOp(..) )
25 import CmdLineOpts      ( opt_ProduceHi )
26 import FieldLabel       ( FieldLabel{-instance NamedThing-} )
27 import FiniteMap        ( fmToList )
28 import HsSyn
29 import Id               ( idType, dataConRawArgTys, dataConFieldLabels,
30                           dataConStrictMarks, StrictnessMark(..),
31                           GenId{-instance NamedThing/Outputable-}
32                         )
33 import Name             ( nameOrigName, origName, nameOf,
34                           exportFlagOn, nameExportFlag, ExportFlag(..),
35                           ltLexical, isExported, getExportFlag,
36                           isLexSym, isLocallyDefined,
37                           RdrName(..){-instance Outputable-},
38                           Name{-instance NamedThing-}
39                         )
40 import ParseUtils       ( UsagesMap(..), VersionsMap(..) )
41 import PprEnv           -- not sure how much...
42 import PprStyle         ( PprStyle(..) )
43 import PprType          -- most of it (??)
44 import Pretty           ( prettyToUn )
45 import Unpretty         -- ditto
46 import RnHsSyn          ( RenamedHsModule(..), RnName{-instance NamedThing-} )
47 import TcModule         ( TcIfaceInfo(..) )
48 import TcInstUtil       ( InstInfo(..) )
49 import TyCon            ( TyCon(..){-instance NamedThing-}, NewOrData(..) )
50 import Type             ( mkSigmaTy, mkDictTy, getAppTyCon )
51 import Util             ( sortLt, zipWithEqual, zipWith3Equal, assertPanic, panic{-ToDo:rm-}, pprTrace{-ToDo:rm-} )
52
53 uppSemid   x = uppBeside (prettyToUn (ppr PprInterface x)) uppSemi -- micro util
54 ppr_ty    ty = prettyToUn (pprType PprInterface ty)
55 ppr_tyvar tv = prettyToUn (ppr PprInterface tv)
56 ppr_name   n
57   = let
58         on = origName n
59         s  = nameOf  on
60         pp = prettyToUn (ppr PprInterface on)
61     in
62     (if isLexSym s then uppParens else id) pp
63 {-OLD:
64 ppr_unq_name n
65   = let
66         on = origName n
67         s  = nameOf  on
68         pp = uppPStr  s
69     in
70     (if isLexSym s then uppParens else id) pp
71 -}
72 \end{code}
73
74 We have a function @startIface@ to open the output file and put
75 (something like) ``interface Foo'' in it.  It gives back a handle
76 for subsequent additions to the interface file.
77
78 We then have one-function-per-block-of-interface-stuff, e.g.,
79 @ifaceExportList@ produces the @__exports__@ section; it appends
80 to the handle provided by @startIface@.
81
82 \begin{code}
83 startIface  :: Module
84             -> IO (Maybe Handle) -- Nothing <=> don't do an interface
85 endIface    :: Maybe Handle -> IO ()
86 ifaceUsages
87             :: Maybe Handle
88             -> UsagesMap
89             -> IO ()
90 ifaceVersions
91             :: Maybe Handle
92             -> VersionsMap
93             -> IO ()
94 ifaceExportList
95             :: Maybe Handle
96             -> RenamedHsModule
97             -> IO ()
98 ifaceFixities
99             :: Maybe Handle
100             -> RenamedHsModule
101             -> IO ()
102 ifaceInstanceModules
103             :: Maybe Handle
104             -> [Module]
105             -> IO ()
106 ifaceDecls  :: Maybe Handle
107             -> TcIfaceInfo  -- info produced by typechecker, for interfaces
108             -> IO ()
109 ifaceInstances
110             :: Maybe Handle
111             -> TcIfaceInfo  -- as above
112             -> IO ()
113 ifacePragmas
114             :: Maybe Handle
115             -> IO ()
116 ifacePragmas = panic "ifacePragmas" -- stub
117 \end{code}
118
119 \begin{code}
120 startIface mod
121   = case opt_ProduceHi of
122       Nothing -> return Nothing -- not producing any .hi file
123       Just fn ->
124         openFile fn WriteMode   >>= \ if_hdl ->
125         hPutStr if_hdl ("interface "++ _UNPK_ mod) >>
126         return (Just if_hdl)
127
128 endIface Nothing        = return ()
129 endIface (Just if_hdl)  = hPutStr if_hdl "\n" >> hClose if_hdl
130 \end{code}
131
132 \begin{code}
133 ifaceUsages Nothing{-no iface handle-} _ = return ()
134
135 ifaceUsages (Just if_hdl) usages
136   | null usages_list
137   = return ()
138   | otherwise
139   = hPutStr if_hdl "\n__usages__\n"   >>
140     hPutStr if_hdl (uppShow 0 (uppAboves (map upp_uses usages_list)))
141   where
142     usages_list = fmToList usages
143
144     upp_uses (m, (mv, versions))
145       = uppBesides [uppPStr m, uppSP, uppInt mv, uppPStr SLIT(" :: "),
146                upp_versions (fmToList versions), uppSemi]
147
148     upp_versions nvs
149       = uppIntersperse uppSP [ uppCat [(if isLexSym n then uppParens else id) (uppPStr n), uppInt v] | (n,v) <- nvs ]
150 \end{code}
151
152 \begin{code}
153 ifaceVersions Nothing{-no iface handle-} _ = return ()
154
155 ifaceVersions (Just if_hdl) version_info
156   | null version_list
157   = return ()
158   | otherwise
159   = hPutStr if_hdl "\n__versions__\n"   >>
160     hPutStr if_hdl (uppShow 0 (upp_versions version_list))
161   where
162     version_list = fmToList version_info
163
164     upp_versions nvs
165       = uppAboves [ (if isLexSym n then uppParens else id) (uppPStr n) | (n,v) <- nvs ]
166 \end{code}
167
168 \begin{code}
169 ifaceInstanceModules Nothing{-no iface handle-} _ = return ()
170 ifaceInstanceModules (Just _)                  [] = return ()
171
172 ifaceInstanceModules (Just if_hdl) imods
173   = hPutStr if_hdl "\n__instance_modules__\n" >>
174     hPutStr if_hdl (uppShow 0 (uppCat (map uppPStr imods)))
175 \end{code}
176
177 Export list: grab the Names of things that are marked Exported, sort
178 (so the interface file doesn't ``wobble'' from one compilation to the
179 next...), and print.  Note that the ``module'' now contains all the
180 imported things that we are dealing with, thus including any entities
181 that we are re-exporting from somewhere else.
182 \begin{code}
183 ifaceExportList Nothing{-no iface handle-} _ = return ()
184
185 ifaceExportList (Just if_hdl)
186                 (HsModule _ _ _ _ _ typedecls _ classdecls _ _ _ binds sigs _)
187   = let
188         name_flag_pairs :: Bag (Name, ExportFlag)
189         name_flag_pairs
190           = foldr from_ty
191            (foldr from_cls
192            (foldr from_sig
193            (from_binds binds emptyBag{-init accum-})
194              sigs)
195              classdecls)
196              typedecls
197
198         sorted_pairs = sortLt lexical_lt (bagToList name_flag_pairs)
199
200     in
201     hPutStr if_hdl "\n__exports__\n" >>
202     hPutStr if_hdl (uppShow 0 (uppAboves (map upp_pair sorted_pairs)))
203   where
204     from_ty (TyData _ n _ _ _ _ _) acc = maybe_add acc n
205     from_ty (TyNew  _ n _ _ _ _ _) acc = maybe_add acc n
206     from_ty (TySynonym n _ _ _)    acc = maybe_add acc n
207
208     from_cls (ClassDecl _ n _ _ _ _ _) acc = maybe_add acc n
209
210     from_sig (Sig n _ _ _) acc = maybe_add acc n
211
212     from_binds bs acc = maybe_add_list acc (collectTopLevelBinders bs)
213
214     --------------
215     maybe_add :: Bag (Name, ExportFlag) -> RnName -> Bag (Name, ExportFlag)
216
217     maybe_add acc rn
218       | exportFlagOn ef = acc `snocBag` (n, ef)
219       | otherwise       = acc
220       where
221         n  = getName rn
222         ef = nameExportFlag n
223
224     --------------
225     maybe_add_list acc []     = acc
226     maybe_add_list acc (n:ns) = maybe_add (maybe_add_list acc ns) n
227
228     --------------
229     lexical_lt (n1,_) (n2,_) = nameOrigName n1 < nameOrigName n2
230
231     --------------
232     upp_pair (n, ef)
233       = uppBeside (ppr_name n) (upp_export ef)
234       where
235         upp_export ExportAll = uppPStr SLIT("(..)")
236         upp_export ExportAbs = uppNil
237 \end{code}
238
239 \begin{code}
240 ifaceFixities Nothing{-no iface handle-} _ = return ()
241
242 ifaceFixities (Just if_hdl) (HsModule _ _ _ _ fixities _ _ _ _ _ _ _ _ _)
243   = let
244         local_fixities = filter from_here fixities
245     in
246     if null local_fixities then
247         return ()
248     else 
249         hPutStr if_hdl "\n__fixities__\n" >>
250         hPutStr if_hdl (uppShow 0 (uppAboves (map uppSemid local_fixities)))
251   where
252     from_here (InfixL v _) = isLocallyDefined v
253     from_here (InfixR v _) = isLocallyDefined v
254     from_here (InfixN v _) = isLocallyDefined v
255 \end{code}
256
257 \begin{code}
258 ifaceDecls Nothing{-no iface handle-} _ = return ()
259
260 ifaceDecls (Just if_hdl) (vals, tycons, classes, _)
261   = ASSERT(all isLocallyDefined vals)
262     ASSERT(all isLocallyDefined tycons)
263     ASSERT(all isLocallyDefined classes)
264     let
265         sorted_classes   = sortLt ltLexical classes
266         sorted_tycons    = sortLt ltLexical tycons
267         sorted_vals      = sortLt ltLexical vals
268     in
269     if (null sorted_classes && null sorted_tycons && null sorted_vals) then
270         --  You could have a module with just instances in it
271         return ()
272     else
273     hPutStr if_hdl "\n__declarations__\n" >>
274     hPutStr if_hdl (uppShow 0 (uppAboves [
275         uppAboves (map ppr_class sorted_classes),
276         uppAboves (map ppr_tycon sorted_tycons),
277         uppAboves [ppr_val v (idType v) | v <- sorted_vals]]))
278 \end{code}
279
280 \begin{code}
281 ifaceInstances Nothing{-no iface handle-} _ = return ()
282
283 ifaceInstances (Just if_hdl) (_, _, _, insts)
284   = let
285         togo_insts      = filter is_togo_inst (bagToList insts)
286
287         sorted_insts    = sortLt lt_inst togo_insts
288     in
289     if null togo_insts then
290         return ()
291     else
292         hPutStr if_hdl "\n__instances__\n" >>
293         hPutStr if_hdl (uppShow 0 (uppAboves (map pp_inst sorted_insts)))
294   where
295     is_togo_inst (InstInfo clas _ ty _ _ _ _ _ from_here _ _ _)
296       = from_here -- && ...
297
298     -------
299     lt_inst (InstInfo clas1 _ ty1 _ _ _ _ _ _ _ _ _)
300             (InstInfo clas2 _ ty2 _ _ _ _ _ _ _ _ _)
301       = let
302             tycon1 = fst (getAppTyCon ty1)
303             tycon2 = fst (getAppTyCon ty2)
304         in
305         case (origName clas1 `cmp` origName clas2) of
306           LT_ -> True
307           GT_ -> False
308           EQ_ -> origName tycon1 < origName tycon2
309
310     -------
311     pp_inst (InstInfo clas tvs ty theta _ _ _ _ _ _ _ _)
312       = let
313             forall_ty     = mkSigmaTy tvs theta (mkDictTy clas ty)
314             renumbered_ty = initNmbr (nmbrType forall_ty)
315         in
316         uppBesides [uppPStr SLIT("instance "), ppr_ty renumbered_ty, uppSemi]
317 \end{code}
318
319 %************************************************************************
320 %*                                                                      *
321 \subsection{Printing tycons, classes, ...}
322 %*                                                                      *
323 %************************************************************************
324
325 \begin{code}
326 ppr_class :: Class -> Unpretty
327
328 ppr_class c
329   = --pprTrace "ppr_class:" (ppr PprDebug c) $
330     case (initNmbr (nmbrClass c)) of { -- renumber it!
331       Class _ n tyvar super_classes sdsels ops sels defms insts links ->
332
333         uppCat [uppPStr SLIT("class"), ppr_theta tyvar super_classes,
334                 ppr_name n, ppr_tyvar tyvar,
335                 if null ops
336                 then uppSemi
337                 else uppCat [uppStr "where {", uppCat (map ppr_op ops), uppStr "};"]]
338     }
339   where
340     ppr_theta :: TyVar -> [Class] -> Unpretty
341
342     ppr_theta tv []   = uppNil
343     ppr_theta tv [sc] = uppBeside (ppr_assert tv sc) (uppPStr SLIT(" =>"))
344     ppr_theta tv super_classes
345       = uppBesides [uppLparen,
346                     uppIntersperse upp'SP{-'-} (map (ppr_assert tv) super_classes),
347                     uppStr ") =>"]
348
349     ppr_assert tv (Class _ n _ _ _ _ _ _ _ _) = uppCat [ppr_name n, ppr_tyvar tv]
350
351     ppr_op (ClassOp o _ ty) = pp_sig (Unqual o) ty
352 \end{code}
353
354 \begin{code}
355 ppr_val v ty -- renumber the type first!
356   = --pprTrace "ppr_val:" (ppr PprDebug v) $
357     pp_sig v (initNmbr (nmbrType ty))
358
359 pp_sig op ty
360   = uppBesides [ppr_name op, uppPStr SLIT(" :: "), ppr_ty ty, uppSemi]
361 \end{code}
362
363 \begin{code}
364 ppr_tycon tycon
365   = --pprTrace "ppr_tycon:" (ppr PprDebug tycon) $
366     ppr_tc (initNmbr (nmbrTyCon tycon))
367
368 ------------------------
369 ppr_tc (PrimTyCon _ n _ _)
370   = uppCat [ uppStr "{- data", ppr_name n, uppStr " *built-in* -}" ]
371
372 ppr_tc FunTyCon
373   = uppCat [ uppStr "{- data", ppr_name FunTyCon, uppStr " *built-in* -}" ]
374
375 ppr_tc (TupleTyCon _ n _)
376   = uppCat [ uppStr "{- ", ppr_name n, uppStr "-}" ]
377
378 ppr_tc (SynTyCon _ n _ _ tvs expand)
379   = let
380         pp_tyvars   = map ppr_tyvar tvs
381     in
382     uppBesides [uppPStr SLIT("type "), ppr_name n, uppSP, uppIntersperse uppSP pp_tyvars,
383            uppPStr SLIT(" = "), ppr_ty expand, uppSemi]
384
385 ppr_tc this_tycon@(DataTyCon u n k tvs ctxt cons derivings data_or_new)
386   = uppCat [pp_data_or_new,
387            ppr_context ctxt,
388            ppr_name n,
389            uppIntersperse uppSP (map ppr_tyvar tvs),
390            uppEquals, pp_condecls,
391            uppSemi]
392            -- NB: we do not print deriving info in interfaces
393   where
394     pp_data_or_new = case data_or_new of
395                       DataType -> uppPStr SLIT("data")
396                       NewType  -> uppPStr SLIT("newtype")
397
398     ppr_context []      = uppNil
399     ppr_context [(c,t)] = uppCat [ppr_name c, ppr_ty t, uppPStr SLIT("=>")]
400     ppr_context cs
401       = uppBesides[uppLparen,
402                    uppInterleave uppComma [uppCat [ppr_name c, ppr_ty t] | (c,t) <- cs],
403                    uppRparen, uppPStr SLIT(" =>")]
404
405     pp_condecls
406       = let
407             (c:cs) = cons
408         in
409         uppCat ((ppr_con c) : (map ppr_next_con cs))
410
411     ppr_next_con con = uppCat [uppChar '|', ppr_con con]
412
413     ppr_con con
414       = let
415             con_arg_tys  = dataConRawArgTys   con
416             labels       = dataConFieldLabels con -- none if not a record
417             strict_marks = dataConStrictMarks con
418         in
419         uppCat [ppr_name con, ppr_fields labels strict_marks con_arg_tys]
420
421     ppr_fields labels strict_marks con_arg_tys
422       = if null labels then -- not a record thingy
423             uppIntersperse uppSP (zipWithEqual  "ppr_fields" ppr_bang_ty strict_marks con_arg_tys)
424         else
425             uppCat [ uppChar '{',
426             uppInterleave uppComma (zipWith3Equal "ppr_field" ppr_field labels strict_marks con_arg_tys),
427             uppChar '}' ]
428
429     ppr_bang_ty b t
430       = uppBeside (case b of { MarkedStrict -> uppChar '!'; _ -> uppNil })
431                   (prettyToUn (pprParendType PprInterface t))
432
433     ppr_field l b t
434       = uppBesides [ppr_name l, uppPStr SLIT(" :: "),
435                    case b of { MarkedStrict -> uppChar '!'; _ -> uppNil },
436                    ppr_ty t]
437 \end{code}