Refactor the desugaring of RULE lhss a bit
[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 import DynFlags
12 import StaticFlags
13 import HscTypes
14 import HsSyn
15 import TcRnTypes
16 import MkIface
17 import Id
18 import Name
19 import CoreSyn
20 import PprCore
21 import DsMonad
22 import DsExpr
23 import DsBinds
24 import DsForeign
25 import DsExpr           ()      -- Forces DsExpr to be compiled; DsBinds only
26                                 -- depends on DsExpr.hi-boot.
27 import Module
28 import RdrName
29 import NameSet
30 import VarSet
31 import Rules
32 import CoreLint
33 import CoreFVs
34 import ErrUtils
35 import Outputable
36 import SrcLoc
37 import Maybes
38 import FastString
39 import Coverage
40
41 import Data.IORef
42 \end{code}
43
44 %************************************************************************
45 %*                                                                      *
46 %*              The main function: deSugar
47 %*                                                                      *
48 %************************************************************************
49
50 \begin{code}
51 deSugar :: HscEnv -> ModLocation -> TcGblEnv -> IO (Messages, Maybe ModGuts)
52 -- Can modify PCS by faulting in more declarations
53
54 deSugar hsc_env 
55         mod_loc
56         tcg_env@(TcGblEnv { tcg_mod          = mod,
57                             tcg_src          = hsc_src,
58                             tcg_type_env     = type_env,
59                             tcg_imports      = imports,
60                             tcg_exports      = exports,
61                             tcg_keep         = keep_var,
62                             tcg_rdr_env      = rdr_env,
63                             tcg_fix_env      = fix_env,
64                             tcg_inst_env     = inst_env,
65                             tcg_fam_inst_env = fam_inst_env,
66                             tcg_warns      = warns,
67                             tcg_binds        = binds,
68                             tcg_fords        = fords,
69                             tcg_rules        = rules,
70                             tcg_insts        = insts,
71                             tcg_fam_insts    = fam_insts,
72                             tcg_hpc          = other_hpc_info })
73
74   = do  { let dflags = hsc_dflags hsc_env
75         ; showPass dflags "Desugar"
76
77         -- Desugar the program
78         ; let export_set = availsToNameSet exports
79         ; let auto_scc = mkAutoScc mod export_set
80         ; let target = hscTarget dflags
81         ; let hpcInfo = emptyHpcInfo other_hpc_info
82         ; (msgs, mb_res)
83               <- case target of
84                    HscNothing ->
85                        return (emptyMessages,
86                                Just ([], [], NoStubs, hpcInfo, emptyModBreaks))
87                    _        -> do
88                      (binds_cvr,ds_hpc_info, modBreaks)
89                          <- if (opt_Hpc
90                                   || target == HscInterpreted)
91                                && (not (isHsBoot hsc_src))
92                               then addCoverageTicksToBinds dflags mod mod_loc (typeEnvTyCons type_env) binds 
93                               else return (binds, hpcInfo, emptyModBreaks)
94                      initDs hsc_env mod rdr_env type_env $ do
95                          core_prs <- dsTopLHsBinds auto_scc binds_cvr
96                          (ds_fords, foreign_prs) <- dsForeigns fords
97                          let all_prs = foreign_prs ++ core_prs
98                          ds_rules <- mapM dsRule rules
99                          return (all_prs, catMaybes ds_rules, ds_fords, ds_hpc_info, modBreaks)
100
101         ; case mb_res of {
102            Nothing -> return (msgs, Nothing) ;
103            Just (all_prs, ds_rules, ds_fords,ds_hpc_info, modBreaks) -> do
104
105         {       -- Add export flags to bindings
106           keep_alive <- readIORef keep_var
107         ; let final_prs = addExportFlags target export_set
108                                  keep_alive all_prs ds_rules
109               ds_binds  = [Rec final_prs]
110         -- Notice that we put the whole lot in a big Rec, even the foreign binds
111         -- When compiling PrelFloat, which defines data Float = F# Float#
112         -- we want F# to be in scope in the foreign marshalling code!
113         -- You might think it doesn't matter, but the simplifier brings all top-level
114         -- things into the in-scope set before simplifying; so we get no unfolding for F#!
115
116         -- Lint result if necessary
117         ; endPass dflags "Desugar" Opt_D_dump_ds ds_binds
118
119         -- Dump output
120         ; doIfSet (dopt Opt_D_dump_ds dflags) 
121                   (printDump (ppr_ds_rules ds_rules))
122
123         ; used_names <- mkUsedNames tcg_env
124         ; deps <- mkDependencies tcg_env
125
126         ; let mod_guts = ModGuts {      
127                 mg_module       = mod,
128                 mg_boot         = isHsBoot hsc_src,
129                 mg_exports      = exports,
130                 mg_deps         = deps,
131                 mg_used_names   = used_names,
132                 mg_dir_imps     = imp_mods imports,
133                 mg_rdr_env      = rdr_env,
134                 mg_fix_env      = fix_env,
135                 mg_warns        = warns,
136                 mg_types        = type_env,
137                 mg_insts        = insts,
138                 mg_fam_insts    = fam_insts,
139                 mg_inst_env     = inst_env,
140                 mg_fam_inst_env = fam_inst_env,
141                 mg_rules        = ds_rules,
142                 mg_binds        = ds_binds,
143                 mg_foreign      = ds_fords,
144                 mg_hpc_info     = ds_hpc_info,
145                 mg_modBreaks    = modBreaks,
146                 mg_vect_info    = noVectInfo
147               }
148         ; return (msgs, Just mod_guts)
149         }}}
150
151 mkAutoScc :: Module -> NameSet -> AutoScc
152 mkAutoScc mod exports
153   | not opt_SccProfilingOn      -- No profiling
154   = NoSccs              
155   | opt_AutoSccsOnAllToplevs    -- Add auto-scc on all top-level things
156   = AddSccs mod (\id -> not $ isDerivedOccName $ getOccName id)
157     -- See #1641.  This is pretty yucky, but I can't see a better way
158     -- to identify compiler-generated Ids, and at least this should
159     -- catch them all.
160   | opt_AutoSccsOnExportedToplevs       -- Only on exported things
161   = AddSccs mod (\id -> idName id `elemNameSet` exports)
162   | otherwise
163   = NoSccs
164
165 deSugarExpr :: HscEnv
166             -> Module -> GlobalRdrEnv -> TypeEnv 
167             -> LHsExpr Id
168             -> IO (Messages, Maybe CoreExpr)
169 -- Prints its own errors; returns Nothing if error occurred
170
171 deSugarExpr hsc_env this_mod rdr_env type_env tc_expr = do
172     let dflags = hsc_dflags hsc_env
173     showPass dflags "Desugar"
174
175     -- Do desugaring
176     (msgs, mb_core_expr) <- initDs hsc_env this_mod rdr_env type_env $
177                                    dsLExpr tc_expr
178
179     case mb_core_expr of
180       Nothing   -> return (msgs, Nothing)
181       Just expr -> do
182
183         -- Dump output
184         dumpIfSet_dyn dflags Opt_D_dump_ds "Desugared" (pprCoreExpr expr)
185
186         return (msgs, Just expr)
187
188 --              addExportFlags
189 -- Set the no-discard flag if either 
190 --      a) the Id is exported
191 --      b) it's mentioned in the RHS of an orphan rule
192 --      c) it's in the keep-alive set
193 --
194 -- It means that the binding won't be discarded EVEN if the binding
195 -- ends up being trivial (v = w) -- the simplifier would usually just 
196 -- substitute w for v throughout, but we don't apply the substitution to
197 -- the rules (maybe we should?), so this substitution would make the rule
198 -- bogus.
199
200 -- You might wonder why exported Ids aren't already marked as such;
201 -- it's just because the type checker is rather busy already and
202 -- I didn't want to pass in yet another mapping.
203
204 addExportFlags :: HscTarget -> NameSet -> NameSet -> [(Id, t)] -> [CoreRule]
205                -> [(Id, t)]
206 addExportFlags target exports keep_alive prs rules
207   = [(add_export bndr, rhs) | (bndr,rhs) <- prs]
208   where
209     add_export bndr
210         | dont_discard bndr = setIdExported bndr
211         | otherwise         = bndr
212
213     orph_rhs_fvs = unionVarSets [ ruleRhsFreeVars rule
214                                 | rule <- rules, 
215                                   not (isLocalRule rule) ]
216         -- A non-local rule keeps alive the free vars of its right-hand side. 
217         -- (A "non-local" is one whose head function is not locally defined.)
218         -- Local rules are (later, after gentle simplification) 
219         -- attached to the Id, and that keeps the rhs free vars alive.
220
221     dont_discard bndr = is_exported name
222                      || name `elemNameSet` keep_alive
223                      || bndr `elemVarSet` orph_rhs_fvs 
224                      where
225                         name = idName bndr
226
227         -- In interactive mode, we don't want to discard any top-level
228         -- entities at all (eg. do not inline them away during
229         -- simplification), and retain them all in the TypeEnv so they are
230         -- available from the command line.
231         --
232         -- isExternalName separates the user-defined top-level names from those
233         -- introduced by the type checker.
234     is_exported :: Name -> Bool
235     is_exported | target == HscInterpreted = isExternalName
236                 | otherwise                = (`elemNameSet` exports)
237
238 ppr_ds_rules :: [CoreRule] -> SDoc
239 ppr_ds_rules [] = empty
240 ppr_ds_rules rules
241   = text "" $$ text "-------------- DESUGARED RULES -----------------" $$
242     pprRules rules
243 \end{code}
244
245
246
247 %************************************************************************
248 %*                                                                      *
249 %*              Desugaring transformation rules
250 %*                                                                      *
251 %************************************************************************
252
253 \begin{code}
254 dsRule :: LRuleDecl Id -> DsM (Maybe CoreRule)
255 dsRule (L loc (HsRule name act vars lhs _tv_lhs rhs _fv_rhs))
256   = putSrcSpanDs loc $ 
257     do  { let bndrs' = [var | RuleBndr (L _ var) <- vars]
258         ; lhs'  <- dsLExpr lhs
259         ; rhs'  <- dsLExpr rhs
260
261         -- Substitute the dict bindings eagerly,
262         -- and take the body apart into a (f args) form
263         ; case decomposeRuleLhs (mkLams bndrs' lhs') of {
264                 Nothing -> do { warnDs msg; return Nothing } ;
265                 Just (bndrs, fn_id, args) -> do
266         
267         { let local_rule = isLocalId fn_id
268                 -- NB: isLocalId is False of implicit Ids.  This is good becuase
269                 -- we don't want to attach rules to the bindings of implicit Ids, 
270                 -- because they don't show up in the bindings until just before code gen
271               fn_name   = idName fn_id
272
273               rule = Rule { ru_name = name, ru_fn = fn_name, ru_act = act,
274                             ru_bndrs = bndrs, ru_args = args, ru_rhs = rhs', 
275                             ru_rough = roughTopNames args, 
276                             ru_local = local_rule }
277         ; return (Just rule)
278         } } }
279   where
280     msg = hang (ptext (sLit "RULE left-hand side too complicated to desugar; ignored"))
281              2 (ppr lhs)
282 \end{code}