[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / compiler / main / Main.lhs
index 918a24c..8a7feb9 100644 (file)
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
+% (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
 %
 \section[GHC_Main]{Main driver for Glasgow Haskell compiler}
 
 \begin{code}
-#include "HsVersions.h"
-
 module Main ( main ) where
 
-import Ubiq{-uitous-}
-
-import PreludeGlaST    ( thenPrimIO, _FILE{-instances-} ) -- ToDo: STOP using this...
+#include "HsVersions.h"
 
-import MainMonad
+import IO      ( IOMode(..), hPutStr, hClose, openFile, stderr )
 import HsSyn
+import BasicTypes      ( NewOrData(..) )
 
 import ReadPrefix      ( rdModule )
 import Rename          ( renameModule )
-import Typecheck       ( typecheckModule, InstInfo )
-import Desugar         ( deSugar, DsMatchContext, pprDsWarnings )
+
+import MkIface         -- several functions
+import TcModule                ( typecheckModule )
+import Desugar         ( deSugar )
 import SimplCore       ( core2core )
 import CoreToStg       ( topCoreBindsToStg )
+import StgSyn          ( collectFinalStgBinders, pprStgBindingsWithSRTs )
 import SimplStg                ( stg2stg )
 import CodeGen         ( codeGen )
 #if ! OMIT_NATIVE_CODEGEN
 import AsmCodeGen      ( dumpRealAsm, writeRealAsm )
 #endif
 
-import AbsCSyn         ( absCNop, AbstractC )
+import AbsCSyn         ( absCNop )
 import AbsCUtils       ( flattenAbsC )
-import Bag             ( emptyBag, isEmptyBag )
 import CmdLineOpts
-import ErrUtils                ( pprBagOfErrors )
+import ErrUtils                ( ghcExit, doIfSet, dumpIfSet )
 import Maybes          ( maybeToBool, MaybeErr(..) )
-import PrelInfo                ( builtinNameInfo )
-import RdrHsSyn                ( getRawExportees )
-import Specialise      ( SpecialiseData(..) )
-import StgSyn          ( pprPlainStgBinding, GenStgBinding )
+import TyCon           ( isDataTyCon )
+import Class           ( classTyCon )
+import UniqSupply      ( mkSplitUniqSupply )
 
 import PprAbsC         ( dumpRealC, writeRealC )
-import PprCore         ( pprCoreBinding )
-import PprStyle                ( PprStyle(..) )
-import Pretty
-
-import Id              ( GenId )               -- instances
-import Name            ( Name, RdrName )       -- instances
-import PprType         ( GenType, GenTyVar )   -- instances
-import RnHsSyn         ( RnName )              -- instances
-import TyVar           ( GenTyVar )            -- instances
-import Unique          ( Unique )              -- instances
-
-{-
---import MkIface       ( mkInterface )
--}
+import FiniteMap       ( emptyFM )
+import Outputable
+import Char            ( isSpace )
+#if REPORT_TO_MOTHERLODE && __GLASGOW_HASKELL__ >= 303
+import SocketPrim
+import BSD
+import IOExts          ( unsafePerformIO )
+import NativeInfo       ( os, arch )
+#endif
 
 \end{code}
 
 \begin{code}
-main
-  = readMn stdin       `thenMn` \ input_pgm     ->
-    let
-       cmd_line_info = classifyOpts
-    in
-    doIt cmd_line_info input_pgm
+main =
+ --  _scc_ "main" 
+ doIt classifyOpts
 \end{code}
 
 \begin{code}
-doIt :: ([CoreToDo], [StgToDo]) -> String -> MainIO ()
+doIt :: ([CoreToDo], [StgToDo]) -> IO ()
 
-doIt (core_cmds, stg_cmds) input_pgm
-  = doDump opt_Verbose "Glasgow Haskell Compiler, version 1.3-xx" ""
-                                               `thenMn_`
+doIt (core_cmds, stg_cmds)
+  = doIfSet opt_Verbose 
+       (hPutStr stderr "Glasgow Haskell Compiler, version "    >>
+        hPutStr stderr compiler_version                        >>
+        hPutStr stderr ", for Haskell 1.4\n")                  >>
 
     -- ******* READER
-    show_pass "Reader"                         `thenMn_`
-    rdModule                                   `thenMn`
+    show_pass "Reader" >>
+    _scc_     "Reader"
+    rdModule           >>= \ (mod_name, rdr_module) ->
 
-       \ (mod_name, rdr_module) ->
-
-    let
-       -- reader things used much later
-       ds_mod_name = mod_name
-       if_mod_name = mod_name
-       co_mod_name = mod_name
-       st_mod_name = mod_name
-       cc_mod_name = mod_name
-    in
-    doDump opt_D_dump_rdr "Reader:"
-       (pp_show (ppr pprStyle rdr_module))     `thenMn_`
+    dumpIfSet opt_D_dump_rdr "Reader" (ppr rdr_module)         >>
 
-    doDump opt_D_source_stats "\nSource Statistics:"
-       (pp_show (ppSourceStats rdr_module))    `thenMn_`
+    dumpIfSet opt_D_source_stats "Source Statistics"
+       (ppSourceStats False rdr_module)                >>
 
     -- UniqueSupplies for later use (these are the only lower case uniques)
-    getSplitUniqSupplyMn 'r'   `thenMn` \ rn_uniqs ->  -- renamer
-    getSplitUniqSupplyMn 't'   `thenMn` \ tc_uniqs ->  -- typechecker
-    getSplitUniqSupplyMn 'd'   `thenMn` \ ds_uniqs ->  -- desugarer
-    getSplitUniqSupplyMn 's'   `thenMn` \ sm_uniqs ->  -- core-to-core simplifier
-    getSplitUniqSupplyMn 'c'   `thenMn` \ c2s_uniqs -> -- core-to-stg
-    getSplitUniqSupplyMn 'g'   `thenMn` \ st_uniqs ->  -- stg-to-stg passes
-    getSplitUniqSupplyMn 'f'   `thenMn` \ fl_uniqs ->  -- absC flattener
-    getSplitUniqSupplyMn 'n'   `thenMn` \ ncg_uniqs -> -- native-code generator
+--    _scc_     "spl-rn"
+    mkSplitUniqSupply 'r'      >>= \ rn_uniqs  -> -- renamer
+--    _scc_     "spl-tc"
+    mkSplitUniqSupply 'a'      >>= \ tc_uniqs  -> -- typechecker
+--    _scc_     "spl-ds"
+    mkSplitUniqSupply 'd'      >>= \ ds_uniqs  -> -- desugarer
+--    _scc_     "spl-sm"
+    mkSplitUniqSupply 's'      >>= \ sm_uniqs  -> -- core-to-core simplifier
+--    _scc_     "spl-c2s"
+    mkSplitUniqSupply 'c'      >>= \ c2s_uniqs -> -- core-to-stg
+--    _scc_     "spl-st"
+    mkSplitUniqSupply 'g'      >>= \ st_uniqs  -> -- stg-to-stg passes
+--    _scc_     "spl-absc"
+    mkSplitUniqSupply 'f'      >>= \ fl_uniqs  -> -- absC flattener
+--    _scc_     "spl-ncg"
+    mkSplitUniqSupply 'n'      >>= \ ncg_uniqs -> -- native-code generator
 
     -- ******* RENAMER
-    show_pass "Renamer"                        `thenMn_`
+    show_pass "Renamer"                        >>
+    _scc_     "Renamer"
 
-    case builtinNameInfo
-    of { (wiredin_fm, key_fm, idinfo_fm) ->
+    renameModule rn_uniqs rdr_module           >>=
+       \ maybe_rn_stuff ->
+    case maybe_rn_stuff of {
+       Nothing ->      -- Hurrah!  Renamer reckons that there's no need to
+                       -- go any further
+                       reportCompile (_UNPK_ mod_name) "Compilation NOT required!" >>
+                       return ();
+       
+       Just (rn_mod, iface_file_stuff, rn_name_supply, imported_modules) ->
+                       -- Oh well, we've got to recompile for real
 
-    renameModule wiredin_fm key_fm rn_uniqs rdr_module `thenMn`
-       \ (rn_mod, import_names,
-          version_info, instance_modules,
-          rn_errs_bag, rn_warns_bag) ->
 
-    if (not (isEmptyBag rn_errs_bag)) then
-       writeMn stderr (ppShow pprCols (pprBagOfErrors pprErrorsStyle rn_errs_bag))
-       `thenMn_` writeMn stderr "\n" `thenMn_`
-       writeMn stderr (ppShow pprCols (pprBagOfErrors pprErrorsStyle rn_warns_bag))
-       `thenMn_` writeMn stderr "\n" `thenMn_`
-       exitMn 1
+    -- Safely past renaming: we can start the interface file:
+    -- (the iface file is produced incrementally, as we have
+    -- the information that we need...; we use "iface<blah>")
+    -- "endIface" finishes the job.
+    startIface mod_name                                        >>= \ if_handle ->
+    ifaceMain if_handle iface_file_stuff               >>
 
-    else -- No renaming errors ...
 
-    (if (isEmptyBag rn_warns_bag) then
-       returnMn ()
-     else
-       writeMn stderr (ppShow pprCols (pprBagOfErrors pprErrorsStyle rn_warns_bag))
-       `thenMn_` writeMn stderr "\n"
-    )                                          `thenMn_`
+    -- ******* TYPECHECKER
+    show_pass "TypeCheck"                              >>
+    _scc_     "TypeCheck"
+    typecheckModule tc_uniqs rn_name_supply rn_mod     >>= \ maybe_tc_stuff ->
+    case maybe_tc_stuff of {
+       Nothing -> ghcExit 1;   -- Type checker failed
 
-    doDump opt_D_dump_rn "Renamer:"
-       (pp_show (ppr pprStyle rn_mod))         `thenMn_`
+       Just (all_binds,
+             local_tycons, local_classes, inst_info, 
+             fo_decls,
+             ddump_deriv,
+             global_env,
+             global_ids) ->
 
---    exitMn 0
-{- LATER ... -}
-
-    -- ******* TYPECHECKER
-    show_pass "TypeCheck"                      `thenMn_`
-    let
-       rn_info = trace "Main.rn_info" (\ x -> Nothing, \ x -> Nothing)
-    in
-    case (case (typecheckModule tc_uniqs {-idinfo_fm-} rn_info rn_mod) of
-           Succeeded (stuff, warns)
-               -> (emptyBag, warns, stuff)
-           Failed (errs, warns)
-               -> (errs, warns, error "tc_results"))
-
-    of { (tc_errs_bag, tc_warns_bag, tc_results) ->
-
-    if (not (isEmptyBag tc_errs_bag)) then
-       writeMn stderr (ppShow pprCols (pprBagOfErrors pprErrorsStyle tc_errs_bag))
-       `thenMn_` writeMn stderr "\n" `thenMn_`
-       writeMn stderr (ppShow pprCols (pprBagOfErrors pprErrorsStyle tc_warns_bag))
-       `thenMn_` writeMn stderr "\n" `thenMn_`
-       exitMn 1
-
-    else ( -- No typechecking errors ...
-
-    (if (isEmptyBag tc_warns_bag) then
-       returnMn ()
-     else
-       writeMn stderr (ppShow pprCols (pprBagOfErrors pprErrorsStyle tc_warns_bag))
-       `thenMn_` writeMn stderr "\n"
-    )                                          `thenMn_`
-
-    case tc_results
-    of {  (typechecked_quint@(recsel_binds, class_binds, inst_binds, val_binds, const_binds),
-          interface_stuff@(_,_,_,_,_),  -- @-pat just for strictness...
-          (local_tycons,local_classes), pragma_tycon_specs, ddump_deriv) ->
-
-    doDump opt_D_dump_tc "Typechecked:"
-       (pp_show (ppAboves [
-           ppr pprStyle recsel_binds,
-           ppr pprStyle class_binds,
-           ppr pprStyle inst_binds,
-           ppAboves (map (\ (i,e) -> ppr pprStyle (VarMonoBind i e)) const_binds),
-           ppr pprStyle val_binds]))           `thenMn_`
-
-    doDump opt_D_dump_deriv "Derived instances:"
-       (pp_show (ddump_deriv pprStyle))        `thenMn_`
 
     -- ******* DESUGARER
-    show_pass "DeSugar"                        `thenMn_`
-    let
-       (desugared,ds_warnings)
-         = deSugar ds_uniqs ds_mod_name typechecked_quint
-    in
-    (if isEmptyBag ds_warnings then
-       returnMn ()
-     else
-       writeMn stderr (ppShow pprCols (pprDsWarnings pprErrorsStyle ds_warnings))
-       `thenMn_` writeMn stderr "\n"
-    )                                          `thenMn_`
+    show_pass "DeSugar"                                            >>
+    _scc_     "DeSugar"
+    deSugar ds_uniqs global_env mod_name all_binds fo_decls >>= \ (desugared, h_code, c_code) ->
 
-    doDump opt_D_dump_ds "Desugared:" (pp_show (ppAboves
-       (map (pprCoreBinding pprStyle) desugared)))
-                                               `thenMn_`
 
-    -- ******* CORE-TO-CORE SIMPLIFICATION (NB: I/O op)
-    core2core core_cmds co_mod_name pprStyle
-             sm_uniqs local_tycons pragma_tycon_specs desugared
-                                               `thenMn`
-
-        \ (simplified, inlinings_env,
-           SpecData _ _ _ gen_tycons all_tycon_specs _ _ _) ->
+    -- ******* CORE-TO-CORE SIMPLIFICATION
+    show_pass "Core2Core"                      >>
+    _scc_     "Core2Core"
+    let
+       local_data_tycons = filter isDataTyCon local_tycons
+    in
+    core2core core_cmds mod_name
+             sm_uniqs desugared
+                                               >>=
+        \ simplified ->
 
-    doDump opt_D_dump_simpl "Simplified:" (pp_show (ppAboves
-       (map (pprCoreBinding pprStyle) simplified)))
-                                               `thenMn_`
 
     -- ******* STG-TO-STG SIMPLIFICATION
-    show_pass "Core2Stg"                       `thenMn_`
+    show_pass "Core2Stg"                       >>
+    _scc_     "Core2Stg"
     let
        stg_binds   = topCoreBindsToStg c2s_uniqs simplified
     in
 
-    show_pass "Stg2Stg"                        `thenMn_`
-    stg2stg stg_cmds st_mod_name pprStyle st_uniqs stg_binds
-                                               `thenMn`
-
+    show_pass "Stg2Stg"                        >>
+    _scc_     "Stg2Stg"
+    stg2stg stg_cmds mod_name st_uniqs stg_binds
+                                               >>=
        \ (stg_binds2, cost_centre_info) ->
 
-    doDump opt_D_dump_stg "STG syntax:"
-       (pp_show (ppAboves (map (pprPlainStgBinding pprStyle) stg_binds2)))
-                                               `thenMn_`
-
-{- LATER ...
-    -- ******* INTERFACE GENERATION (needs STG output)
-{-  let
-       mod_name = "_TestName_"
-       export_list_fns = (\ x -> False, \ x -> False)
-       inlinings_env = nullIdEnv
-       fixities = []
-       if_global_ids = []
-       if_ce = nullCE
-       if_tce = nullTCE
-       if_inst_info = emptyBag
-    in
--}
+    dumpIfSet opt_D_dump_stg "STG syntax:" 
+       (pprStgBindingsWithSRTs stg_binds2)     >>
 
-    show_pass "Interface"                      `thenMn_`
+       -- Dump instance decls and type signatures into the interface file
     let
-       mod_interface
-         = mkInterface if_mod_name export_list_fns
-                       inlinings_env all_tycon_specs
-                       interface_stuff
-                       stg_binds2
+       final_ids = collectFinalStgBinders (map fst stg_binds2)
     in
-    doOutput opt_ProduceHi ( \ file ->
-                        ppAppendFile file 1000{-pprCols-} mod_interface )
-                                                       `thenMn_`
--}
+    _scc_     "Interface"
+    ifaceDecls if_handle local_tycons local_classes inst_info final_ids simplified     >>
+    endIface if_handle                                         >>
+    -- We are definitely done w/ interface-file stuff at this point:
+    -- (See comments near call to "startIface".)
 
     -- ******* "ABSTRACT", THEN "FLAT", THEN *REAL* C!
-    show_pass "CodeGen"                        `thenMn_`
+    show_pass "CodeGen"                        >>
+    _scc_     "CodeGen"
     let
-       abstractC      = codeGen cc_mod_name     -- module name for CC labelling
+       all_local_data_tycons = filter isDataTyCon (map classTyCon local_classes)
+                               ++ local_data_tycons
+                                       -- Generate info tables  for the data constrs arising
+                                       -- from class decls as well
+
+       all_tycon_specs       = emptyFM -- Not specialising tycons any more
+
+       abstractC      = codeGen mod_name               -- module name for CC labelling
                                 cost_centre_info
-                                import_names -- import names for CC registering
-                                gen_tycons      -- type constructors generated locally
-                                all_tycon_specs -- tycon specialisations
+                                imported_modules       -- import names for CC registering
+                                all_local_data_tycons  -- type constructors generated locally
+                                all_tycon_specs        -- tycon specialisations
                                 stg_binds2
 
        flat_abstractC = flattenAbsC fl_uniqs abstractC
     in
-    doDump opt_D_dump_absC  "Abstract C:"
-       (dumpRealC abstractC)                   `thenMn_`
-
-    doDump opt_D_dump_flatC "Flat Abstract C:"
-       (dumpRealC flat_abstractC)              `thenMn_`
-
+    show_pass "CodeOutput"                     >>
+    _scc_     "CodeOutput"
     -- You can have C (c_output) or assembly-language (ncg_output),
     -- but not both.  [Allowing for both gives a space leak on
     -- flat_abstractC.  WDP 94/10]
@@ -282,6 +209,14 @@ doIt (core_cmds, stg_cmds) input_pgm
             (False, False) -> (absCNop, absCNop)
             (True,  True)  -> error "ERROR: Can't do both .hc and .s at the same time"
 
+        -- C stubs for "foreign export"ed functions.
+       stub_c_output_d = pprCode CStyle c_code
+        stub_c_output_w = showSDoc stub_c_output_d
+
+        -- Header file protos for "foreign export"ed functions.
+       stub_h_output_d = pprCode CStyle h_code
+        stub_h_output_w = showSDoc stub_h_output_d
+
        c_output_d = dumpRealC flat_absC_c
        c_output_w = (\ f -> writeRealC f flat_absC_c)
 
@@ -294,70 +229,59 @@ doIt (core_cmds, stg_cmds) input_pgm
 #endif
     in
 
-    doDump opt_D_dump_asm "" ncg_output_d      `thenMn_`
-    doOutput opt_ProduceS ncg_output_w                 `thenMn_`
+    dumpIfSet opt_D_dump_asm "Asm code" ncg_output_d   >>
+    doOutput opt_ProduceS ncg_output_w                         >>
 
-    doDump opt_D_dump_realC "" c_output_d      `thenMn_`
-    doOutput opt_ProduceC c_output_w           `thenMn_`
+    dumpIfSet opt_D_dump_foreign "Foreign export header file" stub_h_output_d >>
+    outputHStub opt_ProduceExportHStubs stub_h_output_w        >>
 
-    exitMn 0
-    } ) }
+    dumpIfSet opt_D_dump_foreign "Foreign export stubs" stub_c_output_d >>
+    outputCStub mod_name opt_ProduceExportCStubs stub_c_output_w       >>
 
-{- LATER -}
+    dumpIfSet opt_D_dump_realC "Real C" c_output_d     >>
+    doOutput opt_ProduceC c_output_w                   >>
 
-    }
-  where
-    -------------------------------------------------------------
-    -- ****** printing styles and column width:
-
-    pprCols = (80 :: Int) -- could make configurable
-
-    (pprStyle, pprErrorsStyle)
-      = if      opt_PprStyle_All   then
-               (PprShowAll, PprShowAll)
-       else if opt_PprStyle_Debug then
-               (PprDebug, PprDebug)
-       else if opt_PprStyle_User  then
-               (PprForUser, PprForUser)
-       else -- defaults...
-               (PprDebug, PprForUser)
-
-    pp_show p = ppShow {-WAS:pprCols-}10000{-random-} p
+    reportCompile (_UNPK_ mod_name) (showSDoc (ppSourceStats True rdr_module)) >>
 
+    ghcExit 0
+    } }
+  where
     -------------------------------------------------------------
     -- ****** help functions:
 
     show_pass
       = if opt_D_show_passes
-       then \ what -> writeMn stderr ("*** "++what++":\n")
-       else \ what -> returnMn ()
+       then \ what -> hPutStr stderr ("*** "++what++":\n")
+       else \ what -> return ()
 
     doOutput switch io_action
       = case switch of
-         Nothing -> returnMn ()
+         Nothing    -> return ()
          Just fname ->
-           fopen fname "a+"    `thenPrimIO` \ file ->
-           if (file == ``NULL'') then
-               error ("doOutput: failed to open:"++fname)
-           else
-               io_action file          `thenMn`     \ () ->
-               fclose file             `thenPrimIO` \ status ->
-               if status == 0
-               then returnMn ()
-               else error ("doOutput: closed failed: "{-++show status++" "-}++fname)
-
-    doDump switch hdr string
-      = if switch
-       then writeMn stderr hdr             `thenMn_`
-            writeMn stderr ('\n': string)  `thenMn_`
-            writeMn stderr "\n"
-       else returnMn ()
-
-
-ppSourceStats (HsModule name version exports imports fixities typedecls typesigs
-                     classdecls instdecls instsigs defdecls binds
-                     [{-no sigs-}] src_loc)
- = ppAboves (map pp_val
+           openFile fname WriteMode    >>= \ handle ->
+           io_action handle            >>
+           hClose handle
+
+    -- don't use doOutput for dumping the f. export stubs
+    -- since it is more than likely that the stubs file will
+    -- turn out to be empty, in which case no file should be created.
+    outputCStub mod_name switch "" = return ()
+    outputCStub mod_name switch doc_str
+      = case switch of
+         Nothing    -> return ()
+         Just fname -> writeFile fname ("#include \"Rts.h\"\n#include \"RtsAPI.h\"\n"++rest)
+           where
+            rest = "#include "++show ((_UNPK_ mod_name) ++ "_stub.h") ++ '\n':doc_str
+             
+    outputHStub switch "" = return ()
+    outputHStub switch doc_str
+      = case switch of
+         Nothing    -> return ()
+         Just fname -> writeFile fname ("#include \"Rts.h\"\n"++doc_str)
+
+ppSourceStats short (HsModule name version exports imports fixities decls src_loc)
+ = (if short then hcat else vcat)
+        (map pp_val
               [("ExportAll        ", export_all), -- 1 if no export list
                ("ExportDecls      ", export_ds),
                ("ExportModules    ", export_ms),
@@ -368,7 +292,7 @@ ppSourceStats (HsModule name version exports imports fixities typedecls typesigs
                ("  ImpPartial     ", import_partial),
                ("  ImpHiding      ", import_hiding),
                ("FixityDecls      ", fixity_ds),
-               ("DefaultDecls     ", defalut_ds),
+               ("DefaultDecls     ", default_ds),
                ("TypeDecls        ", type_ds),
                ("DataDecls        ", data_ds),
                ("NewTypeDecls     ", newt_ds),
@@ -384,57 +308,56 @@ ppSourceStats (HsModule name version exports imports fixities typedecls typesigs
                ("FunBinds         ", fn_bind_ds),
                ("InlineMeths      ", method_inlines),
                ("InlineBinds      ", bind_inlines),
-               ("SpecialisedData  ", data_specs),
-               ("SpecialisedInsts ", inst_specs),
+--             ("SpecialisedData  ", data_specs),
+--             ("SpecialisedInsts ", inst_specs),
                ("SpecialisedMeths ", method_specs),
                ("SpecialisedBinds ", bind_specs)
               ])
   where
-    pp_val (str, 0) = ppNil
-    pp_val (str, n) = ppBesides [ppStr str, ppInt n]
-
-    (export_decls, export_mods) = getRawExportees exports
-    type_decls = filter is_type_decl typedecls
-    data_decls = filter is_data_decl typedecls
-    newt_decls = filter is_newt_decl typedecls
-
-    export_ds  = length export_decls
-    export_ms  = length export_mods
-    export_all = if export_ds == 0 && export_ms == 0 then 1 else 0
-
-    fixity_ds  = length fixities
-    defalut_ds = length defdecls
-    type_ds    = length type_decls
-    data_ds    = length data_decls
-    newt_ds    = length newt_decls
-    class_ds   = length classdecls
-    inst_ds    = length instdecls
+    pp_val (str, 0) = empty
+    pp_val (str, n) 
+      | not short   = hcat [text str, int n]
+      | otherwise   = hcat [text (trim str), equals, int n, semi]
+    
+    trim ls     = takeWhile (not.isSpace) (dropWhile isSpace ls)
+
+    fixity_ds   = length fixities
+    type_decls         = [d | TyD d@(TySynonym _ _ _ _)    <- decls]
+    data_decls         = [d | TyD d@(TyData DataType _ _ _ _ _ _ _) <- decls]
+    newt_decls         = [d | TyD d@(TyData NewType  _ _ _ _ _ _ _) <- decls]
+    type_ds    = length type_decls
+    data_ds    = length data_decls
+    newt_ds    = length newt_decls
+    class_decls = [d | ClD d <- decls]
+    class_ds    = length class_decls
+    inst_decls  = [d | InstD d <- decls]
+    inst_ds     = length inst_decls
+    default_ds  = length [() | DefD _ <- decls]
+    val_decls   = [d | ValD d <- decls]
+
+    real_exports = case exports of { Nothing -> []; Just es -> es }
+    n_exports           = length real_exports
+    export_ms           = length [() | IEModuleContents _ <- real_exports]
+    export_ds           = n_exports - export_ms
+    export_all          = case exports of { Nothing -> 1; other -> 0 }
 
     (val_bind_ds, fn_bind_ds, bind_tys, bind_specs, bind_inlines)
-       = count_binds binds
+       = count_binds (foldr ThenBinds EmptyBinds val_decls)
 
     (import_no, import_qual, import_as, import_all, import_partial, import_hiding)
        = foldr add6 (0,0,0,0,0,0) (map import_info imports)
     (data_constrs, data_derivs)
        = foldr add2 (0,0) (map data_info (newt_decls ++ data_decls))
     (class_method_ds, default_method_ds)
-       = foldr add2 (0,0) (map class_info classdecls)
+       = foldr add2 (0,0) (map class_info class_decls)
     (inst_method_ds, method_specs, method_inlines)
-       = foldr add3 (0,0,0) (map inst_info instdecls)
+       = foldr add3 (0,0,0) (map inst_info inst_decls)
 
-    data_specs  = length typesigs
-    inst_specs  = length instsigs
 
     count_binds EmptyBinds        = (0,0,0,0,0)
     count_binds (ThenBinds b1 b2) = count_binds b1 `add5` count_binds b2
-    count_binds (SingleBind b)    = case count_bind b of
-                                     (vs,fs) -> (vs,fs,0,0,0)
-    count_binds (BindWith b sigs) = case (count_bind b, count_sigs sigs) of
-                                     ((vs,fs),(ts,_,ss,is)) -> (vs,fs,ts,ss,is)
-
-    count_bind EmptyBind      = (0,0)
-    count_bind (NonRecBind b) = count_monobinds b
-    count_bind (RecBind b)    = count_monobinds b
+    count_binds (MonoBind b sigs _) = case (count_monobinds b, count_sigs sigs) of
+                                       ((vs,fs),(ts,_,ss,is)) -> (vs,fs,ts,ss,is)
 
     count_monobinds EmptyMonoBinds       = (0,0)
     count_monobinds (AndMonoBinds b1 b2)  = count_monobinds b1 `add2` count_monobinds b2
@@ -444,13 +367,13 @@ ppSourceStats (HsModule name version exports imports fixities typedecls typesigs
 
     count_sigs sigs = foldr add4 (0,0,0,0) (map sig_info sigs)
 
-    sig_info (Sig _ _ _ _)        = (1,0,0,0)
+    sig_info (Sig _ _ _)          = (1,0,0,0)
     sig_info (ClassOpSig _ _ _ _) = (0,1,0,0)
     sig_info (SpecSig _ _ _ _)    = (0,0,1,0)
     sig_info (InlineSig _ _)      = (0,0,0,1)
     sig_info _                    = (0,0,0,0)
 
-    import_info (ImportDecl _ qual as spec _)
+    import_info (ImportDecl _ qual _ as spec _)
        = add6 (1, qual_info qual, as_info as, 0,0,0) (spec_info spec)
     qual_info False  = 0
     qual_info True   = 1
@@ -460,28 +383,19 @@ ppSourceStats (HsModule name version exports imports fixities typedecls typesigs
     spec_info (Just (False, _)) = (0,0,0,0,1,0)
     spec_info (Just (True, _))  = (0,0,0,0,0,1)
 
-    data_info (TyData _ _ _ constrs derivs _ _)
+    data_info (TyData _ _ _ _ constrs derivs _ _)
        = (length constrs, case derivs of {Nothing -> 0; Just ds -> length ds})
-    data_info (TyNew _ _ _ constr derivs _ _)
-       = (length constr, case derivs of {Nothing -> 0; Just ds -> length ds})
 
-    class_info (ClassDecl _ _ _ meth_sigs def_meths _ _)
+    class_info (ClassDecl _ _ _ meth_sigs def_meths _ _ _ _)
        = case count_sigs meth_sigs of
            (_,classops,_,_) ->
               (classops, addpr (count_monobinds def_meths))
 
-    inst_info (InstDecl _ _ inst_meths _ _ inst_sigs _ _)
+    inst_info (InstDecl _ inst_meths inst_sigs _ _)
        = case count_sigs inst_sigs of
            (_,_,ss,is) ->
               (addpr (count_monobinds inst_meths), ss, is)
 
-    is_type_decl (TySynonym _ _ _ _)     = True
-    is_type_decl _                      = False
-    is_data_decl (TyData _ _ _ _ _ _ _)  = True
-    is_data_decl _                      = False
-    is_newt_decl (TyNew  _ _ _ _ _ _ _)  = True
-    is_newt_decl _                      = False
-
     addpr (x,y) = x+y
     add1 x1 y1  = x1+y1
     add2 (x1,x2) (y1,y2) = (x1+y1,x2+y2)
@@ -490,3 +404,54 @@ ppSourceStats (HsModule name version exports imports fixities typedecls typesigs
     add5 (x1,x2,x3,x4,x5) (y1,y2,y3,y4,y5) = (x1+y1,x2+y2,x3+y3,x4+y4,x5+y5)
     add6 (x1,x2,x3,x4,x5,x6) (y1,y2,y3,y4,y5,y6) = (x1+y1,x2+y2,x3+y3,x4+y4,x5+y5,x6+y6)
 \end{code}
+
+\begin{code}
+compiler_version :: String
+compiler_version =
+     case (show opt_HiVersion) of
+       [x]      -> ['0','.',x]
+       ls@[x,y] -> "0." ++ ls
+       ls       -> go ls
+ where
+  -- 10232353 => 10232.53
+  go ls@[x,y] = '.':ls
+  go (x:xs)   = x:go xs
+
+\end{code}
+
+\begin{code}
+reportCompile :: String -> String -> IO ()
+#if REPORT_TO_MOTHERLODE && __GLASGOW_HASKELL__ >= 303
+reportCompile mod_name info
+  | not opt_ReportCompile = return ()
+  | otherwise = (do 
+      sock <- udpSocket 0
+      addr <- motherShip
+      sendTo sock (mod_name++ ';': compiler_version ++ ';': os ++ ';':arch ++ '\n':' ':info ++ "\n") addr
+      return ()) `catch` (\ _ -> return ())
+
+motherShip :: IO SockAddr
+motherShip = do
+  he <- getHostByName "laysan.dcs.gla.ac.uk"
+  case (hostAddresses he) of
+    []    -> fail (userError "No address!")
+    (x:_) -> return (SockAddrInet motherShipPort x)
+
+--magick
+motherShipPort :: PortNumber
+motherShipPort = mkPortNumber 12345
+
+-- creates a socket capable of sending datagrams,
+-- binding it to a port
+--  ( 0 => have the system pick next available port no.)
+udpSocket :: Int -> IO Socket
+udpSocket p = do
+  pr <- getProtocolNumber "udp"
+  s  <- socket AF_INET Datagram pr
+  bindSocket s (SockAddrInet (mkPortNumber p) iNADDR_ANY)
+  return s
+#else
+reportCompile _ _ = return ()
+#endif
+
+\end{code}