module GHC.HsToCore.Expr
( dsExpr, dsLExpr, dsLExprNoLP, dsLocalBinds
, dsValBinds, dsLit, dsSyntaxExpr
)
where
#include "HsVersions.h"
import GHC.Prelude
import GHC.HsToCore.Match
import GHC.HsToCore.Match.Literal
import GHC.HsToCore.Binds
import GHC.HsToCore.GuardedRHSs
import GHC.HsToCore.ListComp
import GHC.HsToCore.Utils
import GHC.HsToCore.Arrows
import GHC.HsToCore.Monad
import GHC.HsToCore.Pmc ( addTyCs, pmcGRHSs )
import GHC.Types.SourceText
import GHC.Types.Name
import GHC.Types.Name.Env
import GHC.Core.FamInstEnv( topNormaliseType )
import GHC.HsToCore.Quote
import GHC.Hs
import GHC.Tc.Utils.TcType
import GHC.Tc.Types.Evidence
import GHC.Tc.Utils.Monad
import GHC.Core.Type
import GHC.Core.Multiplicity
import GHC.Core.Coercion( Coercion )
import GHC.Core
import GHC.Core.Utils
import GHC.Core.Make
import GHC.Driver.Session
import GHC.Types.CostCentre
import GHC.Types.Id
import GHC.Types.Id.Make
import GHC.Types.Var.Env
import GHC.Unit.Module
import GHC.Core.ConLike
import GHC.Core.DataCon
import GHC.Core.TyCo.Ppr( pprWithTYPE )
import GHC.Builtin.Types
import GHC.Builtin.Names
import GHC.Types.Basic
import GHC.Data.Maybe
import GHC.Types.SrcLoc
import GHC.Types.Tickish
import GHC.Utils.Misc
import GHC.Data.Bag
import GHC.Utils.Outputable as Outputable
import GHC.Utils.Panic
import GHC.Core.PatSyn
import Control.Monad
import Data.Void( absurd )
dsLocalBinds :: HsLocalBinds GhcTc -> CoreExpr -> DsM CoreExpr
dsLocalBinds (EmptyLocalBinds _) body = return body
dsLocalBinds b@(HsValBinds _ binds) body = putSrcSpanDs (spanHsLocaLBinds b) $
dsValBinds binds body
dsLocalBinds (HsIPBinds _ binds) body = dsIPBinds binds body
dsValBinds :: HsValBinds GhcTc -> CoreExpr -> DsM CoreExpr
dsValBinds (XValBindsLR (NValBinds binds _)) body
= foldrM ds_val_bind body binds
dsValBinds (ValBinds {}) _ = panic "dsValBinds ValBindsIn"
dsIPBinds :: HsIPBinds GhcTc -> CoreExpr -> DsM CoreExpr
dsIPBinds (IPBinds ev_binds ip_binds) body
= do { ds_binds <- dsTcEvBinds ev_binds
; let inner = mkCoreLets ds_binds body
; foldrM ds_ip_bind inner ip_binds }
where
ds_ip_bind :: LIPBind GhcTc -> CoreExpr -> DsM CoreExpr
ds_ip_bind (L _ (IPBind _ ~(Right n) e)) body
= do e' <- dsLExpr e
return (Let (NonRec n e') body)
ds_val_bind :: (RecFlag, LHsBinds GhcTc) -> CoreExpr -> DsM CoreExpr
ds_val_bind (NonRecursive, hsbinds) body
| [L loc bind] <- bagToList hsbinds
, isUnliftedHsBind bind
= putSrcSpanDs (locA loc) $
if is_polymorphic bind
then errDsCoreExpr (poly_bind_err bind)
else do { when (looksLazyPatBind bind) $
warnIfSetDs Opt_WarnUnbangedStrictPatterns (unlifted_must_be_bang bind)
; dsUnliftedBind bind body }
where
is_polymorphic (AbsBinds { abs_tvs = tvs, abs_ev_vars = evs })
= not (null tvs && null evs)
is_polymorphic _ = False
unlifted_must_be_bang bind
= hang (text "Pattern bindings containing unlifted types should use" $$
text "an outermost bang pattern:")
2 (ppr bind)
poly_bind_err bind
= hang (text "You can't mix polymorphic and unlifted bindings:")
2 (ppr bind) $$
text "Probable fix: add a type signature"
ds_val_bind (is_rec, binds) _body
| anyBag (isUnliftedHsBind . unLoc) binds
= ASSERT( isRec is_rec )
errDsCoreExpr $
hang (text "Recursive bindings for unlifted types aren't allowed:")
2 (vcat (map ppr (bagToList binds)))
ds_val_bind (is_rec, binds) body
= do { MASSERT( isRec is_rec || isSingletonBag binds )
; (force_vars,prs) <- dsLHsBinds binds
; let body' = foldr seqVar body force_vars
; ASSERT2( not (any (isUnliftedType . idType . fst) prs), ppr is_rec $$ ppr binds )
case prs of
[] -> return body
_ -> return (Let (Rec prs) body') }
dsUnliftedBind :: HsBind GhcTc -> CoreExpr -> DsM CoreExpr
dsUnliftedBind (AbsBinds { abs_tvs = [], abs_ev_vars = []
, abs_exports = exports
, abs_ev_binds = ev_binds
, abs_binds = lbinds }) body
= do { let body1 = foldr bind_export body exports
bind_export export b = bindNonRec (abe_poly export) (Var (abe_mono export)) b
; body2 <- foldlM (\body lbind -> dsUnliftedBind (unLoc lbind) body)
body1 lbinds
; ds_binds <- dsTcEvBinds_s ev_binds
; return (mkCoreLets ds_binds body2) }
dsUnliftedBind (FunBind { fun_id = L l fun
, fun_matches = matches
, fun_ext = co_fn
, fun_tick = tick }) body
= do { (args, rhs) <- matchWrapper (mkPrefixFunRhs (L l $ idName fun))
Nothing matches
; MASSERT( null args )
; MASSERT( isIdHsWrapper co_fn )
; let rhs' = mkOptTickBox tick rhs
; return (bindNonRec fun rhs' body) }
dsUnliftedBind (PatBind {pat_lhs = pat, pat_rhs = grhss
, pat_ext = ty }) body
=
do { match_nablas <- pmcGRHSs PatBindGuards grhss
; rhs <- dsGuarded grhss ty match_nablas
; let upat = unLoc pat
eqn = EqnInfo { eqn_pats = [upat],
eqn_orig = FromSource,
eqn_rhs = cantFailMatchResult body }
; var <- selectMatchVar Many upat
; result <- matchEquations PatBindRhs [var] [eqn] (exprType body)
; return (bindNonRec var rhs result) }
dsUnliftedBind bind body = pprPanic "dsLet: unlifted" (ppr bind $$ ppr body)
dsLExpr :: LHsExpr GhcTc -> DsM CoreExpr
dsLExpr (L loc e) =
putSrcSpanDsA loc $ dsExpr e
dsLExprNoLP :: LHsExpr GhcTc -> DsM CoreExpr
dsLExprNoLP (L loc e)
= putSrcSpanDsA loc $
do { e' <- dsExpr e
; dsNoLevPolyExpr e' (text "In the type of expression:" <+> ppr e)
; return e' }
dsExpr :: HsExpr GhcTc -> DsM CoreExpr
dsExpr (HsVar _ (L _ id)) = dsHsVar id
dsExpr (HsRecFld _ (Unambiguous id _)) = dsHsVar id
dsExpr (HsRecFld _ (Ambiguous id _)) = dsHsVar id
dsExpr (HsUnboundVar (HER ref _ _) _) = dsEvTerm =<< readMutVar ref
dsExpr (HsPar _ e) = dsLExpr e
dsExpr (ExprWithTySig _ e _) = dsLExpr e
dsExpr (HsConLikeOut _ con) = dsConLike con
dsExpr (HsIPVar {}) = panic "dsExpr: HsIPVar"
dsExpr (HsGetField x _ _) = absurd x
dsExpr (HsProjection x _) = absurd x
dsExpr (HsLit _ lit)
= do { warnAboutOverflowedLit lit
; dsLit (convertLit lit) }
dsExpr (HsOverLit _ lit)
= do { warnAboutOverflowedOverLit lit
; dsOverLit lit }
dsExpr e@(XExpr expansion)
= case expansion of
ExpansionExpr (HsExpanded _ b) -> dsExpr b
WrapExpr {} -> dsHsWrapped e
dsExpr (NegApp _ (L loc
(HsOverLit _ lit@(OverLit { ol_val = HsIntegral i})))
neg_expr)
= do { expr' <- putSrcSpanDsA loc $ do
{ warnAboutOverflowedOverLit
(lit { ol_val = HsIntegral (negateIntegralLit i) })
; dsOverLit lit }
; dsSyntaxExpr neg_expr [expr'] }
dsExpr (NegApp _ expr neg_expr)
= do { expr' <- dsLExpr expr
; dsSyntaxExpr neg_expr [expr'] }
dsExpr (HsLam _ a_Match)
= uncurry mkLams <$> matchWrapper LambdaExpr Nothing a_Match
dsExpr (HsLamCase _ matches)
= do { ([discrim_var], matching_code) <- matchWrapper CaseAlt Nothing matches
; return $ Lam discrim_var matching_code }
dsExpr e@(HsApp _ fun arg)
= do { fun' <- dsLExpr fun
; dsWhenNoErrs (dsLExprNoLP arg)
(\arg' -> mkCoreAppDs (text "HsApp" <+> ppr e) fun' arg') }
dsExpr e@(HsAppType {}) = dsHsWrapped e
dsExpr (ExplicitTuple _ tup_args boxity)
= do { let go (lam_vars, args) (Missing (Scaled mult ty))
= do { lam_var <- newSysLocalDsNoLP mult ty
; return (lam_var : lam_vars, Var lam_var : args) }
go (lam_vars, args) (Present _ expr)
= do { core_expr <- dsLExprNoLP expr
; return (lam_vars, core_expr : args) }
; dsWhenNoErrs (foldM go ([], []) (reverse tup_args))
(\(lam_vars, args) ->
mkCoreLams lam_vars $
mkCoreTupBoxity boxity args) }
dsExpr (ExplicitSum types alt arity expr)
= dsWhenNoErrs (dsLExprNoLP expr) (mkCoreUbxSum arity alt types)
dsExpr (HsPragE _ prag expr) =
ds_prag_expr prag expr
dsExpr (HsCase _ discrim matches)
= do { core_discrim <- dsLExpr discrim
; ([discrim_var], matching_code) <- matchWrapper CaseAlt (Just discrim) matches
; return (bindNonRec discrim_var core_discrim matching_code) }
dsExpr (HsLet _ binds body) = do
body' <- dsLExpr body
dsLocalBinds binds body'
dsExpr (HsDo res_ty ListComp (L _ stmts)) = dsListComp stmts res_ty
dsExpr (HsDo _ ctx@DoExpr{} (L _ stmts)) = dsDo ctx stmts
dsExpr (HsDo _ ctx@GhciStmtCtxt (L _ stmts)) = dsDo ctx stmts
dsExpr (HsDo _ ctx@MDoExpr{} (L _ stmts)) = dsDo ctx stmts
dsExpr (HsDo _ MonadComp (L _ stmts)) = dsMonadComp stmts
dsExpr (HsIf _ guard_expr then_expr else_expr)
= do { pred <- dsLExpr guard_expr
; b1 <- dsLExpr then_expr
; b2 <- dsLExpr else_expr
; return $ mkIfThenElse pred b1 b2 }
dsExpr (HsMultiIf res_ty alts)
| null alts
= mkErrorExpr
| otherwise
= do { let grhss = GRHSs noExtField alts emptyLocalBinds
; rhss_nablas <- pmcGRHSs IfAlt grhss
; match_result <- dsGRHSs IfAlt grhss res_ty rhss_nablas
; error_expr <- mkErrorExpr
; extractMatchResult match_result error_expr }
where
mkErrorExpr = mkErrorAppDs nON_EXHAUSTIVE_GUARDS_ERROR_ID res_ty
(text "multi-way if")
dsExpr (ExplicitList elt_ty xs) = dsExplicitList elt_ty xs
dsExpr (ArithSeq expr witness seq)
= case witness of
Nothing -> dsArithSeq expr seq
Just fl -> do { newArithSeq <- dsArithSeq expr seq
; dsSyntaxExpr fl [newArithSeq] }
dsExpr (HsStatic _ expr@(L loc _)) = do
expr_ds <- dsLExprNoLP expr
let ty = exprType expr_ds
makeStaticId <- dsLookupGlobalId makeStaticName
dflags <- getDynFlags
let platform = targetPlatform dflags
let (line, col) = case locA loc of
RealSrcSpan r _ ->
( srcLocLine $ realSrcSpanStart r
, srcLocCol $ realSrcSpanStart r
)
_ -> (0, 0)
srcLoc = mkCoreConApps (tupleDataCon Boxed 2)
[ Type intTy , Type intTy
, mkIntExprInt platform line, mkIntExprInt platform col
]
putSrcSpanDsA loc $ return $
mkCoreApps (Var makeStaticId) [ Type ty, srcLoc, expr_ds ]
dsExpr (RecordCon { rcon_con = L _ con_like
, rcon_flds = rbinds
, rcon_ext = con_expr })
= do { con_expr' <- dsExpr con_expr
; let
(arg_tys, _) = tcSplitFunTys (exprType con_expr')
mk_arg (arg_ty, fl)
= case findField (rec_flds rbinds) (flSelector fl) of
(rhs:rhss) -> ASSERT( null rhss )
dsLExprNoLP rhs
[] -> mkErrorAppDs rEC_CON_ERROR_ID arg_ty (ppr (flLabel fl))
unlabelled_bottom arg_ty = mkErrorAppDs rEC_CON_ERROR_ID arg_ty Outputable.empty
labels = conLikeFieldLabels con_like
; con_args <- if null labels
then mapM unlabelled_bottom (map scaledThing arg_tys)
else mapM mk_arg (zipEqual "dsExpr:RecordCon" (map scaledThing arg_tys) labels)
; return (mkCoreApps con_expr' con_args) }
dsExpr RecordUpd { rupd_flds = Right _} =
panic "The impossible happened"
dsExpr expr@(RecordUpd { rupd_expr = record_expr, rupd_flds = Left fields
, rupd_ext = RecordUpdTc
{ rupd_cons = cons_to_upd
, rupd_in_tys = in_inst_tys
, rupd_out_tys = out_inst_tys
, rupd_wrap = dict_req_wrap }} )
| null fields
= dsLExpr record_expr
| otherwise
= ASSERT2( notNull cons_to_upd, ppr expr )
do { record_expr' <- dsLExpr record_expr
; field_binds' <- mapM ds_field fields
; let upd_fld_env :: NameEnv Id
upd_fld_env = mkNameEnv [(f,l) | (f,l,_) <- field_binds']
; alts <- mapM (mk_alt upd_fld_env) cons_to_upd
; ([discrim_var], matching_code)
<- matchWrapper RecUpd (Just record_expr)
(MG { mg_alts = noLocA alts
, mg_ext = MatchGroupTc [unrestricted in_ty] out_ty
, mg_origin = FromSource
})
; return (add_field_binds field_binds' $
bindNonRec discrim_var record_expr' matching_code) }
where
ds_field :: LHsRecUpdField GhcTc -> DsM (Name, Id, CoreExpr)
ds_field (L _ rec_field)
= do { rhs <- dsLExpr (hsRecFieldArg rec_field)
; let fld_id = unLoc (hsRecUpdFieldId rec_field)
; lcl_id <- newSysLocalDs (idMult fld_id) (idType fld_id)
; return (idName fld_id, lcl_id, rhs) }
add_field_binds [] expr = expr
add_field_binds ((_,b,r):bs) expr = bindNonRec b r (add_field_binds bs expr)
(in_ty, out_ty) =
case (head cons_to_upd) of
RealDataCon data_con ->
let tycon = dataConTyCon data_con in
(mkTyConApp tycon in_inst_tys, mkFamilyTyConApp tycon out_inst_tys)
PatSynCon pat_syn ->
( patSynInstResTy pat_syn in_inst_tys
, patSynInstResTy pat_syn out_inst_tys)
mk_alt upd_fld_env con
= do { let (univ_tvs, ex_tvs, eq_spec,
prov_theta, _req_theta, arg_tys, _) = conLikeFullSig con
arg_tys' = map (scaleScaled Many) arg_tys
user_tvs = binderVars $ conLikeUserTyVarBinders con
in_subst = zipTvSubst univ_tvs in_inst_tys
out_subst = zipTvSubst univ_tvs out_inst_tys
; eqs_vars <- mapM newPredVarDs (substTheta in_subst (eqSpecPreds eq_spec))
; theta_vars <- mapM newPredVarDs (substTheta in_subst prov_theta)
; arg_ids <- newSysLocalsDs (substScaledTysUnchecked in_subst arg_tys')
; let field_labels = conLikeFieldLabels con
val_args = zipWithEqual "dsExpr:RecordUpd" mk_val_arg
field_labels arg_ids
mk_val_arg fl pat_arg_id
= nlHsVar (lookupNameEnv upd_fld_env (flSelector fl) `orElse` pat_arg_id)
inst_con = noLocA $ mkHsWrap wrap (HsConLikeOut noExtField con)
wrap = mkWpEvVarApps theta_vars <.>
dict_req_wrap <.>
mkWpTyApps [ lookupTyVar out_subst tv
`orElse` mkTyVarTy tv
| tv <- user_tvs ]
rhs = foldl' (\a b -> nlHsApp a b) inst_con val_args
wrapped_rhs =
case con of
RealDataCon data_con
| null eq_spec -> rhs
| otherwise -> mkLHsWrap (mkWpCastN wrap_co) rhs
where
rep_tc = dataConTyCon data_con
wrap_co = mkTcFamilyTyConAppCo rep_tc univ_cos
univ_cos = zipWithEqual "dsExpr:upd" mk_univ_co univ_tvs out_inst_tys
mk_univ_co :: TyVar
-> Type
-> Coercion
mk_univ_co univ_tv inst_ty
= case lookupVarEnv eq_spec_env univ_tv of
Just co -> co
Nothing -> mkTcNomReflCo inst_ty
eq_spec_env :: VarEnv Coercion
eq_spec_env = mkVarEnv [ (eqSpecTyVar spec, mkTcSymCo (mkTcCoVarCo eqs_var))
| (spec,eqs_var) <- zipEqual "dsExpr:upd2" eq_spec eqs_vars ]
PatSynCon _ -> rhs
req_wrap = dict_req_wrap <.> mkWpTyApps in_inst_tys
pat = noLocA $ ConPat { pat_con = noLocA con
, pat_args = PrefixCon [] $ map nlVarPat arg_ids
, pat_con_ext = ConPatTc
{ cpt_tvs = ex_tvs
, cpt_dicts = eqs_vars ++ theta_vars
, cpt_binds = emptyTcEvBinds
, cpt_arg_tys = in_inst_tys
, cpt_wrap = req_wrap
}
}
; return (mkSimpleMatch RecUpd [pat] wrapped_rhs) }
dsExpr (HsRnBracketOut _ _ _) = panic "dsExpr HsRnBracketOut"
dsExpr (HsTcBracketOut _ hs_wrapper x ps) = dsBracket hs_wrapper x ps
dsExpr (HsSpliceE _ s) = pprPanic "dsExpr:splice" (ppr s)
dsExpr (HsProc _ pat cmd) = dsProcExpr pat cmd
dsExpr (HsTick _ tickish e) = do
e' <- dsLExpr e
return (Tick tickish e')
dsExpr (HsBinTick _ ixT ixF e) = do
e2 <- dsLExpr e
do { ASSERT(exprType e2 `eqType` boolTy)
mkBinaryTickBox ixT ixF e2
}
dsExpr (HsOverLabel x _) = absurd x
dsExpr (OpApp x _ _ _) = absurd x
dsExpr (SectionL x _ _) = absurd x
dsExpr (SectionR x _ _) = absurd x
dsExpr (HsBracket {}) = panic "dsExpr:HsBracket"
dsExpr (HsDo {}) = panic "dsExpr:HsDo"
ds_prag_expr :: HsPragE GhcTc -> LHsExpr GhcTc -> DsM CoreExpr
ds_prag_expr (HsPragSCC _ _ cc) expr = do
dflags <- getDynFlags
if sccProfilingEnabled dflags
then do
mod_name <- getModule
count <- goptM Opt_ProfCountEntries
let nm = sl_fs cc
flavour <- ExprCC <$> getCCIndexDsM nm
Tick (ProfNote (mkUserCC nm mod_name (getLocA expr) flavour) count True)
<$> dsLExpr expr
else dsLExpr expr
dsSyntaxExpr :: SyntaxExpr GhcTc -> [CoreExpr] -> DsM CoreExpr
dsSyntaxExpr (SyntaxExprTc { syn_expr = expr
, syn_arg_wraps = arg_wraps
, syn_res_wrap = res_wrap })
arg_exprs
= do { fun <- dsExpr expr
; core_arg_wraps <- mapM dsHsWrapper arg_wraps
; core_res_wrap <- dsHsWrapper res_wrap
; let wrapped_args = zipWithEqual "dsSyntaxExpr" ($) core_arg_wraps arg_exprs
; dsWhenNoErrs (zipWithM_ dsNoLevPolyExpr wrapped_args [ mk_doc n | n <- [1..] ])
(\_ -> core_res_wrap (mkApps fun wrapped_args)) }
where
mk_doc n = text "In the" <+> speakNth n <+> text "argument of" <+> quotes (ppr expr)
dsSyntaxExpr NoSyntaxExprTc _ = panic "dsSyntaxExpr"
findField :: [LHsRecField GhcTc arg] -> Name -> [arg]
findField rbinds sel
= [hsRecFieldArg fld | L _ fld <- rbinds
, sel == idName (unLoc $ hsRecFieldId fld) ]
maxBuildLength :: Int
maxBuildLength = 32
dsExplicitList :: Type -> [LHsExpr GhcTc]
-> DsM CoreExpr
dsExplicitList elt_ty xs
= do { dflags <- getDynFlags
; xs' <- mapM dsLExprNoLP xs
; if xs' `lengthExceeds` maxBuildLength
|| null xs'
|| not (gopt Opt_EnableRewriteRules dflags)
then return $ mkListExpr elt_ty xs'
else mkBuildExpr elt_ty (mk_build_list xs') }
where
mk_build_list xs' (cons, _) (nil, _)
= return (foldr (App . App (Var cons)) (Var nil) xs')
dsArithSeq :: PostTcExpr -> (ArithSeqInfo GhcTc) -> DsM CoreExpr
dsArithSeq expr (From from)
= App <$> dsExpr expr <*> dsLExprNoLP from
dsArithSeq expr (FromTo from to)
= do fam_envs <- dsGetFamInstEnvs
dflags <- getDynFlags
warnAboutEmptyEnumerations fam_envs dflags from Nothing to
expr' <- dsExpr expr
from' <- dsLExprNoLP from
to' <- dsLExprNoLP to
return $ mkApps expr' [from', to']
dsArithSeq expr (FromThen from thn)
= mkApps <$> dsExpr expr <*> mapM dsLExprNoLP [from, thn]
dsArithSeq expr (FromThenTo from thn to)
= do fam_envs <- dsGetFamInstEnvs
dflags <- getDynFlags
warnAboutEmptyEnumerations fam_envs dflags from (Just thn) to
expr' <- dsExpr expr
from' <- dsLExprNoLP from
thn' <- dsLExprNoLP thn
to' <- dsLExprNoLP to
return $ mkApps expr' [from', thn', to']
dsDo :: HsStmtContext GhcRn -> [ExprLStmt GhcTc] -> DsM CoreExpr
dsDo ctx stmts
= goL stmts
where
goL [] = panic "dsDo"
goL ((L loc stmt):lstmts) = putSrcSpanDsA loc (go loc stmt lstmts)
go _ (LastStmt _ body _ _) stmts
= ASSERT( null stmts ) dsLExpr body
go _ (BodyStmt _ rhs then_expr _) stmts
= do { rhs2 <- dsLExpr rhs
; warnDiscardedDoBindings rhs (exprType rhs2)
; rest <- goL stmts
; dsSyntaxExpr then_expr [rhs2, rest] }
go _ (LetStmt _ binds) stmts
= do { rest <- goL stmts
; dsLocalBinds binds rest }
go _ (BindStmt xbs pat rhs) stmts
= do { body <- goL stmts
; rhs' <- dsLExpr rhs
; var <- selectSimpleMatchVarL (xbstc_boundResultMult xbs) pat
; match <- matchSinglePatVar var Nothing (StmtCtxt ctx) pat
(xbstc_boundResultType xbs) (cantFailMatchResult body)
; match_code <- dsHandleMonadicFailure ctx pat match (xbstc_failOp xbs)
; dsSyntaxExpr (xbstc_bindOp xbs) [rhs', Lam var match_code] }
go _ (ApplicativeStmt body_ty args mb_join) stmts
= do {
let
(pats, rhss) = unzip (map (do_arg . snd) args)
do_arg (ApplicativeArgOne fail_op pat expr _) =
((pat, fail_op), dsLExpr expr)
do_arg (ApplicativeArgMany _ stmts ret pat _) =
((pat, Nothing), dsDo ctx (stmts ++ [noLocA $ mkLastStmt (noLocA ret)]))
; rhss' <- sequence rhss
; body' <- dsLExpr $ noLocA $ HsDo body_ty ctx (noLocA stmts)
; let match_args (pat, fail_op) (vs,body)
= do { var <- selectSimpleMatchVarL Many pat
; match <- matchSinglePatVar var Nothing (StmtCtxt ctx) pat
body_ty (cantFailMatchResult body)
; match_code <- dsHandleMonadicFailure ctx pat match fail_op
; return (var:vs, match_code)
}
; (vars, body) <- foldrM match_args ([],body') pats
; let fun' = mkLams vars body
; let mk_ap_call l (op,r) = dsSyntaxExpr op [l,r]
; expr <- foldlM mk_ap_call fun' (zip (map fst args) rhss')
; case mb_join of
Nothing -> return expr
Just join_op -> dsSyntaxExpr join_op [expr] }
go loc (RecStmt { recS_stmts = L _ rec_stmts, recS_later_ids = later_ids
, recS_rec_ids = rec_ids, recS_ret_fn = return_op
, recS_mfix_fn = mfix_op, recS_bind_fn = bind_op
, recS_ext = RecStmtTc
{ recS_bind_ty = bind_ty
, recS_rec_rets = rec_rets
, recS_ret_ty = body_ty} }) stmts
= goL (new_bind_stmt : stmts)
where
new_bind_stmt = L loc $ BindStmt
XBindStmtTc
{ xbstc_bindOp = bind_op
, xbstc_boundResultType = bind_ty
, xbstc_boundResultMult = Many
, xbstc_failOp = Nothing
}
(mkBigLHsPatTupId later_pats)
mfix_app
tup_ids = rec_ids ++ filterOut (`elem` rec_ids) later_ids
tup_ty = mkBigCoreTupTy (map idType tup_ids)
rec_tup_pats = map nlVarPat tup_ids
later_pats = rec_tup_pats
rets = map noLocA rec_rets
mfix_app = nlHsSyntaxApps mfix_op [mfix_arg]
mfix_arg = noLocA $ HsLam noExtField
(MG { mg_alts = noLocA [mkSimpleMatch
LambdaExpr
[mfix_pat] body]
, mg_ext = MatchGroupTc [unrestricted tup_ty] body_ty
, mg_origin = Generated })
mfix_pat = noLocA $ LazyPat noExtField $ mkBigLHsPatTupId rec_tup_pats
body = noLocA $ HsDo body_ty
ctx (noLocA (rec_stmts ++ [ret_stmt]))
ret_app = nlHsSyntaxApps return_op [mkBigLHsTupId rets]
ret_stmt = noLocA $ mkLastStmt ret_app
go _ (ParStmt {}) _ = panic "dsDo ParStmt"
go _ (TransStmt {}) _ = panic "dsDo TransStmt"
dsHsVar :: Id -> DsM CoreExpr
dsHsVar var
= do { checkLevPolyFunction (ppr var) var (idType var)
; return (varToCoreExpr var) }
dsConLike :: ConLike -> DsM CoreExpr
dsConLike (RealDataCon dc) = dsHsVar (dataConWrapId dc)
dsConLike (PatSynCon ps)
| Just (builder_name, _, add_void) <- patSynBuilder ps
= do { builder_id <- dsLookupGlobalId builder_name
; return (if add_void
then mkCoreApp (text "dsConLike" <+> ppr ps)
(Var builder_id) (Var voidPrimId)
else Var builder_id) }
| otherwise
= pprPanic "dsConLike" (ppr ps)
warnDiscardedDoBindings :: LHsExpr GhcTc -> Type -> DsM ()
warnDiscardedDoBindings rhs rhs_ty
| Just (m_ty, elt_ty) <- tcSplitAppTy_maybe rhs_ty
= do { warn_unused <- woptM Opt_WarnUnusedDoBind
; warn_wrong <- woptM Opt_WarnWrongDoBind
; when (warn_unused || warn_wrong) $
do { fam_inst_envs <- dsGetFamInstEnvs
; let norm_elt_ty = topNormaliseType fam_inst_envs elt_ty
; if warn_unused && not (isUnitTy norm_elt_ty)
then warnDs (Reason Opt_WarnUnusedDoBind)
(badMonadBind rhs elt_ty)
else
when warn_wrong $
case tcSplitAppTy_maybe norm_elt_ty of
Just (elt_m_ty, _)
| m_ty `eqType` topNormaliseType fam_inst_envs elt_m_ty
-> warnDs (Reason Opt_WarnWrongDoBind)
(badMonadBind rhs elt_ty)
_ -> return () } }
| otherwise
= return ()
badMonadBind :: LHsExpr GhcTc -> Type -> SDoc
badMonadBind rhs elt_ty
= vcat [ hang (text "A do-notation statement discarded a result of type")
2 (quotes (ppr elt_ty))
, hang (text "Suppress this warning by saying")
2 (quotes $ text "_ <-" <+> ppr rhs)
]
dsHsWrapped :: HsExpr GhcTc -> DsM CoreExpr
dsHsWrapped orig_hs_expr
= go id orig_hs_expr
where
go wrap (XExpr (WrapExpr (HsWrap co_fn hs_e)))
= do { wrap' <- dsHsWrapper co_fn
; addTyCs FromSource (hsWrapDictBinders co_fn) $
go (wrap . wrap') hs_e }
go wrap (HsConLikeOut _ (RealDataCon dc))
= go_head wrap (dataConWrapId dc)
go wrap (HsAppType ty hs_e _) = go_l (wrap . (\e -> App e (Type ty))) hs_e
go wrap (HsPar _ hs_e) = go_l wrap hs_e
go wrap (HsVar _ (L _ var)) = go_head wrap var
go wrap hs_e = do { e <- dsExpr hs_e; return (wrap e) }
go_l wrap (L _ hs_e) = go wrap hs_e
go_head wrap var
= do { let wrapped_e = wrap (Var var)
wrapped_ty = exprType wrapped_e
; checkLevPolyFunction (ppr orig_hs_expr) var wrapped_ty
; dflags <- getDynFlags
; warnAboutIdentities dflags var wrapped_ty
; return wrapped_e }
checkLevPolyFunction :: SDoc -> Id -> Type -> DsM ()
checkLevPolyFunction pp_hs_expr var ty
| let bad_tys = isBadLevPolyFunction var ty
, not (null bad_tys)
= errDs $ vcat
[ hang (text "Cannot use function with levity-polymorphic arguments:")
2 (pp_hs_expr <+> dcolon <+> pprWithTYPE ty)
, ppUnlessOption sdocPrintTypecheckerElaboration $ vcat
[ text "(Note that levity-polymorphic primops such as 'coerce' and unboxed tuples"
, text "are eta-expanded internally because they must occur fully saturated."
, text "Use -fprint-typechecker-elaboration to display the full expression.)"
]
, hang (text "Levity-polymorphic arguments:")
2 $ vcat $ map
(\t -> pprWithTYPE t <+> dcolon <+> pprWithTYPE (typeKind t))
bad_tys
]
checkLevPolyFunction _ _ _ = return ()
isBadLevPolyFunction :: Id -> Type -> [Type]
isBadLevPolyFunction id ty
| hasNoBinding id
= filter isTypeLevPoly arg_tys
| otherwise
= []
where
(binders, _) = splitPiTys ty
arg_tys = mapMaybe binderRelevantType_maybe binders