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