X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FdeSugar%2FMatchCon.lhs;h=a84c96d198cc08fabf27dd60782ef06d9189ab45;hb=ed75b2fd12799f62ea76ae43ebaa46d04f70db3d;hp=62ed087648247219fded6b54aac75807c697586e;hpb=23f40f0e9be6d4aa5cf9ea31d73f4013f8e7b4bd;p=ghc-hetmet.git diff --git a/ghc/compiler/deSugar/MatchCon.lhs b/ghc/compiler/deSugar/MatchCon.lhs index 62ed087..a84c96d 100644 --- a/ghc/compiler/deSugar/MatchCon.lhs +++ b/ghc/compiler/deSugar/MatchCon.lhs @@ -22,7 +22,7 @@ import DsUtils import Id ( Id ) import Type ( Type ) import ListSetOps ( equivClassesByUniq ) -import SrcLoc ( unLoc ) +import SrcLoc ( unLoc, Located(..) ) import Unique ( Uniquable(..) ) import Outputable \end{code} @@ -86,12 +86,23 @@ matchConFamily (var:vars) ty eqns_info = let -- Sort into equivalence classes by the unique on the constructor -- All the EqnInfos should start with a ConPat - eqn_groups = equivClassesByUniq get_uniq eqns_info - get_uniq (EqnInfo { eqn_pats = ConPatOut data_con _ _ _ _ _ : _}) = getUnique data_con + groups = equivClassesByUniq get_uniq eqns_info + get_uniq (EqnInfo { eqn_pats = ConPatOut (L _ data_con) _ _ _ _ _ : _}) = getUnique data_con + + -- Get the wrapper from the head of each group. We're going to + -- use it as the pattern in this case expression, so we need to + -- ensure that any type variables it mentions in the pattern are + -- in scope. So we put its wrappers outside the case, and + -- zap the wrapper for it. + wraps :: [CoreExpr -> CoreExpr] + wraps = map (eqn_wrap . head) groups + + groups' = [ eqn { eqn_wrap = idWrapper } : eqns | eqn:eqns <- groups ] in -- Now make a case alternative out of each group - mappM (match_con vars ty) eqn_groups `thenDs` \ alts -> - returnDs (mkCoAlgCaseMatchResult var ty alts) + mappM (match_con vars ty) groups' `thenDs` \ alts -> + returnDs (adjustMatchResult (foldr (.) idWrapper wraps) $ + mkCoAlgCaseMatchResult var ty alts) \end{code} And here is the local function that does all the work. It is @@ -105,35 +116,28 @@ wouldn't). Cf.~@shift_lit_pats@ in @MatchLits@. \begin{code} match_con vars ty eqns = do { -- Make new vars for the con arguments; avoid new locals where possible - arg_vars <- selectMatchVars (map unLoc arg_pats1) arg_tys - - ; match_result <- match (arg_vars ++ vars) ty (shiftEqns eqns) - - ; binds <- mapM ds_binds [ bind | ConPatOut _ _ _ bind _ _ <- pats, - not (isEmptyLHsBinds bind) ] - - ; let match_result' = bindInMatchResult (line_up other_pats) $ - mkCoLetsMatchResult binds match_result - - ; return (data_con, tvs1 ++ dicts1 ++ arg_vars, match_result') } + arg_vars <- selectMatchVars (map unLoc arg_pats1) arg_tys + ; eqns' <- mapM shift eqns + ; match_result <- match (arg_vars ++ vars) ty eqns' + ; return (con, tvs1 ++ dicts1 ++ arg_vars, match_result) } where - pats@(pat1 : other_pats) = map firstPat eqns - ConPatOut data_con tvs1 dicts1 _ (PrefixCon arg_pats1) pat_ty = pat1 - - ds_binds bind = do { prs <- dsHsNestedBinds bind; return (Rec prs) } + ConPatOut (L _ con) tvs1 dicts1 _ (PrefixCon arg_pats1) pat_ty = firstPat (head eqns) - line_up pats - | null tvs1 && null dicts1 = [] -- Common case - | otherwise = [ pr | ConPatOut _ ts ds _ _ _ <- pats, - pr <- (ts `zip` tvs1) ++ (ds `zip` dicts1)] + shift eqn@(EqnInfo { eqn_wrap = wrap, + eqn_pats = ConPatOut _ tvs ds bind (PrefixCon arg_pats) _ : pats }) + = do { prs <- dsHsNestedBinds bind + ; return (eqn { eqn_wrap = wrap . wrapBinds (tvs `zip` tvs1) + . wrapBinds (ds `zip` dicts1) + . mkDsLet (Rec prs), + eqn_pats = map unLoc arg_pats ++ pats }) } -- Get the arg types, which we use to type the new vars -- to match on, from the "outside"; the types of pats1 may -- be more refined, and hence won't do - arg_tys = substTys (zipTopTvSubst (dataConTyVars data_con) inst_tys) - (dataConOrigArgTys data_con) - inst_tys | isVanillaDataCon data_con = tcTyConAppArgs pat_ty -- Newtypes opaque! - | otherwise = mkTyVarTys tvs1 + arg_tys = substTys (zipTopTvSubst (dataConTyVars con) inst_tys) + (dataConOrigArgTys con) + inst_tys | isVanillaDataCon con = tcTyConAppArgs pat_ty -- Newtypes opaque! + | otherwise = mkTyVarTys tvs1 \end{code} Note [Existentials in shift_con_pat]