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