2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1995
4 \section[MkIface]{Print an interface for a module}
7 #include "HsVersions.h"
22 import Bag ( emptyBag, snocBag, bagToList )
23 import Class ( GenClass(..){-instance NamedThing-}, GenClassOp(..) )
24 import CmdLineOpts ( opt_ProduceHi )
25 import FieldLabel ( FieldLabel{-instance NamedThing-} )
27 import Id ( idType, dataConSig, dataConFieldLabels,
28 dataConStrictMarks, StrictnessMark(..),
29 GenId{-instance NamedThing/Outputable-}
31 import Name ( nameOrigName, origName, nameOf,
32 exportFlagOn, nameExportFlag, ExportFlag(..),
33 ltLexical, isExported, getExportFlag,
34 isLexSym, isLocallyDefined,
35 RdrName(..){-instance Outputable-},
36 Name{-instance NamedThing-}
38 import PprEnv -- not sure how much...
39 import PprStyle ( PprStyle(..) )
40 import PprType -- most of it (??)
41 import Pretty -- quite a bit
42 import RnHsSyn ( RenamedHsModule(..), RnName{-instance NamedThing-} )
43 import RnIfaces ( VersionInfo(..) )
44 import TcModule ( TcIfaceInfo(..) )
45 import TcInstUtil ( InstInfo(..) )
46 import TyCon ( TyCon(..){-instance NamedThing-}, NewOrData(..) )
47 import Type ( mkSigmaTy, mkDictTy, getAppTyCon )
48 import Util ( sortLt, zipWithEqual, zipWith3Equal, assertPanic, panic{-ToDo:rm-}, pprTrace{-ToDo:rm-} )
50 ppSemid x = ppBeside (ppr PprInterface x) ppSemi -- micro util
51 ppr_ty ty = pprType PprInterface ty
52 ppr_tyvar tv = ppr PprInterface tv
57 pp = ppr PprInterface on
59 (if isLexSym s then ppParens else id) pp
66 (if isLexSym s then ppParens else id) pp
69 We have a function @startIface@ to open the output file and put
70 (something like) ``interface Foo N'' in it. It gives back a handle
71 for subsequent additions to the interface file.
73 We then have one-function-per-block-of-interface-stuff, e.g.,
74 @ifaceExportList@ produces the @__exports__@ section; it appends
75 to the handle provided by @startIface@.
79 -> IO (Maybe Handle) -- Nothing <=> don't do an interface
80 endIface :: Maybe Handle -> IO ()
97 ifaceDecls :: Maybe Handle
98 -> TcIfaceInfo -- info produced by typechecker, for interfaces
102 -> TcIfaceInfo -- as above
107 ifacePragmas = panic "ifacePragmas" -- stub
112 = case opt_ProduceHi of
113 Nothing -> return Nothing -- not producing any .hi file
115 openFile fn WriteMode >>= \ if_hdl ->
116 hPutStr if_hdl ("interface "++ _UNPK_ mod ++" 1\n") >>
119 endIface Nothing = return ()
120 endIface (Just if_hdl) = hPutStr if_hdl "\n" >> hClose if_hdl
124 ifaceVersions Nothing{-no iface handle-} _ = return ()
126 ifaceVersions (Just if_hdl) version_info
127 = hPutStr if_hdl "__versions__\nFoo(1)" -- a stub, obviously
131 ifaceInstanceModules Nothing{-no iface handle-} _ = return ()
132 ifaceInstanceModules (Just _) [] = return ()
134 ifaceInstanceModules (Just if_hdl) imods
135 = hPutStr if_hdl "\n__instance_modules__\n" >>
136 hPutStr if_hdl (ppShow 100 (ppCat (map ppPStr imods)))
139 Export list: grab the Names of things that are marked Exported, sort
140 (so the interface file doesn't ``wobble'' from one compilation to the
141 next...), and print. Note that the ``module'' now contains all the
142 imported things that we are dealing with, thus including any entities
143 that we are re-exporting from somewhere else.
145 ifaceExportList Nothing{-no iface handle-} _ = return ()
147 ifaceExportList (Just if_hdl)
148 (HsModule _ _ _ _ _ typedecls _ classdecls _ _ _ binds sigs _)
150 name_flag_pairs :: Bag (Name, ExportFlag)
155 (from_binds binds emptyBag{-init accum-})
160 sorted_pairs = sortLt lexical_lt (bagToList name_flag_pairs)
163 hPutStr if_hdl "\n__exports__\n" >>
164 hPutStr if_hdl (ppShow 100 (ppAboves (map pp_pair sorted_pairs)))
166 from_ty (TyData _ n _ _ _ _ _) acc = maybe_add acc n
167 from_ty (TyNew _ n _ _ _ _ _) acc = maybe_add acc n
168 from_ty (TySynonym n _ _ _) acc = maybe_add acc n
170 from_cls (ClassDecl _ n _ _ _ _ _) acc = maybe_add acc n
172 from_sig (Sig n _ _ _) acc = maybe_add acc n
174 from_binds bs acc = maybe_add_list acc (collectTopLevelBinders bs)
177 maybe_add :: Bag (Name, ExportFlag) -> RnName -> Bag (Name, ExportFlag)
180 | exportFlagOn ef = acc `snocBag` (n, ef)
184 ef = nameExportFlag n
187 maybe_add_list acc [] = acc
188 maybe_add_list acc (n:ns) = maybe_add (maybe_add_list acc ns) n
191 lexical_lt (n1,_) (n2,_) = nameOrigName n1 < nameOrigName n2
195 = ppBeside (ppr_name n) (pp_export ef)
197 pp_export ExportAll = ppPStr SLIT("(..)")
198 pp_export ExportAbs = ppNil
202 ifaceFixities Nothing{-no iface handle-} _ = return ()
204 ifaceFixities (Just if_hdl) (HsModule _ _ _ _ fixities _ _ _ _ _ _ _ _ _)
206 local_fixities = filter from_here fixities
208 if null local_fixities then
211 hPutStr if_hdl "\n__fixities__\n" >>
212 hPutStr if_hdl (ppShow 100 (ppAboves (map ppSemid local_fixities)))
214 from_here (InfixL v _) = isLocallyDefined v
215 from_here (InfixR v _) = isLocallyDefined v
216 from_here (InfixN v _) = isLocallyDefined v
220 ifaceDecls Nothing{-no iface handle-} _ = return ()
222 ifaceDecls (Just if_hdl) (vals, tycons, classes, _)
224 exported_classes = filter isExported classes
225 exported_tycons = filter isExported tycons
226 exported_vals = filter isExported vals
228 sorted_classes = sortLt ltLexical exported_classes
229 sorted_tycons = sortLt ltLexical exported_tycons
230 sorted_vals = sortLt ltLexical exported_vals
232 ASSERT(not (null exported_classes && null exported_tycons && null exported_vals))
234 hPutStr if_hdl "\n__declarations__\n" >>
235 hPutStr if_hdl (ppShow 100 (ppAboves [
236 ppAboves (map ppr_class sorted_classes),
237 ppAboves (map ppr_tycon sorted_tycons),
238 ppAboves [ppr_val v (idType v) | v <- sorted_vals]]))
242 ifaceInstances Nothing{-no iface handle-} _ = return ()
244 ifaceInstances (Just if_hdl) (_, _, _, insts)
246 exported_insts = filter is_exported_inst (bagToList insts)
248 sorted_insts = sortLt lt_inst exported_insts
250 if null exported_insts then
253 hPutStr if_hdl "\n__instances__\n" >>
254 hPutStr if_hdl (ppShow 100 (ppAboves (map pp_inst sorted_insts)))
256 is_exported_inst (InstInfo clas _ ty _ _ _ _ _ from_here _ _ _)
257 = from_here -- && ...
260 lt_inst (InstInfo clas1 _ ty1 _ _ _ _ _ _ _ _ _)
261 (InstInfo clas2 _ ty2 _ _ _ _ _ _ _ _ _)
263 tycon1 = fst (getAppTyCon ty1)
264 tycon2 = fst (getAppTyCon ty2)
266 case (origName clas1 `cmp` origName clas2) of
269 EQ_ -> origName tycon1 < origName tycon2
272 pp_inst (InstInfo clas tvs ty theta _ _ _ _ _ _ _ _)
274 forall_ty = mkSigmaTy tvs theta (mkDictTy clas ty)
275 renumbered_ty = initNmbr (nmbrType forall_ty)
277 ppBesides [ppPStr SLIT("instance "), ppr_ty renumbered_ty, ppSemi]
280 %************************************************************************
282 \subsection{Printing tycons, classes, ...}
284 %************************************************************************
287 ppr_class :: Class -> Pretty
290 = --pprTrace "ppr_class:" (ppr PprDebug c) $
291 case (initNmbr (nmbrClass c)) of { -- renumber it!
292 Class _ n tyvar super_classes sdsels ops sels defms insts links ->
294 ppAbove (ppCat [ppPStr SLIT("class"), ppr_theta tyvar super_classes,
295 ppr_name n, ppr_tyvar tyvar,
296 if null ops then ppSemi else ppStr "where {"])
299 else ppAbove (ppNest 2 (ppAboves (map ppr_op ops)))
304 ppr_theta :: TyVar -> [Class] -> Pretty
306 ppr_theta tv [] = ppNil
307 ppr_theta tv [sc] = ppBeside (ppr_assert tv sc) (ppStr " =>")
308 ppr_theta tv super_classes
309 = ppBesides [ppLparen,
310 ppIntersperse pp'SP{-'-} (map (ppr_assert tv) super_classes),
313 ppr_assert tv (Class _ n _ _ _ _ _ _ _ _) = ppCat [ppr_name n, ppr_tyvar tv]
315 ppr_op (ClassOp o _ ty) = pp_sig (Unqual o) ty
319 ppr_val v ty -- renumber the type first!
320 = --pprTrace "ppr_val:" (ppr PprDebug v) $
321 pp_sig v (initNmbr (nmbrType ty))
324 = ppBesides [ppr_name op, ppPStr SLIT(" :: "), ppr_ty ty, ppSemi]
329 = --pprTrace "ppr_tycon:" (ppr PprDebug tycon) $
330 ppr_tc (initNmbr (nmbrTyCon tycon))
332 ------------------------
333 ppr_tc (PrimTyCon _ n _)
334 = ppCat [ ppStr "{- data", ppr_name n, ppStr " *built-in* -}" ]
337 = ppCat [ ppStr "{- data", ppr_name FunTyCon, ppStr " *built-in* -}" ]
339 ppr_tc (TupleTyCon _ n _)
340 = ppCat [ ppStr "{- ", ppr_name n, ppStr "-}" ]
342 ppr_tc (SynTyCon _ n _ _ tvs expand)
344 pp_tyvars = map ppr_tyvar tvs
346 ppBesides [ppPStr SLIT("type "), ppr_name n, ppSP, ppIntersperse ppSP pp_tyvars,
347 ppPStr SLIT(" = "), ppr_ty expand, ppSemi]
349 ppr_tc this_tycon@(DataTyCon u n k tvs ctxt cons derivings data_or_new)
350 = ppHang (ppCat [pp_data_or_new,
353 ppIntersperse ppSP (map ppr_tyvar tvs)])
355 (ppBeside pp_unabstract_condecls ppSemi)
356 -- NB: we do not print deriving info in interfaces
358 pp_data_or_new = case data_or_new of
359 DataType -> ppPStr SLIT("data")
360 NewType -> ppPStr SLIT("newtype")
362 ppr_context [] = ppNil
363 ppr_context [(c,t)] = ppCat [ppr_name c, ppr_ty t, ppStr "=>"]
365 = ppBesides[ppLparen,
366 ppInterleave ppComma [ppCat [ppr_name c, ppr_ty t] | (c,t) <- cs],
367 ppRparen, ppStr " =>"]
369 yes_we_print_condecls
370 = case (getExportFlag n) of
374 pp_unabstract_condecls
375 = if yes_we_print_condecls
376 then ppCat [ppEquals, pp_condecls]
383 ppSep ((ppr_con c) : (map ppr_next_con cs))
385 ppr_next_con con = ppCat [ppChar '|', ppr_con con]
389 (_, _, con_arg_tys, _) = dataConSig con
390 labels = dataConFieldLabels con -- none if not a record
391 strict_marks = dataConStrictMarks con
393 ppCat [ppr_unq_name con, ppr_fields labels strict_marks con_arg_tys]
395 ppr_fields labels strict_marks con_arg_tys
396 = if null labels then -- not a record thingy
397 ppIntersperse ppSP (zipWithEqual ppr_bang_ty strict_marks con_arg_tys)
400 ppInterleave ppComma (zipWith3Equal ppr_field labels strict_marks con_arg_tys),
404 = ppBeside (case b of { MarkedStrict -> ppChar '!'; _ -> ppNil })
405 (pprParendType PprInterface t)
408 = ppBesides [ppr_unq_name l, ppPStr SLIT(" :: "),
409 case b of { MarkedStrict -> ppChar '!'; _ -> ppNil },