[project @ 2005-03-02 04:35:24 by simonpj]
[ghc-hetmet.git] / ghc / compiler / deSugar / MatchCon.lhs
index 62ed087..a84c96d 100644 (file)
@@ -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]