X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FdeSugar%2FDsExpr.lhs;h=e8e9e7b37000c4cf0b7548afac96cd9535a9a984;hb=31751ccacc24ebe5d15a0af84b10dc612d455440;hp=ce5a9d8e7b2b7380754fd9fc84d681b05d4fa69e;hpb=36436bc62a98f53e126ec02fe946337c4c766c3f;p=ghc-hetmet.git diff --git a/ghc/compiler/deSugar/DsExpr.lhs b/ghc/compiler/deSugar/DsExpr.lhs index ce5a9d8..e8e9e7b 100644 --- a/ghc/compiler/deSugar/DsExpr.lhs +++ b/ghc/compiler/deSugar/DsExpr.lhs @@ -7,16 +7,23 @@ module DsExpr ( dsExpr, dsLExpr, dsLocalBinds, dsValBinds, dsLit ) where #include "HsVersions.h" +#if defined(GHCI) && defined(BREAKPOINT) +import Foreign.StablePtr ( newStablePtr, castStablePtrToPtr ) +import GHC.Exts ( Ptr(..), Int(..), addr2Int# ) +import IOEnv ( ioToIOEnv ) +import PrelNames ( breakpointJumpName ) +import TysWiredIn ( unitTy ) +import TypeRep ( Type(..) ) +#endif - -import Match ( matchWrapper, matchSimply, matchSinglePat ) +import Match ( matchWrapper, matchSinglePat, matchEquations ) import MatchLit ( dsLit, dsOverLit ) -import DsBinds ( dsLHsBinds ) +import DsBinds ( dsLHsBinds, dsCoercion ) import DsGRHSs ( dsGuarded ) import DsListComp ( dsListComp, dsPArrComp ) import DsUtils ( mkErrorAppDs, mkStringExpr, mkConsExpr, mkNilExpr, extractMatchResult, cantFailMatchResult, matchCanFail, - mkCoreTupTy, selectSimpleMatchVarL, lookupEvidence ) + mkCoreTupTy, selectSimpleMatchVarL, lookupEvidence, selectMatchVar ) import DsArrows ( dsProcExpr ) import DsMonad @@ -26,7 +33,7 @@ import DsMeta ( dsBracket ) #endif import HsSyn -import TcHsSyn ( hsPatType ) +import TcHsSyn ( hsPatType, mkVanillaTuplePat ) -- NB: The desugarer, which straddles the source and Core worlds, sometimes -- needs to see source types (newtypes etc), and sometimes not @@ -60,21 +67,10 @@ import FastString %************************************************************************ %* * -\subsection{dsLet} + dsLocalBinds, dsValBinds %* * %************************************************************************ -@dsLet@ is a match-result transformer, taking the @MatchResult@ for the body -and transforming it into one for the let-bindings enclosing the body. - -This may seem a bit odd, but (source) let bindings can contain unboxed -binds like -\begin{verbatim} - C x# = e -\end{verbatim} -This must be transformed to a case expression and, if the type has -more than one constructor, may fail. - \begin{code} dsLocalBinds :: HsLocalBinds Id -> CoreExpr -> DsM CoreExpr dsLocalBinds EmptyLocalBinds body = return body @@ -101,44 +97,52 @@ ds_val_bind :: (RecFlag, LHsBinds Id) -> CoreExpr -> DsM CoreExpr -- We need to do a case right away, rather than building -- a tuple and doing selections. -- Silently ignore INLINE and SPECIALISE pragmas... -ds_val_bind (is_rec, hsbinds) body +ds_val_bind (NonRecursive, hsbinds) body | [L _ (AbsBinds [] [] exports binds)] <- bagToList hsbinds, - or [isUnLiftedType (idType g) | (_, g, _, _) <- exports] - = ASSERT (case is_rec of {NonRecursive -> True; other -> False}) - -- Unlifted bindings are always non-recursive - -- and are always a Fun or Pat monobind - -- - -- ToDo: in some bizarre case it's conceivable that there - -- could be dict binds in the 'binds'. (See the notes - -- below. Then pattern-match would fail. Urk.) - let + (L loc bind : null_binds) <- bagToList binds, + isBangHsBind bind + || isUnboxedTupleBind bind + || or [isUnLiftedType (idType g) | (_, g, _, _) <- exports] + = let body_w_exports = foldr bind_export body exports bind_export (tvs, g, l, _) body = ASSERT( null tvs ) bindNonRec g (Var l) body - - mk_error_app pat = mkErrorAppDs iRREFUT_PAT_ERROR_ID - (exprType body) - (showSDoc (ppr pat)) in - case bagToList binds of - [L loc (FunBind (L _ fun) _ matches _)] - -> putSrcSpanDs loc $ - matchWrapper (FunRhs (idName fun)) matches `thenDs` \ (args, rhs) -> + ASSERT (null null_binds) + -- Non-recursive, non-overloaded bindings only come in ones + -- ToDo: in some bizarre case it's conceivable that there + -- could be dict binds in the 'binds'. (See the notes + -- below. Then pattern-match would fail. Urk.) + putSrcSpanDs loc $ + case bind of + FunBind { fun_id = L _ fun, fun_matches = matches, fun_co_fn = co_fn } + -> matchWrapper (FunRhs (idName fun)) matches `thenDs` \ (args, rhs) -> ASSERT( null args ) -- Functions aren't lifted + ASSERT( isIdCoercion co_fn ) returnDs (bindNonRec fun rhs body_w_exports) - [L loc (PatBind pat grhss ty _)] - -> putSrcSpanDs loc $ - dsGuarded grhss ty `thenDs` \ rhs -> - mk_error_app pat `thenDs` \ error_expr -> - matchSimply rhs PatBindRhs pat body_w_exports error_expr + PatBind {pat_lhs = pat, pat_rhs = grhss, pat_rhs_ty = ty } + -> -- let C x# y# = rhs in body + -- ==> case rhs of C x# y# -> body + putSrcSpanDs loc $ + do { rhs <- dsGuarded grhss ty + ; let upat = unLoc pat + eqn = EqnInfo { eqn_wrap = idWrapper, eqn_pats = [upat], + eqn_rhs = cantFailMatchResult body_w_exports } + ; var <- selectMatchVar upat ty + ; result <- matchEquations PatBindRhs [var] [eqn] (exprType body) + ; return (scrungleMatch var rhs result) } other -> pprPanic "dsLet: unlifted" (pprLHsBinds hsbinds $$ ppr body) --- Ordinary case for bindings + +-- Ordinary case for bindings; none should be unlifted ds_val_bind (is_rec, binds) body - = dsLHsBinds binds `thenDs` \ prs -> - returnDs (Let (Rec prs) body) + = do { prs <- dsLHsBinds binds + ; ASSERT( not (any (isUnLiftedType . idType . fst) prs) ) + case prs of + [] -> return body + other -> return (Let (Rec prs) body) } -- Use a Rec regardless of is_rec. -- Why? Because it allows the binds to be all -- mixed up, which is what happens in one rare case @@ -149,6 +153,35 @@ ds_val_bind (is_rec, binds) body -- -- NB The previous case dealt with unlifted bindings, so we -- only have to deal with lifted ones now; so Rec is ok + +isUnboxedTupleBind :: HsBind Id -> Bool +isUnboxedTupleBind (PatBind { pat_rhs_ty = ty }) = isUnboxedTupleType ty +isUnboxedTupleBind other = False + +scrungleMatch :: Id -> CoreExpr -> CoreExpr -> CoreExpr +-- Returns something like (let var = scrut in body) +-- but if var is an unboxed-tuple type, it inlines it in a fragile way +-- Special case to handle unboxed tuple patterns; they can't appear nested +-- The idea is that +-- case e of (# p1, p2 #) -> rhs +-- should desugar to +-- case e of (# x1, x2 #) -> ... match p1, p2 ... +-- NOT +-- let x = e in case x of .... +-- +-- But there may be a big +-- let fail = ... in case e of ... +-- wrapping the whole case, which complicates matters slightly +-- It all seems a bit fragile. Test is dsrun013. + +scrungleMatch var scrut body + | isUnboxedTupleType (idType var) = scrungle body + | otherwise = bindNonRec var scrut body + where + scrungle (Case (Var x) bndr ty alts) + | x == var = Case scrut bndr ty alts + scrungle (Let binds body) = Let binds (scrungle body) + scrungle other = panic ("scrungleMatch: tuple pattern:\n" ++ showSDoc (ppr other)) \end{code} %************************************************************************ @@ -179,6 +212,36 @@ dsExpr expr@(HsLam a_Match) = matchWrapper LambdaExpr a_Match `thenDs` \ (binders, matching_code) -> returnDs (mkLams binders matching_code) +#if defined(GHCI) && defined(BREAKPOINT) +dsExpr (HsApp (L _ (HsApp realFun@(L _ (HsCoerce _ fun)) (L loc arg))) _) + | HsVar funId <- fun + , idName funId == breakpointJumpName + , ids <- filter (not.hasTyVar.idType) (extractIds arg) + = do dsWarn (text "Extracted ids:" <+> ppr ids <+> ppr (map idType ids)) + stablePtr <- ioToIOEnv $ newStablePtr ids + -- Yes, I know... I'm gonna burn in hell. + let Ptr addr# = castStablePtrToPtr stablePtr + funCore <- dsLExpr realFun + argCore <- dsLExpr (L loc (HsLit (HsInt (fromIntegral (I# (addr2Int# addr#)))))) + hvalCore <- dsLExpr (L loc (extractHVals ids)) + return ((funCore `App` argCore) `App` hvalCore) + where extractIds :: HsExpr Id -> [Id] + extractIds (HsApp fn arg) + | HsVar argId <- unLoc arg + = argId:extractIds (unLoc fn) + | TyApp arg' ts <- unLoc arg + , HsVar argId <- unLoc arg' + = error (showSDoc (ppr ts)) -- argId:extractIds (unLoc fn) + extractIds x = [] + extractHVals ids = ExplicitList unitTy (map (L loc . HsVar) ids) + hasTyVar (TyVarTy _) = True + hasTyVar (FunTy a b) = hasTyVar a || hasTyVar b + hasTyVar (NoteTy _ t) = hasTyVar t + hasTyVar (AppTy a b) = hasTyVar a || hasTyVar b + hasTyVar (TyConApp _ ts) = any hasTyVar ts + hasTyVar _ = False +#endif + dsExpr expr@(HsApp fun arg) = dsLExpr fun `thenDs` \ core_fun -> dsLExpr arg `thenDs` \ core_arg -> @@ -256,20 +319,10 @@ dsExpr (HsCoreAnn fs expr) = dsLExpr expr `thenDs` \ core_expr -> returnDs (Note (CoreNote $ unpackFS fs) core_expr) --- Special case to handle unboxed tuple patterns; they can't appear nested -dsExpr (HsCase discrim matches@(MatchGroup _ ty)) - | isUnboxedTupleType (funArgTy ty) - = dsLExpr discrim `thenDs` \ core_discrim -> - matchWrapper CaseAlt matches `thenDs` \ ([discrim_var], matching_code) -> - case matching_code of - Case (Var x) bndr ty alts | x == discrim_var -> - returnDs (Case core_discrim bndr ty alts) - _ -> panic ("dsLExpr: tuple pattern:\n" ++ showSDoc (ppr matching_code)) - dsExpr (HsCase discrim matches) = dsLExpr discrim `thenDs` \ core_discrim -> matchWrapper CaseAlt matches `thenDs` \ ([discrim_var], matching_code) -> - returnDs (bindNonRec discrim_var core_discrim matching_code) + returnDs (scrungleMatch discrim_var core_discrim matching_code) dsExpr (HsLet binds body) = dsLExpr body `thenDs` \ body' -> @@ -548,6 +601,8 @@ dsExpr (DictLam dictvars expr) dsExpr (DictApp expr dicts) -- becomes a curried application = dsLExpr expr `thenDs` \ core_expr -> returnDs (foldl (\f d -> f `App` (Var d)) core_expr dicts) + +dsExpr (HsCoerce co_fn e) = dsCoercion co_fn (dsExpr e) \end{code} Here is where we desugar the Template Haskell brackets and escapes @@ -718,7 +773,7 @@ dsMDo tbl stmts body result_ty mk_tup_pat :: [LPat Id] -> LPat Id mk_tup_pat [p] = p - mk_tup_pat ps = noLoc $ TuplePat ps Boxed + mk_tup_pat ps = noLoc $ mkVanillaTuplePat ps Boxed mk_ret_tup :: [LHsExpr Id] -> LHsExpr Id mk_ret_tup [r] = r