%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 19921998
%
The Desugarer: turning HsSyn into Core.
\begin{code}
module Desugar ( deSugar, deSugarExpr ) where
import DynFlags
import StaticFlags
import HscTypes
import HsSyn
import TcRnTypes
import MkIface
import Id
import Name
import CoreSyn
import PprCore
import DsMonad
import DsExpr
import DsBinds
import DsForeign
import DsExpr ()
import Module
import RdrName
import NameSet
import VarSet
import Rules
import CoreLint
import CoreFVs
import ErrUtils
import Outputable
import SrcLoc
import Maybes
import FastString
import Coverage
import Data.IORef
\end{code}
%************************************************************************
%* *
%* The main function: deSugar
%* *
%************************************************************************
\begin{code}
deSugar :: HscEnv -> ModLocation -> TcGblEnv -> IO (Messages, Maybe ModGuts)
deSugar hsc_env
mod_loc
tcg_env@(TcGblEnv { tcg_mod = mod,
tcg_src = hsc_src,
tcg_type_env = type_env,
tcg_imports = imports,
tcg_exports = exports,
tcg_keep = keep_var,
tcg_rdr_env = rdr_env,
tcg_fix_env = fix_env,
tcg_inst_env = inst_env,
tcg_fam_inst_env = fam_inst_env,
tcg_warns = warns,
tcg_anns = anns,
tcg_binds = binds,
tcg_fords = fords,
tcg_rules = rules,
tcg_insts = insts,
tcg_fam_insts = fam_insts,
tcg_hpc = other_hpc_info })
= do { let dflags = hsc_dflags hsc_env
; showPass dflags "Desugar"
; let export_set = availsToNameSet exports
; let auto_scc = mkAutoScc dflags mod export_set
; let target = hscTarget dflags
; let hpcInfo = emptyHpcInfo other_hpc_info
; (msgs, mb_res)
<- case target of
HscNothing ->
return (emptyMessages,
Just ([], [], NoStubs, hpcInfo, emptyModBreaks))
_ -> do
(binds_cvr,ds_hpc_info, modBreaks)
<- if (opt_Hpc
|| target == HscInterpreted)
&& (not (isHsBoot hsc_src))
then addCoverageTicksToBinds dflags mod mod_loc (typeEnvTyCons type_env) binds
else return (binds, hpcInfo, emptyModBreaks)
initDs hsc_env mod rdr_env type_env $ do
core_prs <- dsTopLHsBinds auto_scc binds_cvr
(ds_fords, foreign_prs) <- dsForeigns fords
let all_prs = foreign_prs ++ core_prs
ds_rules <- mapM dsRule rules
return (all_prs, catMaybes ds_rules, ds_fords, ds_hpc_info, modBreaks)
; case mb_res of {
Nothing -> return (msgs, Nothing) ;
Just (all_prs, ds_rules, ds_fords,ds_hpc_info, modBreaks) -> do
{
keep_alive <- readIORef keep_var
; let final_prs = addExportFlags target export_set
keep_alive all_prs ds_rules
ds_binds = [Rec final_prs]
; endPass dflags "Desugar" Opt_D_dump_ds ds_binds
; doIfSet (dopt Opt_D_dump_ds dflags)
(printDump (ppr_ds_rules ds_rules))
; used_names <- mkUsedNames tcg_env
; deps <- mkDependencies tcg_env
; let mod_guts = ModGuts {
mg_module = mod,
mg_boot = isHsBoot hsc_src,
mg_exports = exports,
mg_deps = deps,
mg_used_names = used_names,
mg_dir_imps = imp_mods imports,
mg_rdr_env = rdr_env,
mg_fix_env = fix_env,
mg_warns = warns,
mg_anns = anns,
mg_types = type_env,
mg_insts = insts,
mg_fam_insts = fam_insts,
mg_inst_env = inst_env,
mg_fam_inst_env = fam_inst_env,
mg_rules = ds_rules,
mg_binds = ds_binds,
mg_foreign = ds_fords,
mg_hpc_info = ds_hpc_info,
mg_modBreaks = modBreaks,
mg_vect_info = noVectInfo
}
; return (msgs, Just mod_guts)
}}}
mkAutoScc :: DynFlags -> Module -> NameSet -> AutoScc
mkAutoScc dflags mod exports
| not opt_SccProfilingOn
= NoSccs
| dopt Opt_AutoSccsOnAllToplevs dflags
= AddSccs mod (\id -> not $ isDerivedOccName $ getOccName id)
| dopt Opt_AutoSccsOnExportedToplevs dflags
= AddSccs mod (\id -> idName id `elemNameSet` exports)
| otherwise
= NoSccs
deSugarExpr :: HscEnv
-> Module -> GlobalRdrEnv -> TypeEnv
-> LHsExpr Id
-> IO (Messages, Maybe CoreExpr)
deSugarExpr hsc_env this_mod rdr_env type_env tc_expr = do
let dflags = hsc_dflags hsc_env
showPass dflags "Desugar"
(msgs, mb_core_expr) <- initDs hsc_env this_mod rdr_env type_env $
dsLExpr tc_expr
case mb_core_expr of
Nothing -> return (msgs, Nothing)
Just expr -> do
dumpIfSet_dyn dflags Opt_D_dump_ds "Desugared" (pprCoreExpr expr)
return (msgs, Just expr)
addExportFlags :: HscTarget -> NameSet -> NameSet -> [(Id, t)] -> [CoreRule]
-> [(Id, t)]
addExportFlags target exports keep_alive prs rules
= [(add_export bndr, rhs) | (bndr,rhs) <- prs]
where
add_export bndr
| dont_discard bndr = setIdExported bndr
| otherwise = bndr
orph_rhs_fvs = unionVarSets [ ruleRhsFreeVars rule
| rule <- rules,
not (isLocalRule rule) ]
dont_discard bndr = is_exported name
|| name `elemNameSet` keep_alive
|| bndr `elemVarSet` orph_rhs_fvs
where
name = idName bndr
is_exported :: Name -> Bool
is_exported | target == HscInterpreted = isExternalName
| otherwise = (`elemNameSet` exports)
ppr_ds_rules :: [CoreRule] -> SDoc
ppr_ds_rules [] = empty
ppr_ds_rules rules
= text "" $$ text "-------------- DESUGARED RULES -----------------" $$
pprRules rules
\end{code}
%************************************************************************
%* *
%* Desugaring transformation rules
%* *
%************************************************************************
\begin{code}
dsRule :: LRuleDecl Id -> DsM (Maybe CoreRule)
dsRule (L loc (HsRule name act vars lhs _tv_lhs rhs _fv_rhs))
= putSrcSpanDs loc $
do { let bndrs' = [var | RuleBndr (L _ var) <- vars]
; lhs' <- dsLExpr lhs
; rhs' <- dsLExpr rhs
; case decomposeRuleLhs (mkLams bndrs' lhs') of {
Nothing -> do { warnDs msg; return Nothing } ;
Just (bndrs, fn_id, args) -> do
{ let local_rule = isLocalId fn_id
fn_name = idName fn_id
rule = Rule { ru_name = name, ru_fn = fn_name, ru_act = act,
ru_bndrs = bndrs, ru_args = args, ru_rhs = rhs',
ru_rough = roughTopNames args,
ru_local = local_rule }
; return (Just rule)
} } }
where
msg = hang (ptext (sLit "RULE left-hand side too complicated to desugar; ignored"))
2 (ppr lhs)
\end{code}