fb1e504c43d0142686b69ad84cf7d3aca2e6ac44
[ghc-hetmet.git] / ghc / compiler / main / MkIface.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
3 %
4 \section[MkIface]{Print an interface for a module}
5
6 \begin{code}
7 module MkIface ( 
8         mkModDetails, mkModDetailsFromIface, completeIface, 
9         writeIface, pprIface
10   ) where
11
12 #include "HsVersions.h"
13
14 import HsSyn
15 import HsCore           ( HsIdInfo(..), UfExpr(..), toUfExpr, toUfBndr )
16 import HsTypes          ( toHsTyVars )
17 import BasicTypes       ( Fixity(..), NewOrData(..),
18                           Version, initialVersion, bumpVersion, isLoopBreaker
19                         )
20 import RnMonad
21 import RnHsSyn          ( RenamedInstDecl, RenamedTyClDecl )
22 import TcHsSyn          ( TypecheckedRuleDecl )
23 import HscTypes         ( VersionInfo(..), ModIface(..), ModDetails(..),
24                           IfaceDecls, mkIfaceDecls, dcl_tycl, dcl_rules, dcl_insts,
25                           TyThing(..), DFunId, TypeEnv, isTyClThing, Avails,
26                           WhatsImported(..), GenAvailInfo(..), 
27                           ImportVersion, AvailInfo, Deprecations(..)
28                         )
29
30 import CmdLineOpts
31 import Id               ( Id, idType, idInfo, omitIfaceSigForId, isUserExportedId, hasNoBinding,
32                           idSpecialisation, idName, setIdInfo
33                         )
34 import Var              ( isId )
35 import VarSet
36 import DataCon          ( StrictnessMark(..), dataConSig, dataConFieldLabels, dataConStrictMarks )
37 import IdInfo           -- Lots
38 import CoreSyn          ( CoreExpr, CoreBind, Bind(..), CoreRule(..), IdCoreRule, 
39                           isBuiltinRule, rulesRules, rulesRhsFreeVars, emptyCoreRules,
40                           bindersOfBinds
41                         )
42 import CoreFVs          ( exprSomeFreeVars, ruleSomeLhsFreeVars, ruleSomeFreeVars )
43 import CoreUnfold       ( okToUnfoldInHiFile, mkTopUnfolding, neverUnfold, unfoldingTemplate, noUnfolding )
44 import Name             ( isLocallyDefined, getName, 
45                           Name, NamedThing(..)
46                         )
47 import Name     -- Env
48 import OccName          ( pprOccName )
49 import TyCon            ( TyCon, getSynTyConDefn, isSynTyCon, isNewTyCon, isAlgTyCon,
50                           tyConTheta, tyConTyVars, tyConDataCons, tyConFamilySize, isClassTyCon
51                         )
52 import Class            ( classExtraBigSig, DefMeth(..) )
53 import FieldLabel       ( fieldLabelType )
54 import Type             ( splitSigmaTy, tidyTopType, deNoteType )
55 import SrcLoc           ( noSrcLoc )
56 import Outputable
57 import Module           ( ModuleName )
58
59 import List             ( partition )
60 import IO               ( IOMode(..), openFile, hClose )
61 \end{code}
62
63
64 %************************************************************************
65 %*                                                                      *
66 \subsection{Write a new interface file}
67 %*                                                                      *
68 %************************************************************************
69
70 \begin{code}
71 mkModDetails :: TypeEnv -> [DFunId]     -- From typechecker
72              -> [CoreBind] -> [Id]      -- Final bindings, plus the top-level Ids from the
73                                         -- code generator; they have authoritative arity info
74              -> [IdCoreRule]            -- Tidy orphan rules
75              -> ModDetails
76 mkModDetails type_env dfun_ids tidy_binds stg_ids orphan_rules
77   = ModDetails { md_types = new_type_env,
78                  md_rules = rule_dcls,
79                  md_insts = dfun_ids }
80   where
81         -- The competed type environment is gotten from
82         --      a) keeping the types and classes
83         --      b) removing all Ids, and Ids with correct IdInfo
84         --              gotten from the bindings
85         -- From (b) we keep only those Ids with Global names, plus Ids
86         --          accessible from them (notably via unfoldings)
87         -- This truncates the type environment to include only the 
88         -- exported Ids and things needed from them, which saves space
89         --
90         -- However, we do keep things like constructors, which should not appear 
91         -- in interface files, because they are needed by importing modules when
92         -- using the compilation manager
93     new_type_env = mkNameEnv [(getName tycl, tycl) | tycl <- orig_type_env, isTyClThing tycl]
94                         `plusNameEnv`
95                    mkNameEnv [(idName id, AnId id) | id <- final_ids]
96
97     orig_type_env = nameEnvElts type_env
98
99     final_ids = bindsToIds (mkVarSet dfun_ids `unionVarSet` orphan_rule_ids)
100                            (mkVarSet stg_ids)
101                            tidy_binds
102
103         -- The complete rules are gotten by combining
104         --      a) the orphan rules
105         --      b) rules embedded in the top-level Ids
106     rule_dcls | opt_OmitInterfacePragmas = []
107               | otherwise                 = getRules orphan_rules tidy_binds (mkVarSet final_ids)
108
109     orphan_rule_ids = unionVarSets [ ruleSomeFreeVars interestingId rule 
110                                    | (_, rule) <- orphan_rules]
111
112
113 -- This version is used when we are re-linking a module
114 -- so we've only run the type checker on its previous interface 
115 mkModDetailsFromIface :: TypeEnv -> [DFunId]    -- From typechecker
116                       -> [TypecheckedRuleDecl]
117                       -> ModDetails
118 mkModDetailsFromIface type_env dfun_ids rules
119   = ModDetails { md_types = type_env,
120                  md_rules = rule_dcls,
121                  md_insts = dfun_ids }
122   where
123     rule_dcls = [(id,rule) | IfaceRuleOut id rule <- rules]
124         -- All the rules from an interface are of the IfaceRuleOut form
125
126
127 completeIface :: Maybe ModIface         -- The old interface, if we have it
128               -> ModIface               -- The new one, minus the decls and versions
129               -> ModDetails             -- The ModDetails for this module
130               -> (ModIface, Maybe SDoc) -- The new one, complete with decls and versions
131                                         -- The SDoc is a debug document giving differences
132                                         -- Nothing => no change
133
134         -- NB: 'Nothing' means that even the usages havn't changed, so there's no
135         --     need to write a new interface file.  But even if the usages have
136         --     changed, the module version may not have.
137 completeIface maybe_old_iface new_iface mod_details 
138   = addVersionInfo maybe_old_iface (new_iface { mi_decls = new_decls })
139   where
140      new_decls   = mkIfaceDecls ty_cls_dcls rule_dcls inst_dcls
141      inst_dcls   = map ifaceInstance (md_insts mod_details)
142      ty_cls_dcls = foldNameEnv ifaceTyCls [] (md_types mod_details)
143      rule_dcls   = map ifaceRule (md_rules mod_details)
144 \end{code}
145
146
147 %************************************************************************
148 %*                                                                      *
149 \subsection{Types and classes}
150 %*                                                                      *
151 %************************************************************************
152
153 \begin{code}
154 ifaceTyCls :: TyThing -> [RenamedTyClDecl] -> [RenamedTyClDecl]
155 ifaceTyCls (AClass clas) so_far
156   = cls_decl : so_far
157   where
158     cls_decl = ClassDecl (toHsContext sc_theta)
159                          (getName clas)          
160                          (toHsTyVars clas_tyvars)
161                          (toHsFDs clas_fds)
162                          (map toClassOpSig op_stuff)
163                          EmptyMonoBinds
164                          [] noSrcLoc
165
166     (clas_tyvars, clas_fds, sc_theta, _, op_stuff) = classExtraBigSig clas
167
168     toClassOpSig (sel_id, def_meth)
169         = ASSERT(sel_tyvars == clas_tyvars)
170           ClassOpSig (getName sel_id) (Just def_meth') (toHsType op_ty) noSrcLoc
171         where
172           (sel_tyvars, _, op_ty) = splitSigmaTy (idType sel_id)
173           def_meth' = case def_meth of
174                          NoDefMeth  -> NoDefMeth
175                          GenDefMeth -> GenDefMeth
176                          DefMeth id -> DefMeth (getName id)
177
178 ifaceTyCls (ATyCon tycon) so_far
179   | isClassTyCon tycon = so_far
180   | otherwise          = ty_decl : so_far
181   where
182     ty_decl | isSynTyCon tycon
183             = TySynonym (getName tycon)(toHsTyVars tyvars) 
184                         (toHsType syn_ty) noSrcLoc
185
186             | isAlgTyCon tycon
187             = TyData new_or_data (toHsContext (tyConTheta tycon))
188                      (getName tycon)      
189                      (toHsTyVars tyvars)
190                      (map ifaceConDecl (tyConDataCons tycon))
191                      (tyConFamilySize tycon)
192                      Nothing noSrcLoc (panic "gen1") (panic "gen2")
193
194             | otherwise = pprPanic "ifaceTyCls" (ppr tycon)
195
196     tyvars      = tyConTyVars tycon
197     (_, syn_ty) = getSynTyConDefn tycon
198     new_or_data | isNewTyCon tycon = NewType
199                 | otherwise        = DataType
200
201     ifaceConDecl data_con 
202         = ConDecl (getName data_con) (error "ifaceConDecl")
203                   (toHsTyVars ex_tyvars)
204                   (toHsContext ex_theta)
205                   details noSrcLoc
206         where
207           (tyvars1, _, ex_tyvars, ex_theta, arg_tys, tycon1) = dataConSig data_con
208           field_labels   = dataConFieldLabels data_con
209           strict_marks   = dataConStrictMarks data_con
210           details | null field_labels
211                   = ASSERT( tycon == tycon1 && tyvars == tyvars1 )
212                     VanillaCon (zipWith mk_bang_ty strict_marks arg_tys)
213
214                   | otherwise
215                   = RecCon (zipWith mk_field strict_marks field_labels)
216
217     mk_bang_ty NotMarkedStrict     ty = Unbanged (toHsType ty)
218     mk_bang_ty (MarkedUnboxed _ _) ty = Unpacked (toHsType ty)
219     mk_bang_ty MarkedStrict        ty = Banged   (toHsType ty)
220
221     mk_field strict_mark field_label
222         = ([getName field_label], mk_bang_ty strict_mark (fieldLabelType field_label))
223
224 ifaceTyCls (AnId id) so_far
225   | omitIfaceSigForId id = so_far
226   | otherwise            = iface_sig : so_far
227   where
228     iface_sig = IfaceSig (getName id) (toHsType id_type) hs_idinfo noSrcLoc
229
230     id_type = idType id
231     id_info = idInfo id
232
233     hs_idinfo | opt_OmitInterfacePragmas = []
234               | otherwise                = arity_hsinfo  ++ caf_hsinfo  ++ cpr_hsinfo ++ 
235                                            strict_hsinfo ++ wrkr_hsinfo ++ unfold_hsinfo
236
237     ------------  Arity  --------------
238     arity_hsinfo = case arityInfo id_info of
239                         a@(ArityExactly n) -> [HsArity a]
240                         other              -> []
241
242     ------------ Caf Info --------------
243     caf_hsinfo = case cafInfo id_info of
244                    NoCafRefs -> [HsNoCafRefs]
245                    otherwise -> []
246
247     ------------ CPR Info --------------
248     cpr_hsinfo = case cprInfo id_info of
249                    ReturnsCPR -> [HsCprInfo]
250                    NoCPRInfo  -> []
251
252     ------------  Strictness  --------------
253     strict_hsinfo = case strictnessInfo id_info of
254                         NoStrictnessInfo -> []
255                         info             -> [HsStrictness info]
256
257
258     ------------  Worker  --------------
259     wrkr_hsinfo = case workerInfo id_info of
260                     HasWorker work_id wrap_arity -> [HsWorker (getName work_id)]
261                     NoWorker                     -> []
262
263     ------------  Unfolding  --------------
264     unfold_info = unfoldingInfo id_info
265     inline_prag = inlinePragInfo id_info
266     rhs         = unfoldingTemplate unfold_info
267     unfold_hsinfo | neverUnfold unfold_info = []
268                   | otherwise               = [HsUnfold inline_prag (toUfExpr rhs)]
269 \end{code}
270
271
272 %************************************************************************
273 %*                                                                      *
274 \subsection{Instances and rules}
275 %*                                                                      *
276 %************************************************************************
277
278 \begin{code}
279 ifaceInstance :: DFunId -> RenamedInstDecl
280 ifaceInstance dfun_id
281   = InstDecl (toHsType tidy_ty) EmptyMonoBinds [] (Just (getName dfun_id)) noSrcLoc                      
282   where
283     tidy_ty = tidyTopType (deNoteType (idType dfun_id))
284                 -- The deNoteType is very important.   It removes all type
285                 -- synonyms from the instance type in interface files.
286                 -- That in turn makes sure that when reading in instance decls
287                 -- from interface files that the 'gating' mechanism works properly.
288                 -- Otherwise you could have
289                 --      type Tibble = T Int
290                 --      instance Foo Tibble where ...
291                 -- and this instance decl wouldn't get imported into a module
292                 -- that mentioned T but not Tibble.
293
294 ifaceRule (id, BuiltinRule _)
295   = pprTrace "toHsRule: builtin" (ppr id) (bogusIfaceRule id)
296
297 ifaceRule (id, Rule name bndrs args rhs)
298   = IfaceRule name (map toUfBndr bndrs) (getName id)
299               (map toUfExpr args) (toUfExpr rhs) noSrcLoc
300
301 bogusIfaceRule id
302   = IfaceRule SLIT("bogus") [] (getName id) [] (UfVar (getName id)) noSrcLoc
303 \end{code}
304
305
306 %************************************************************************
307 %*                                                                      *
308 \subsection{Compute final Ids}
309 %*                                                                      * 
310 %************************************************************************
311
312 A "final Id" has exactly the IdInfo for going into an interface file, or
313 exporting to another module.
314
315 \begin{code}
316 bindsToIds :: IdSet             -- These Ids are needed already
317            -> IdSet             -- Ids used at code-gen time; they have better pragma info!
318            -> [CoreBind]        -- In dependency order, later depend on earlier
319            -> [Id]              -- Set of Ids actually spat out, complete with exactly the IdInfo
320                                 -- they need for exporting to another module
321
322 bindsToIds needed_ids codegen_ids binds
323   = go needed_ids (reverse binds) []
324                 -- Reverse so that later things will 
325                 -- provoke earlier ones to be emitted
326   where
327         -- The 'needed' set contains the Ids that are needed by earlier
328         -- interface file emissions.  If the Id isn't in this set, and isn't
329         -- exported, there's no need to emit anything
330     need_id needed_set id = id `elemVarSet` needed_set || isUserExportedId id 
331
332     go needed [] emitted
333         | not (isEmptyVarSet needed) = pprTrace "ifaceBinds: free vars:" 
334                                           (sep (map ppr (varSetElems needed)))
335                                        emitted
336         | otherwise                  = emitted
337
338     go needed (NonRec id rhs : binds) emitted
339         | need_id needed id = go new_needed binds (new_id:emitted)
340         | otherwise         = go needed     binds emitted
341         where
342           (new_id, extras) = mkFinalId codegen_ids False id rhs
343           new_needed       = (needed `unionVarSet` extras) `delVarSet` id
344
345         -- Recursive groups are a bit more of a pain.  We may only need one to
346         -- start with, but it may call out the next one, and so on.  So we
347         -- have to look for a fixed point.  We don't want necessarily them all, 
348         -- because without -O we may only need the first one (if we don't emit
349         -- its unfolding)
350     go needed (Rec pairs : binds) emitted
351         = go needed' binds emitted' 
352         where
353           (new_emitted, extras) = go_rec needed pairs
354           needed'  = (needed `unionVarSet` extras) `minusVarSet` mkVarSet (map fst pairs) 
355           emitted' = new_emitted ++ emitted 
356
357     go_rec :: IdSet -> [(Id,CoreExpr)] -> ([Id], IdSet)
358     go_rec needed pairs
359         | null needed_prs = ([], emptyVarSet)
360         | otherwise       = (emitted ++           more_emitted,
361                              extras `unionVarSet` more_extras)
362         where
363           (needed_prs,leftover_prs)   = partition is_needed pairs
364           (emitted, extras_s)         = unzip [ mkFinalId codegen_ids True id rhs 
365                                               | (id,rhs) <- needed_prs, not (omitIfaceSigForId id)]
366           extras                      = unionVarSets extras_s
367           (more_emitted, more_extras) = go_rec extras leftover_prs
368
369           is_needed (id,_) = need_id needed id
370 \end{code}
371
372
373
374 \begin{code}
375 mkFinalId :: IdSet              -- The Ids with arity info from the code generator
376           -> Bool               -- True <=> recursive, so don't include unfolding
377           -> Id
378           -> CoreExpr           -- The Id's right hand side
379           -> (Id, IdSet)        -- The emitted id, plus any *extra* needed Ids
380
381 mkFinalId codegen_ids is_rec id rhs
382   | omitIfaceSigForId id 
383   = (id, emptyVarSet)           -- An optimisation for top-level constructors and suchlike
384   | otherwise
385   = (id `setIdInfo` new_idinfo, new_needed_ids)
386   where
387     core_idinfo = idInfo id
388     stg_idinfo  = case lookupVarSet codegen_ids id of
389                         Just id' -> idInfo id'
390                         Nothing  -> pprTrace "ifaceBinds not found:" (ppr id) $
391                                     idInfo id
392
393     new_idinfo | opt_OmitInterfacePragmas
394                = vanillaIdInfo
395                | otherwise                
396                = core_idinfo `setArityInfo`      arity_info
397                              `setCafInfo`        cafInfo stg_idinfo
398                              `setUnfoldingInfo`  unfold_info
399                              `setWorkerInfo`     worker_info
400                              `setSpecInfo`       emptyCoreRules
401         -- We zap the specialisations because they are
402         -- passed on separately through the modules IdCoreRules
403
404     ------------  Arity  --------------
405     arity_info = arityInfo stg_idinfo
406     stg_arity  = arityLowerBound arity_info
407
408     ------------  Worker  --------------
409         -- We only treat a function as having a worker if
410         -- the exported arity (which is now the number of visible lambdas)
411         -- is the same as the arity at the moment of the w/w split
412         -- If so, we can safely omit the unfolding inside the wrapper, and
413         -- instead re-generate it from the type/arity/strictness info
414         -- But if the arity has changed, we just take the simple path and
415         -- put the unfolding into the interface file, forgetting the fact
416         -- that it's a wrapper.  
417         --
418         -- How can this happen?  Sometimes we get
419         --      f = coerce t (\x y -> $wf x y)
420         -- at the moment of w/w split; but the eta reducer turns it into
421         --      f = coerce t $wf
422         -- which is perfectly fine except that the exposed arity so far as
423         -- the code generator is concerned (zero) differs from the arity
424         -- when we did the split (2).  
425         --
426         -- All this arises because we use 'arity' to mean "exactly how many
427         -- top level lambdas are there" in interface files; but during the
428         -- compilation of this module it means "how many things can I apply
429         -- this to".
430     worker_info = case workerInfo core_idinfo of
431                      info@(HasWorker work_id wrap_arity)
432                         | wrap_arity == stg_arity -> info
433                         | otherwise               -> pprTrace "ifaceId: arity change:" (ppr id) 
434                                                      NoWorker
435                      NoWorker                     -> NoWorker
436
437     has_worker = case worker_info of
438                    HasWorker _ _ -> True
439                    other         -> False
440
441     HasWorker work_id _ = worker_info
442
443     ------------  Unfolding  --------------
444     inline_pragma  = inlinePragInfo core_idinfo
445     dont_inline    = isNeverInlinePrag inline_pragma
446     loop_breaker   = isLoopBreaker (occInfo core_idinfo)
447     bottoming_fn   = isBottomingStrictness (strictnessInfo core_idinfo)
448
449     unfolding    = mkTopUnfolding rhs
450     rhs_is_small = not (neverUnfold unfolding)
451
452     unfold_info | show_unfold = unfolding
453                 | otherwise   = noUnfolding
454
455     show_unfold = not has_worker         &&     -- Not unnecessary
456                   not bottoming_fn       &&     -- Not necessary
457                   not dont_inline        &&
458                   not loop_breaker       &&
459                   rhs_is_small           &&     -- Small enough
460                   okToUnfoldInHiFile rhs        -- No casms etc
461
462
463     ------------  Extra free Ids  --------------
464     new_needed_ids | opt_OmitInterfacePragmas = emptyVarSet
465                    | otherwise                = worker_ids      `unionVarSet`
466                                                 unfold_ids      `unionVarSet`
467                                                 spec_ids
468
469     spec_ids = filterVarSet interestingId (rulesRhsFreeVars (specInfo core_idinfo))
470
471     worker_ids | has_worker && interestingId work_id = unitVarSet work_id
472                         -- Conceivably, the worker might come from
473                         -- another module
474                | otherwise = emptyVarSet
475
476     unfold_ids | show_unfold = find_fvs rhs
477                | otherwise   = emptyVarSet
478
479     find_fvs expr = exprSomeFreeVars interestingId expr
480
481 interestingId id = isId id && isLocallyDefined id && not (hasNoBinding id)
482 \end{code}
483
484
485 \begin{code}
486 getRules :: [IdCoreRule]        -- Orphan rules
487          -> [CoreBind]          -- Bindings, with rules in the top-level Ids
488          -> IdSet               -- Ids that are exported, so we need their rules
489          -> [IdCoreRule]
490 getRules orphan_rules binds emitted
491   = orphan_rules ++ local_rules
492   where
493     local_rules  = [ (fn, rule)
494                    | fn <- bindersOfBinds binds,
495                      fn `elemVarSet` emitted,
496                      rule <- rulesRules (idSpecialisation fn),
497                      not (isBuiltinRule rule),
498                                 -- We can't print builtin rules in interface files
499                                 -- Since they are built in, an importing module
500                                 -- will have access to them anyway
501
502                         -- Sept 00: I've disabled this test.  It doesn't stop many, if any, rules
503                         -- from coming out, and to make it work properly we need to add ????
504                         --      (put it back in for now)
505                      all (`elemVarSet` emitted) (varSetElems (ruleSomeLhsFreeVars interestingId rule))
506                                 -- Spit out a rule only if all its lhs free vars are emitted
507                                 -- This is a good reason not to do it when we emit the Id itself
508                    ]
509 \end{code}
510
511
512 %************************************************************************
513 %*                                                                      *
514 \subsection{Checking if the new interface is up to date
515 %*                                                                      *
516 %************************************************************************
517
518 \begin{code}
519 addVersionInfo :: Maybe ModIface                -- The old interface, read from M.hi
520                -> ModIface                      -- The new interface decls
521                -> (ModIface, Maybe SDoc)        -- Nothing => no change; no need to write new Iface
522                                                 -- Just mi => Here is the new interface to write
523                                                 --            with correct version numbers
524
525 -- NB: the fixities, declarations, rules are all assumed
526 -- to be sorted by increasing order of hsDeclName, so that 
527 -- we can compare for equality
528
529 addVersionInfo Nothing new_iface
530 -- No old interface, so definitely write a new one!
531   = (new_iface, Just (text "No old interface available"))
532
533 addVersionInfo (Just old_iface@(ModIface { mi_version = old_version, 
534                                            mi_decls   = old_decls,
535                                            mi_fixities = old_fixities }))
536                new_iface@(ModIface { mi_decls = new_decls,
537                                      mi_fixities = new_fixities })
538
539   | no_output_change && no_usage_change
540   = (old_iface, Nothing)
541
542   | otherwise           -- Add updated version numbers
543   = (final_iface, Just pp_tc_diffs)
544         
545   where
546     final_iface = new_iface { mi_version = new_version }
547     new_version = VersionInfo { vers_module  = bumpVersion no_output_change (vers_module  old_version),
548                                 vers_exports = bumpVersion no_export_change (vers_exports old_version),
549                                 vers_rules   = bumpVersion no_rule_change   (vers_rules   old_version),
550                                 vers_decls   = tc_vers }
551
552     no_output_change = no_tc_change && no_rule_change && no_export_change
553     no_usage_change  = mi_usages old_iface == mi_usages new_iface
554
555     no_export_change = mi_exports old_iface == mi_exports new_iface             -- Kept sorted
556     no_rule_change   = dcl_rules old_decls  == dcl_rules  new_decls             -- Ditto
557
558         -- Fill in the version number on the new declarations by looking at the old declarations.
559         -- Set the flag if anything changes. 
560         -- Assumes that the decls are sorted by hsDeclName.
561     old_vers_decls = vers_decls old_version
562     (no_tc_change,  pp_tc_diffs,  tc_vers) = diffDecls old_vers_decls old_fixities new_fixities
563                                                        (dcl_tycl old_decls) (dcl_tycl new_decls)
564
565
566
567 diffDecls :: NameEnv Version                            -- Old version map
568           -> NameEnv Fixity -> NameEnv Fixity           -- Old and new fixities
569           -> [RenamedTyClDecl] -> [RenamedTyClDecl]     -- Old and new decls
570           -> (Bool,             -- True <=> no change
571               SDoc,             -- Record of differences
572               NameEnv Version)  -- New version
573
574 diffDecls old_vers old_fixities new_fixities old new
575   = diff True empty emptyNameEnv old new
576   where
577         -- When seeing if two decls are the same, 
578         -- remember to check whether any relevant fixity has changed
579     eq_tc  d1 d2 = d1 == d2 && all (same_fixity . fst) (tyClDeclNames d1)
580     same_fixity n = lookupNameEnv old_fixities n == lookupNameEnv new_fixities n
581
582     diff ok_so_far pp new_vers []  []      = (ok_so_far, pp, new_vers)
583     diff ok_so_far pp new_vers old []      = (False,     pp, new_vers)
584     diff ok_so_far pp new_vers [] (nd:nds) = diff False (pp $$ only_new nd) new_vers [] nds
585     diff ok_so_far pp new_vers (od:ods) (nd:nds)
586         = case nameOccName od_name `compare` nameOccName nd_name of
587                 LT -> diff False (pp $$ only_old od) new_vers ods      (nd:nds)
588                 GT -> diff False (pp $$ only_new nd) new_vers (od:ods) nds
589                 EQ | od `eq_tc` nd -> diff ok_so_far pp                    new_vers  ods nds
590                    | otherwise     -> diff False     (pp $$ changed od nd) new_vers' ods nds
591         where
592           od_name = tyClDeclName od
593           nd_name = tyClDeclName nd
594           new_vers' = extendNameEnv new_vers nd_name 
595                                     (bumpVersion True (lookupNameEnv_NF old_vers od_name))
596
597     only_old d   = ptext SLIT("Only in old iface:") <+> ppr d
598     only_new d   = ptext SLIT("Only in new iface:") <+> ppr d
599     changed d nd = ptext SLIT("Changed in iface: ") <+> ((ptext SLIT("Old:") <+> ppr d) $$ 
600                                                          (ptext SLIT("New:") <+> ppr nd))
601 \end{code}
602
603
604
605 %************************************************************************
606 %*                                                                      *
607 \subsection{Writing an interface file}
608 %*                                                                      *
609 %************************************************************************
610
611 \begin{code}
612 writeIface :: FilePath -> ModIface -> IO ()
613 writeIface hi_path mod_iface
614   = do  { if_hdl <- openFile hi_path WriteMode
615         ; printForIface if_hdl (pprIface mod_iface)
616         ; hClose if_hdl
617         }
618          
619 pprIface :: ModIface -> SDoc
620 pprIface iface
621  = vcat [ ptext SLIT("__interface")
622                 <+> doubleQuotes (ptext opt_InPackage)
623                 <+> ppr (mi_module iface) <+> ppr (vers_module version_info)
624                 <+> pp_sub_vers
625                 <+> (if mi_orphan iface then char '!' else empty)
626                 <+> int opt_HiVersion
627                 <+> ptext SLIT("where")
628
629         , vcat (map pprExport (mi_exports iface))
630         , vcat (map pprUsage (mi_usages iface))
631
632         , pprFixities (mi_fixities iface) (dcl_tycl decls)
633         , pprIfaceDecls (vers_decls version_info) decls
634         , pprDeprecs (mi_deprecs iface)
635         ]
636   where
637     version_info = mi_version iface
638     decls        = mi_decls iface
639     exp_vers     = vers_exports version_info
640     rule_vers    = vers_rules version_info
641
642     pp_sub_vers | exp_vers == initialVersion && rule_vers == initialVersion = empty
643                 | otherwise = brackets (ppr exp_vers <+> ppr rule_vers)
644 \end{code}
645
646 When printing export lists, we print like this:
647         Avail   f               f
648         AvailTC C [C, x, y]     C(x,y)
649         AvailTC C [x, y]        C!(x,y)         -- Exporting x, y but not C
650
651 \begin{code}
652 pprExport :: (ModuleName, Avails) -> SDoc
653 pprExport (mod, items)
654  = hsep [ ptext SLIT("__export "), ppr mod, hsep (map pp_avail items) ] <> semi
655   where
656     pp_avail :: AvailInfo -> SDoc
657     pp_avail (Avail name)                    = pprOcc name
658     pp_avail (AvailTC n [])                  = empty
659     pp_avail (AvailTC n (n':ns)) | n==n'     = pprOcc n             <> pp_export ns
660                                  | otherwise = pprOcc n <> char '|' <> pp_export (n':ns)
661     
662     pp_export []    = empty
663     pp_export names = braces (hsep (map pprOcc names))
664
665 pprOcc :: Name -> SDoc  -- Print the occurrence name only
666 pprOcc n = pprOccName (nameOccName n)
667 \end{code}
668
669
670 \begin{code}
671 pprUsage :: ImportVersion Name -> SDoc
672 pprUsage (m, has_orphans, is_boot, whats_imported)
673   = hsep [ptext SLIT("import"), ppr m, 
674           pp_orphan, pp_boot,
675           pp_versions whats_imported
676     ] <> semi
677   where
678     pp_orphan | has_orphans = char '!'
679               | otherwise   = empty
680     pp_boot   | is_boot     = char '@'
681               | otherwise   = empty
682
683         -- Importing the whole module is indicated by an empty list
684     pp_versions NothingAtAll                = empty
685     pp_versions (Everything v)              = dcolon <+> int v
686     pp_versions (Specifically vm ve nvs vr) = dcolon <+> int vm <+> pp_export_version ve <+> int vr 
687                                               <+> hsep [ pprOcc n <+> int v | (n,v) <- nvs ]
688
689         -- HACK for the moment: print the export-list version even if
690         -- we don't use it, so that syntax of interface files doesn't change
691     pp_export_version Nothing  = int 1
692     pp_export_version (Just v) = int v
693 \end{code}
694
695 \begin{code}
696 pprIfaceDecls version_map decls
697   = vcat [ vcat [ppr i <+> semi | i <- dcl_insts decls]
698          , vcat (map ppr_decl (dcl_tycl decls))
699          , pprRules (dcl_rules decls)
700          ]
701   where
702     ppr_decl d  = ppr_vers d <+> ppr d <> semi
703
704         -- Print the version for the decl
705     ppr_vers d = case lookupNameEnv version_map (tyClDeclName d) of
706                    Nothing -> empty
707                    Just v  -> int v
708 \end{code}
709
710 \begin{code}
711 pprFixities fixity_map decls
712   = hsep [ ppr fix <+> ppr n 
713          | d <- decls, 
714            (n,_) <- tyClDeclNames d, 
715            Just fix <- [lookupNameEnv fixity_map n]] <> semi
716
717 pprRules []    = empty
718 pprRules rules = hsep [ptext SLIT("{-## __R"), vcat (map ppr rules), ptext SLIT("##-}")]
719
720 pprDeprecs NoDeprecs = empty
721 pprDeprecs deprecs   = ptext SLIT("{-## __D") <+> guts <+> ptext SLIT("##-}")
722                      where
723                        guts = case deprecs of
724                                 DeprecAll txt  -> ptext txt
725                                 DeprecSome env -> pp_deprecs env
726
727 pp_deprecs env = vcat (punctuate semi (map pp_deprec (nameEnvElts env)))
728                where
729                  pp_deprec (name, txt) = pprOcc name <+> ptext txt
730 \end{code}