Haskell Program Coverage
[ghc-hetmet.git] / compiler / deSugar / Desugar.lhs
1 %
2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 %
5
6 The Desugarer: turning HsSyn into Core.
7
8 \begin{code}
9 module Desugar ( deSugar, deSugarExpr ) where
10
11 #include "HsVersions.h"
12
13 import DynFlags
14 import StaticFlags
15 import HscTypes
16 import HsSyn
17 import TcRnTypes
18 import MkIface
19 import Id
20 import Name
21 import CoreSyn
22 import PprCore
23 import DsMonad
24 import DsExpr
25 import DsBinds
26 import DsForeign
27 import DsExpr           ()      -- Forces DsExpr to be compiled; DsBinds only
28                                 -- depends on DsExpr.hi-boot.
29 import Module
30 import UniqFM
31 import PackageConfig
32 import RdrName
33 import NameSet
34 import VarSet
35 import Rules
36 import CoreLint
37 import CoreFVs
38 import ErrUtils
39 import ListSetOps
40 import Outputable
41 import SrcLoc
42 import Maybes
43 import FastString
44 import Util
45 import Coverage
46
47 import Data.IORef
48 \end{code}
49
50 %************************************************************************
51 %*                                                                      *
52 %*              The main function: deSugar
53 %*                                                                      *
54 %************************************************************************
55
56 \begin{code}
57 deSugar :: HscEnv -> ModLocation -> TcGblEnv -> IO (Maybe ModGuts)
58 -- Can modify PCS by faulting in more declarations
59
60 deSugar hsc_env 
61         mod_loc
62         tcg_env@(TcGblEnv { tcg_mod       = mod,
63                             tcg_src       = hsc_src,
64                             tcg_type_env  = type_env,
65                             tcg_imports   = imports,
66                             tcg_exports   = exports,
67                             tcg_dus       = dus, 
68                             tcg_inst_uses = dfun_uses_var,
69                             tcg_th_used   = th_var,
70                             tcg_keep      = keep_var,
71                             tcg_rdr_env   = rdr_env,
72                             tcg_fix_env   = fix_env,
73                             tcg_deprecs   = deprecs,
74                             tcg_binds     = binds,
75                             tcg_fords     = fords,
76                             tcg_rules     = rules,
77                             tcg_insts     = insts,
78                             tcg_fam_insts = fam_insts })
79   = do  { showPass dflags "Desugar"
80
81         -- Desugar the program
82         ; let export_set = availsToNameSet exports
83         ; let auto_scc = mkAutoScc mod export_set
84
85         ; mb_res <- case ghcMode dflags of
86                      JustTypecheck -> return (Just ([], [], NoStubs, noHpcInfo))
87                      _        -> do (binds_cvr,ds_hpc_info) 
88                                               <- if dopt Opt_Hpc dflags
89                                                  then addCoverageTicksToBinds dflags mod mod_loc binds
90                                                  else return (binds, noHpcInfo)
91                                     initDs hsc_env mod rdr_env type_env $ do
92                                         { core_prs <- dsTopLHsBinds auto_scc binds_cvr
93                                         ; (ds_fords, foreign_prs) <- dsForeigns fords
94                                         ; let all_prs = foreign_prs ++ core_prs
95                                               local_bndrs = mkVarSet (map fst all_prs)
96                                         ; ds_rules <- mappM (dsRule mod local_bndrs) rules
97                                         ; return (all_prs, catMaybes ds_rules, ds_fords, ds_hpc_info)
98                                         }
99         ; case mb_res of {
100            Nothing -> return Nothing ;
101            Just (all_prs, ds_rules, ds_fords,ds_hpc_info) -> do
102
103         {       -- Add export flags to bindings
104           keep_alive <- readIORef keep_var
105         ; let final_prs = addExportFlags ghci_mode export_set
106                                  keep_alive all_prs ds_rules
107               ds_binds  = [Rec final_prs]
108         -- Notice that we put the whole lot in a big Rec, even the foreign binds
109         -- When compiling PrelFloat, which defines data Float = F# Float#
110         -- we want F# to be in scope in the foreign marshalling code!
111         -- You might think it doesn't matter, but the simplifier brings all top-level
112         -- things into the in-scope set before simplifying; so we get no unfolding for F#!
113
114         -- Lint result if necessary
115         ; endPass dflags "Desugar" Opt_D_dump_ds ds_binds
116
117         -- Dump output
118         ; doIfSet (dopt Opt_D_dump_ds dflags) 
119                   (printDump (ppr_ds_rules ds_rules))
120
121         ; dfun_uses <- readIORef dfun_uses_var          -- What dfuns are used
122         ; th_used   <- readIORef th_var                 -- Whether TH is used
123         ; let used_names = allUses dus `unionNameSets` dfun_uses
124               pkgs | th_used   = insertList thPackageId (imp_dep_pkgs imports)
125                    | otherwise = imp_dep_pkgs imports
126
127               dep_mods = eltsUFM (delFromUFM (imp_dep_mods imports) (moduleName mod))
128                 -- M.hi-boot can be in the imp_dep_mods, but we must remove
129                 -- it before recording the modules on which this one depends!
130                 -- (We want to retain M.hi-boot in imp_dep_mods so that 
131                 --  loadHiBootInterface can see if M's direct imports depend 
132                 --  on M.hi-boot, and hence that we should do the hi-boot consistency 
133                 --  check.)
134
135               dir_imp_mods = imp_mods imports
136
137         ; usages <- mkUsageInfo hsc_env dir_imp_mods dep_mods used_names
138
139         ; let 
140                 -- Modules don't compare lexicographically usually, 
141                 -- but we want them to do so here.
142              le_mod :: Module -> Module -> Bool  
143              le_mod m1 m2 = moduleNameFS (moduleName m1) 
144                                 <= moduleNameFS (moduleName m2)
145              le_dep_mod :: (ModuleName, IsBootInterface) -> (ModuleName, IsBootInterface) -> Bool        
146              le_dep_mod (m1,_) (m2,_) = moduleNameFS m1 <= moduleNameFS m2
147
148              deps = Deps { dep_mods   = sortLe le_dep_mod dep_mods,
149                            dep_pkgs   = sortLe (<=)   pkgs,     
150                            dep_orphs  = sortLe le_mod (imp_orphs  imports),
151                            dep_finsts = sortLe le_mod (imp_finsts imports) }
152                 -- sort to get into canonical order
153
154              mod_guts = ModGuts {       
155                 mg_module    = mod,
156                 mg_boot      = isHsBoot hsc_src,
157                 mg_exports   = exports,
158                 mg_deps      = deps,
159                 mg_usages    = usages,
160                 mg_dir_imps  = [m | (m,_,_) <- moduleEnvElts dir_imp_mods],
161                 mg_rdr_env   = rdr_env,
162                 mg_fix_env   = fix_env,
163                 mg_deprecs   = deprecs,
164                 mg_types     = type_env,
165                 mg_insts     = insts,
166                 mg_fam_insts = fam_insts,
167                 mg_rules     = ds_rules,
168                 mg_binds     = ds_binds,
169                 mg_foreign   = ds_fords,
170                 mg_hpc_info  = ds_hpc_info }
171         ; return (Just mod_guts)
172         }}}
173
174   where
175     dflags    = hsc_dflags hsc_env
176     ghci_mode = ghcMode (hsc_dflags hsc_env)
177
178 mkAutoScc :: Module -> NameSet -> AutoScc
179 mkAutoScc mod exports
180   | not opt_SccProfilingOn      -- No profiling
181   = NoSccs              
182   | opt_AutoSccsOnAllToplevs    -- Add auto-scc on all top-level things
183   = AddSccs mod (\id -> True)
184   | opt_AutoSccsOnExportedToplevs       -- Only on exported things
185   = AddSccs mod (\id -> idName id `elemNameSet` exports)
186   | otherwise
187   = NoSccs
188
189
190 deSugarExpr :: HscEnv
191             -> Module -> GlobalRdrEnv -> TypeEnv 
192             -> LHsExpr Id
193             -> IO (Maybe CoreExpr)
194 -- Prints its own errors; returns Nothing if error occurred
195
196 deSugarExpr hsc_env this_mod rdr_env type_env tc_expr
197   = do  { let dflags = hsc_dflags hsc_env
198         ; showPass dflags "Desugar"
199
200         -- Do desugaring
201         ; mb_core_expr <- initDs hsc_env this_mod rdr_env type_env $
202                           dsLExpr tc_expr
203
204         ; case mb_core_expr of {
205             Nothing   -> return Nothing ;
206             Just expr -> do {
207
208                 -- Dump output
209           dumpIfSet_dyn dflags Opt_D_dump_ds "Desugared" (pprCoreExpr expr)
210
211         ; return (Just expr) } } }
212
213 --              addExportFlags
214 -- Set the no-discard flag if either 
215 --      a) the Id is exported
216 --      b) it's mentioned in the RHS of an orphan rule
217 --      c) it's in the keep-alive set
218 --
219 -- It means that the binding won't be discarded EVEN if the binding
220 -- ends up being trivial (v = w) -- the simplifier would usually just 
221 -- substitute w for v throughout, but we don't apply the substitution to
222 -- the rules (maybe we should?), so this substitution would make the rule
223 -- bogus.
224
225 -- You might wonder why exported Ids aren't already marked as such;
226 -- it's just because the type checker is rather busy already and
227 -- I didn't want to pass in yet another mapping.
228
229 addExportFlags ghci_mode exports keep_alive prs rules
230   = [(add_export bndr, rhs) | (bndr,rhs) <- prs]
231   where
232     add_export bndr
233         | dont_discard bndr = setIdExported bndr
234         | otherwise         = bndr
235
236     orph_rhs_fvs = unionVarSets [ ruleRhsFreeVars rule
237                                 | rule <- rules, 
238                                   not (isLocalRule rule) ]
239         -- A non-local rule keeps alive the free vars of its right-hand side. 
240         -- (A "non-local" is one whose head function is not locally defined.)
241         -- Local rules are (later, after gentle simplification) 
242         -- attached to the Id, and that keeps the rhs free vars alive.
243
244     dont_discard bndr = is_exported name
245                      || name `elemNameSet` keep_alive
246                      || bndr `elemVarSet` orph_rhs_fvs 
247                      where
248                         name = idName bndr
249
250         -- In interactive mode, we don't want to discard any top-level
251         -- entities at all (eg. do not inline them away during
252         -- simplification), and retain them all in the TypeEnv so they are
253         -- available from the command line.
254         --
255         -- isExternalName separates the user-defined top-level names from those
256         -- introduced by the type checker.
257     is_exported :: Name -> Bool
258     is_exported | ghci_mode == Interactive = isExternalName
259                 | otherwise                = (`elemNameSet` exports)
260
261 ppr_ds_rules [] = empty
262 ppr_ds_rules rules
263   = text "" $$ text "-------------- DESUGARED RULES -----------------" $$
264     pprRules rules
265 \end{code}
266
267
268
269 %************************************************************************
270 %*                                                                      *
271 %*              Desugaring transformation rules
272 %*                                                                      *
273 %************************************************************************
274
275 \begin{code}
276 dsRule :: Module -> IdSet -> LRuleDecl Id -> DsM (Maybe CoreRule)
277 dsRule mod in_scope (L loc (HsRule name act vars lhs tv_lhs rhs fv_rhs))
278   = putSrcSpanDs loc $ 
279     do  { let bndrs     = [var | RuleBndr (L _ var) <- vars]
280         ; lhs'  <- dsLExpr lhs
281         ; rhs'  <- dsLExpr rhs
282
283         ; case decomposeRuleLhs bndrs lhs' of {
284                 Nothing -> do { warnDs msg; return Nothing } ;
285                 Just (bndrs', fn_id, args) -> do
286         
287         -- Substitute the dict bindings eagerly,
288         -- and take the body apart into a (f args) form
289         { let local_rule = nameIsLocalOrFrom mod fn_name
290                 -- NB we can't use isLocalId in the orphan test, 
291                 -- because isLocalId isn't true of class methods
292               fn_name   = idName fn_id
293               lhs_names = fn_name : nameSetToList (exprsFreeNames args)
294                 -- No need to delete bndrs, because
295                 -- exprsFreeNames finds only External names
296
297                 -- A rule is an orphan only if none of the variables
298                 -- mentioned on its left-hand side are locally defined
299               orph = case filter (nameIsLocalOrFrom mod) lhs_names of
300                         (n:ns) -> Just (nameOccName n)
301                         []     -> Nothing
302
303               rule = Rule { ru_name = name, ru_fn = fn_name, ru_act = act,
304                             ru_bndrs = bndrs', ru_args = args, ru_rhs = rhs', 
305                             ru_rough = roughTopNames args, 
306                             ru_local = local_rule, ru_orph = orph }
307         ; return (Just rule)
308         } } }
309   where
310     msg = hang (ptext SLIT("RULE left-hand side too complicated to desugar; ignored"))
311              2 (ppr lhs)
312 \end{code}