[project @ 1999-05-21 12:52:28 by simonmar]
[ghc-hetmet.git] / ghc / compiler / rename / Rename.lhs
1 %
2 % (c) The GRASP Project, Glasgow University, 1992-1998
3 %
4 \section[Rename]{Renaming and dependency analysis passes}
5
6 \begin{code}
7 module Rename ( renameModule ) where
8
9 #include "HsVersions.h"
10
11 import HsSyn
12 import RdrHsSyn         ( RdrNameHsModule )
13 import RnHsSyn          ( RenamedHsModule, RenamedHsDecl, 
14                           extractHsTyNames, extractHsCtxtTyNames
15                         )
16
17 import CmdLineOpts      ( opt_HiMap, opt_D_dump_rn_trace,
18                           opt_D_dump_rn, opt_D_dump_rn_stats,
19                           opt_WarnUnusedBinds, opt_WarnUnusedImports
20                         )
21 import RnMonad
22 import RnNames          ( getGlobalNames )
23 import RnSource         ( rnSourceDecls, rnDecl )
24 import RnIfaces         ( getImportedInstDecls, importDecl, getImportVersions,
25                           getImportedRules, loadHomeInterface, getSlurped
26                         )
27 import RnEnv            ( availName, availNames, availsToNameSet, 
28                           warnUnusedTopNames, mapFvRn,
29                           FreeVars, plusFVs, plusFV, unitFV, emptyFVs, isEmptyFVs
30                         )
31 import Module           ( Module, ModuleName, pprModule, mkSearchPath, mkThisModule )
32 import Name             ( Name, isLocallyDefined,
33                           NamedThing(..), ImportReason(..), Provenance(..),
34                           pprOccName, nameOccName,
35                           getNameProvenance, occNameUserString, 
36                           maybeWiredInTyConName, maybeWiredInIdName, isWiredInName
37                         )
38 import Id               ( idType )
39 import DataCon          ( dataConTyCon, dataConType )
40 import TyCon            ( TyCon, tyConDataCons, isSynTyCon, getSynTyConDefn )
41 import RdrName          ( RdrName )
42 import NameSet
43 import PrelMods         ( mAIN_Name, pREL_MAIN_Name )
44 import TysWiredIn       ( unitTyCon, intTyCon, doubleTyCon, boolTyCon )
45 import PrelInfo         ( ioTyCon_NAME, thinAirIdNames )
46 import Type             ( namesOfType, funTyCon )
47 import ErrUtils         ( pprBagOfErrors, pprBagOfWarnings,
48                           doIfSet, dumpIfSet, ghcExit
49                         )
50 import BasicTypes       ( NewOrData(..) )
51 import Bag              ( isEmptyBag, bagToList )
52 import FiniteMap        ( fmToList, delListFromFM, addToFM, sizeFM, eltsFM )
53 import UniqSupply       ( UniqSupply )
54 import Util             ( equivClasses )
55 import Maybes           ( maybeToBool )
56 import Outputable
57 \end{code}
58
59
60
61 \begin{code}
62 renameModule :: UniqSupply
63              -> RdrNameHsModule
64              -> IO (Maybe 
65                       ( Module
66                       , RenamedHsModule   -- Output, after renaming
67                       , InterfaceDetails  -- Interface; for interface file generation
68                       , RnNameSupply      -- Final env; for renaming derivings
69                       , [ModuleName]      -- Imported modules; for profiling
70                       ))
71
72 renameModule us this_mod@(HsModule mod_name vers exports imports local_decls loc)
73   =     -- Initialise the renamer monad
74     initRn mod_name us (mkSearchPath opt_HiMap) loc
75            (rename this_mod)                            >>=
76         \ (maybe_rn_stuff, rn_errs_bag, rn_warns_bag) ->
77
78         -- Check for warnings
79     doIfSet (not (isEmptyBag rn_warns_bag))
80             (printErrs (pprBagOfWarnings rn_warns_bag)) >>
81
82         -- Check for errors; exit if so
83     doIfSet (not (isEmptyBag rn_errs_bag))
84             (printErrs (pprBagOfErrors rn_errs_bag)      >>
85              ghcExit 1
86             )                                            >>
87
88         -- Dump output, if any
89     (case maybe_rn_stuff of
90         Nothing  -> return ()
91         Just results@(_, rn_mod, _, _, _)
92                  -> dumpIfSet opt_D_dump_rn "Renamer:"
93                               (ppr rn_mod)
94     )                                                   >>
95
96         -- Return results
97     return maybe_rn_stuff
98 \end{code}
99
100
101 \begin{code}
102 rename this_mod@(HsModule mod_name vers exports imports local_decls loc)
103   =     -- FIND THE GLOBAL NAME ENVIRONMENT
104     getGlobalNames this_mod                     `thenRn` \ maybe_stuff ->
105
106         -- CHECK FOR EARLY EXIT
107     if not (maybeToBool maybe_stuff) then
108         -- Everything is up to date; no need to recompile further
109         rnStats []              `thenRn_`
110         returnRn Nothing
111     else
112     let
113         Just (export_env, gbl_env, fixity_env, global_avail_env) = maybe_stuff
114     in
115
116         -- RENAME THE SOURCE
117     initRnMS gbl_env fixity_env SourceMode (
118         rnSourceDecls local_decls
119     )                                   `thenRn` \ (rn_local_decls, source_fvs) ->
120
121         -- SLURP IN ALL THE NEEDED DECLARATIONS
122     let
123         real_source_fvs = implicitFVs mod_name `plusFV` source_fvs
124                 -- It's important to do the "plus" this way round, so that
125                 -- when compiling the prelude, locally-defined (), Bool, etc
126                 -- override the implicit ones. 
127     in
128     slurpImpDecls real_source_fvs       `thenRn` \ rn_imp_decls ->
129
130         -- EXIT IF ERRORS FOUND
131     checkErrsRn                         `thenRn` \ no_errs_so_far ->
132     if not no_errs_so_far then
133         -- Found errors already, so exit now
134         rnStats []              `thenRn_`
135         returnRn Nothing
136     else
137
138         -- GENERATE THE VERSION/USAGE INFO
139     getImportVersions mod_name exports                  `thenRn` \ my_usages ->
140     getNameSupplyRn                                     `thenRn` \ name_supply ->
141
142         -- REPORT UNUSED NAMES
143     reportUnusedNames gbl_env global_avail_env
144                       export_env
145                       source_fvs                        `thenRn_`
146
147         -- RETURN THE RENAMED MODULE
148     let
149         has_orphans        = any isOrphanDecl rn_local_decls
150         direct_import_mods = [mod | ImportDecl mod _ _ _ _ _ <- imports]
151         rn_all_decls       = rn_imp_decls ++ rn_local_decls 
152         renamed_module = HsModule mod_name vers 
153                                   trashed_exports trashed_imports
154                                   rn_all_decls
155                                   loc
156     in
157     rnStats rn_imp_decls        `thenRn_`
158     returnRn (Just (mkThisModule mod_name,
159                     renamed_module, 
160                     (has_orphans, my_usages, export_env),
161                     name_supply,
162                     direct_import_mods))
163   where
164     trashed_exports  = {-trace "rnSource:trashed_exports"-} Nothing
165     trashed_imports  = {-trace "rnSource:trashed_imports"-} []
166 \end{code}
167
168 @implicitFVs@ forces the renamer to slurp in some things which aren't
169 mentioned explicitly, but which might be needed by the type checker.
170
171 \begin{code}
172 implicitFVs mod_name
173   = implicit_main               `plusFV` 
174     mkNameSet default_tys       `plusFV`
175     mkNameSet thinAirIdNames
176   where
177         -- Add occurrences for Int, Double, and (), because they
178         -- are the types to which ambigious type variables may be defaulted by
179         -- the type checker; so they won't always appear explicitly.
180         -- [The () one is a GHC extension for defaulting CCall results.]
181         -- ALSO: funTyCon, since it occurs implicitly everywhere!
182         --       (we don't want to be bothered with making funTyCon a
183         --        free var at every function application!)
184     default_tys = [getName intTyCon, getName doubleTyCon,
185                    getName unitTyCon, getName funTyCon, getName boolTyCon]
186
187         -- Add occurrences for IO or PrimIO
188     implicit_main |  mod_name == mAIN_Name
189                   || mod_name == pREL_MAIN_Name = unitFV ioTyCon_NAME
190                   |  otherwise                  = emptyFVs
191 \end{code}
192
193 \begin{code}
194 isOrphanDecl (InstD (InstDecl inst_ty _ _ _ _))
195   = not (foldNameSet ((||) . isLocallyDefined) False (extractHsTyNames inst_ty))
196 isOrphanDecl (RuleD (RuleDecl _ _ _ lhs _ _))
197   = check lhs
198   where
199     check (HsVar v)   = not (isLocallyDefined v)
200     check (HsApp f a) = check f && check a
201     check other       = True
202 isOrphanDecl other = False
203 \end{code}
204
205
206 %*********************************************************
207 %*                                                       *
208 \subsection{Slurping declarations}
209 %*                                                       *
210 %*********************************************************
211
212 \begin{code}
213 -------------------------------------------------------
214 slurpImpDecls source_fvs
215   = traceRn (text "slurpImp" <+> fsep (map ppr (nameSetToList source_fvs))) `thenRn_`
216
217         -- The current slurped-set records all local things
218     getSlurped                                  `thenRn` \ source_binders ->
219     slurpSourceRefs source_binders source_fvs   `thenRn` \ (decls1, needed1, inst_gates) ->
220
221         -- Now we can get the instance decls
222     slurpInstDecls decls1 needed1 inst_gates    `thenRn` \ (decls2, needed2) ->
223
224         -- And finally get everything else
225     closeDecls   decls2 needed2
226   where
227
228 -------------------------------------------------------
229 slurpSourceRefs :: NameSet                      -- Variables defined in source
230                 -> FreeVars                     -- Variables referenced in source
231                 -> RnMG ([RenamedHsDecl],
232                          FreeVars,              -- Un-satisfied needs
233                          FreeVars)              -- "Gates"
234 -- The declaration (and hence home module) of each gate has
235 -- already been loaded
236
237 slurpSourceRefs source_binders source_fvs
238   = go []                               -- Accumulating decls
239        emptyFVs                         -- Unsatisfied needs
240        source_fvs                       -- Accumulating gates
241        (nameSetToList source_fvs)       -- Gates whose defn hasn't been loaded yet
242   where
243     go decls fvs gates []
244         = returnRn (decls, fvs, gates)
245
246     go decls fvs gates (wanted_name:refs) 
247         | isWiredInName wanted_name
248         = load_home wanted_name         `thenRn_`
249           go decls fvs (gates `plusFV` getWiredInGates wanted_name) refs
250
251         | otherwise
252         = importDecl wanted_name                `thenRn` \ maybe_decl ->
253           case maybe_decl of
254                 -- No declaration... (already slurped, or local)
255             Nothing   -> go decls fvs gates refs
256             Just decl -> rnIfaceDecl decl               `thenRn` \ (new_decl, fvs1) ->
257                          let
258                             new_gates = getGates source_fvs new_decl
259                          in
260                          go (new_decl : decls)
261                             (fvs1 `plusFV` fvs)
262                             (gates `plusFV` new_gates)
263                             (nameSetToList new_gates ++ refs)
264
265         -- When we find a wired-in name we must load its
266         -- home module so that we find any instance decls therein
267     load_home name 
268         | name `elemNameSet` source_binders = returnRn ()
269                 -- When compiling the prelude, a wired-in thing may
270                 -- be defined in this module, in which case we don't
271                 -- want to load its home module!
272                 -- Using 'isLocallyDefined' doesn't work because some of
273                 -- the free variables returned are simply 'listTyCon_Name',
274                 -- with a system provenance.  We could look them up every time
275                 -- but that seems a waste.
276         | otherwise                           = loadHomeInterface doc name      `thenRn_`
277                                                 returnRn ()
278         where
279           doc = ptext SLIT("need home module for wired in thing") <+> ppr name
280
281 -------------------------------------------------------
282 -- slurpInstDecls imports appropriate instance decls.
283 -- It has to incorporate a loop, because consider
284 --      instance Foo a => Baz (Maybe a) where ...
285 -- It may be that Baz and Maybe are used in the source module,
286 -- but not Foo; so we need to chase Foo too.
287
288 slurpInstDecls decls needed gates
289   | isEmptyFVs gates
290   = returnRn (decls, needed)
291
292   | otherwise
293   = getImportedInstDecls gates                          `thenRn` \ inst_decls ->
294     rnInstDecls decls needed emptyFVs inst_decls        `thenRn` \ (decls1, needed1, gates1) ->
295     slurpInstDecls decls1 needed1 gates1
296   where
297     rnInstDecls decls fvs gates []
298         = returnRn (decls, fvs, gates)
299     rnInstDecls decls fvs gates (d:ds) 
300         = rnIfaceDecl d         `thenRn` \ (new_decl, fvs1) ->
301           rnInstDecls (new_decl:decls) 
302                       (fvs1 `plusFV` fvs)
303                       (gates `plusFV` getInstDeclGates new_decl)
304                       ds
305     
306
307 -------------------------------------------------------
308 -- closeDecls keeps going until the free-var set is empty
309 closeDecls decls needed
310   | not (isEmptyFVs needed)
311   = slurpDecls decls needed     `thenRn` \ (decls1, needed1) ->
312     closeDecls decls1 needed1
313
314   | otherwise
315   = getImportedRules                    `thenRn` \ rule_decls ->
316     case rule_decls of
317         []    -> returnRn decls -- No new rules, so we are done
318         other -> rnIfaceDecls decls emptyFVs rule_decls         `thenRn` \ (decls1, needed1) ->
319                  closeDecls decls1 needed1
320                  
321
322 -------------------------------------------------------
323 rnIfaceDecls :: [RenamedHsDecl] -> FreeVars
324              -> [(Module, RdrNameHsDecl)]
325              -> RnM d ([RenamedHsDecl], FreeVars)
326 rnIfaceDecls decls fvs []     = returnRn (decls, fvs)
327 rnIfaceDecls decls fvs (d:ds) = rnIfaceDecl d           `thenRn` \ (new_decl, fvs1) ->
328                                 rnIfaceDecls (new_decl:decls) (fvs1 `plusFV` fvs) ds
329
330 rnIfaceDecl (mod, decl) = initIfaceRnMS mod (rnDecl decl)       
331                         
332
333 -------------------------------------------------------
334 -- Augment decls with any decls needed by needed.
335 -- Return also free vars of the new decls (only)
336 slurpDecls decls needed
337   = go decls emptyFVs (nameSetToList needed) 
338   where
339     go decls fvs []         = returnRn (decls, fvs)
340     go decls fvs (ref:refs) = slurpDecl decls fvs ref   `thenRn` \ (decls1, fvs1) ->
341                               go decls1 fvs1 refs
342
343 -------------------------------------------------------
344 slurpDecl decls fvs wanted_name
345   = importDecl wanted_name              `thenRn` \ maybe_decl ->
346     case maybe_decl of
347         -- No declaration... (wired in thing)
348         Nothing -> returnRn (decls, fvs)
349
350         -- Found a declaration... rename it
351         Just decl -> rnIfaceDecl decl           `thenRn` \ (new_decl, fvs1) ->
352                      returnRn (new_decl:decls, fvs1 `plusFV` fvs)
353 \end{code}
354
355
356 %*********************************************************
357 %*                                                       *
358 \subsection{Extracting the 'gates'}
359 %*                                                       *
360 %*********************************************************
361
362 When we import a declaration like
363
364         data T = T1 Wibble | T2 Wobble
365
366 we don't want to treat Wibble and Wobble as gates *unless* T1, T2
367 respectively are mentioned by the user program.  If only T is mentioned
368 we want only T to be a gate; that way we don't suck in useless instance
369 decls for (say) Eq Wibble, when they can't possibly be useful.
370
371 @getGates@ takes a newly imported (and renamed) decl, and the free
372 vars of the source program, and extracts from the decl the gate names.
373
374 \begin{code}
375 getGates source_fvs (SigD (IfaceSig _ ty _ _))
376   = extractHsTyNames ty
377
378 getGates source_fvs (TyClD (ClassDecl ctxt cls tvs sigs _ _ _ _ _ _))
379   = delListFromNameSet (foldr (plusFV . get) (extractHsCtxtTyNames ctxt) sigs)
380                        (map getTyVarName tvs)
381     `addOneToNameSet` cls
382   where
383     get (ClassOpSig n _ ty _) 
384         | n `elemNameSet` source_fvs = extractHsTyNames ty
385         | otherwise                  = emptyFVs
386
387 getGates source_fvs (TyClD (TySynonym tycon tvs ty _))
388   = delListFromNameSet (extractHsTyNames ty)
389                        (map getTyVarName tvs)
390         -- A type synonym type constructor isn't a "gate" for instance decls
391
392 getGates source_fvs (TyClD (TyData _ ctxt tycon tvs cons _ _ _))
393   = delListFromNameSet (foldr (plusFV . get) (extractHsCtxtTyNames ctxt) cons)
394                        (map getTyVarName tvs)
395     `addOneToNameSet` tycon
396   where
397     get (ConDecl n tvs ctxt details _)
398         | n `elemNameSet` source_fvs
399                 -- If the constructor is method, get fvs from all its fields
400         = delListFromNameSet (get_details details `plusFV` 
401                               extractHsCtxtTyNames ctxt)
402                              (map getTyVarName tvs)
403     get (ConDecl n tvs ctxt (RecCon fields) _)
404                 -- Even if the constructor isn't mentioned, the fields
405                 -- might be, as selectors.  They can't mention existentially
406                 -- bound tyvars (typechecker checks for that) so no need for 
407                 -- the deleteListFromNameSet part
408         = foldr (plusFV . get_field) emptyFVs fields
409         
410     get other_con = emptyFVs
411
412     get_details (VanillaCon tys) = plusFVs (map get_bang tys)
413     get_details (InfixCon t1 t2) = get_bang t1 `plusFV` get_bang t2
414     get_details (RecCon fields)  = plusFVs [get_bang t | (_, t) <- fields]
415     get_details (NewCon t _)     = extractHsTyNames t
416
417     get_field (fs,t) | any (`elemNameSet` source_fvs) fs = get_bang t
418                      | otherwise                         = emptyFVs
419
420     get_bang (Banged   t) = extractHsTyNames t
421     get_bang (Unbanged t) = extractHsTyNames t
422     get_bang (Unpacked t) = extractHsTyNames t
423
424 getGates source_fvs other_decl = emptyFVs
425 \end{code}
426
427 getWiredInGates is just like getGates, but it sees a wired-in Name
428 rather than a declaration.
429
430 \begin{code}
431 getWiredInGates :: Name -> FreeVars
432 getWiredInGates name    -- No classes are wired in
433   | is_id                = getWiredInGates_s (namesOfType (idType the_id))
434   | isSynTyCon the_tycon = getWiredInGates_s (delListFromNameSet (namesOfType ty) (map getName tyvars))
435   | otherwise            = unitFV name
436   where
437     maybe_wired_in_id    = maybeWiredInIdName name
438     is_id                = maybeToBool maybe_wired_in_id
439     maybe_wired_in_tycon = maybeWiredInTyConName name
440     Just the_id          = maybe_wired_in_id
441     Just the_tycon       = maybe_wired_in_tycon
442     (tyvars,ty)          = getSynTyConDefn the_tycon
443
444 getWiredInGates_s names = foldr (plusFV . getWiredInGates) emptyFVs (nameSetToList names)
445 \end{code}
446
447 \begin{code}
448 getInstDeclGates (InstD (InstDecl inst_ty _ _ _ _)) = extractHsTyNames inst_ty
449 getInstDeclGates other                              = emptyFVs
450 \end{code}
451
452
453 %*********************************************************
454 %*                                                       *
455 \subsection{Unused names}
456 %*                                                       *
457 %*********************************************************
458
459 \begin{code}
460 reportUnusedNames gbl_env avail_env (ExportEnv export_avails _) mentioned_names
461   | not (opt_WarnUnusedBinds || opt_WarnUnusedImports)
462   = returnRn ()
463
464   | otherwise
465   = let
466         used_names = mentioned_names `unionNameSets` availsToNameSet export_avails
467
468         -- Now, a use of C implies a use of T,
469         -- if C was brought into scope by T(..) or T(C)
470         really_used_names = used_names `unionNameSets`
471                             mkNameSet [ availName avail 
472                                       | sub_name <- nameSetToList used_names,
473                                         let avail = case lookupNameEnv avail_env sub_name of
474                                                         Just avail -> avail
475                                                         Nothing -> pprTrace "r.u.n" (ppr sub_name) $
476                                                                    Avail sub_name
477                                       ]
478
479         defined_names = mkNameSet (concat (rdrEnvElts gbl_env))
480         defined_but_not_used = nameSetToList (defined_names `minusNameSet` really_used_names)
481
482         -- Filter out the ones only defined implicitly
483         bad_guys = filter reportableUnusedName defined_but_not_used
484     in
485     warnUnusedTopNames bad_guys `thenRn_`
486     returnRn ()
487
488 reportableUnusedName :: Name -> Bool
489 reportableUnusedName name
490   = explicitlyImported (getNameProvenance name) &&
491     not (startsWithUnderscore (occNameUserString (nameOccName name)))
492   where
493     explicitlyImported (LocalDef _ _)                        = True     -- Report unused defns of local vars
494     explicitlyImported (NonLocalDef (UserImport _ _ expl) _) = expl     -- Report unused explicit imports
495     explicitlyImported other                                 = False    -- Don't report others
496    
497         -- Haskell 98 encourages compilers to suppress warnings about
498         -- unused names in a pattern if they start with "_".
499     startsWithUnderscore ('_' : _) = True       -- Suppress warnings for names starting
500     startsWithUnderscore other     = False      -- with an underscore
501
502 rnStats :: [RenamedHsDecl] -> RnMG ()
503 rnStats imp_decls
504         | opt_D_dump_rn_trace || 
505           opt_D_dump_rn_stats ||
506           opt_D_dump_rn 
507         = getRnStats imp_decls          `thenRn` \ msg ->
508           ioToRnM (printErrs msg)       `thenRn_`
509           returnRn ()
510
511         | otherwise = returnRn ()
512 \end{code}
513
514
515
516 %*********************************************************
517 %*                                                      *
518 \subsection{Statistics}
519 %*                                                      *
520 %*********************************************************
521
522 \begin{code}
523 getRnStats :: [RenamedHsDecl] -> RnMG SDoc
524 getRnStats imported_decls
525   = getIfacesRn                 `thenRn` \ ifaces ->
526     let
527         n_mods = length [() | (_, _, Just _) <- eltsFM (iImpModInfo ifaces)]
528
529         decls_read     = [decl | (_, avail, True, (_,decl)) <- nameEnvElts (iDecls ifaces),
530                                         -- Data, newtype, and class decls are in the decls_fm
531                                         -- under multiple names; the tycon/class, and each
532                                         -- constructor/class op too.
533                                         -- The 'True' selects just the 'main' decl
534                                  not (isLocallyDefined (availName avail))
535                              ]
536
537         (cd_rd, dd_rd, nd_rd, sd_rd, vd_rd,     _) = count_decls decls_read
538         (cd_sp, dd_sp, nd_sp, sd_sp, vd_sp, id_sp) = count_decls imported_decls
539
540         unslurped_insts       = iInsts ifaces
541         inst_decls_unslurped  = length (bagToList unslurped_insts)
542         inst_decls_read       = id_sp + inst_decls_unslurped
543
544         stats = vcat 
545                 [int n_mods <+> text "interfaces read",
546                  hsep [ int cd_sp, text "class decls imported, out of", 
547                         int cd_rd, text "read"],
548                  hsep [ int dd_sp, text "data decls imported, out of",  
549                         int dd_rd, text "read"],
550                  hsep [ int nd_sp, text "newtype decls imported, out of",  
551                         int nd_rd, text "read"],
552                  hsep [int sd_sp, text "type synonym decls imported, out of",  
553                         int sd_rd, text "read"],
554                  hsep [int vd_sp, text "value signatures imported, out of",  
555                         int vd_rd, text "read"],
556                  hsep [int id_sp, text "instance decls imported, out of",  
557                         int inst_decls_read, text "read"],
558                  text "cls dcls slurp" <+> fsep (map (ppr . tyClDeclName) 
559                                            [d | TyClD d <- imported_decls, isClassDecl d]),
560                  text "cls dcls read"  <+> fsep (map (ppr . tyClDeclName) 
561                                            [d | TyClD d <- decls_read, isClassDecl d])]
562     in
563     returnRn (hcat [text "Renamer stats: ", stats])
564
565 count_decls decls
566   = (class_decls, 
567      data_decls, 
568      newtype_decls,
569      syn_decls, 
570      val_decls, 
571      inst_decls)
572   where
573     tycl_decls = [d | TyClD d <- decls]
574     (class_decls, data_decls, newtype_decls, syn_decls) = countTyClDecls tycl_decls
575
576     val_decls     = length [() | SigD _   <- decls]
577     inst_decls    = length [() | InstD _  <- decls]
578 \end{code}    
579