- shift eqn@(EqnInfo { eqn_pats = ConPatOut{ pat_tvs = tvs, pat_dicts = ds,
- pat_binds = bind, pat_args = args
- } : pats })
- = do { prs <- dsLHsBinds bind
- ; return (wrapBinds (tvs `zip` tvs1)
- . wrapBinds (ds `zip` dicts1)
- . mkDsLet (Rec prs),
- eqn { eqn_pats = conArgPats con1 arg_tys args ++ pats }) }
-
-conArgPats :: DataCon
- -> [Type] -- Instantiated argument types
+ match_group :: [Id] -> [(ConArgPats, EquationInfo)] -> DsM MatchResult
+ -- All members of the group have compatible ConArgPats
+ match_group arg_vars arg_eqn_prs
+ = do { (wraps, eqns') <- mapAndUnzipM shift arg_eqn_prs
+ ; let group_arg_vars = select_arg_vars arg_vars arg_eqn_prs
+ ; match_result <- match (group_arg_vars ++ vars) ty eqns'
+ ; return (adjustMatchResult (foldr1 (.) wraps) match_result) }
+
+ shift (_, eqn@(EqnInfo { eqn_pats = ConPatOut{ pat_tvs = tvs, pat_dicts = ds,
+ pat_binds = bind, pat_args = args
+ } : pats }))
+ = do { prs <- dsLHsBinds bind
+ ; return (wrapBinds (tvs `zip` tvs1)
+ . wrapBinds (ds `zip` dicts1)
+ . mkCoreLet (Rec prs),
+ eqn { eqn_pats = conArgPats arg_tys args ++ pats }) }
+
+ -- Choose the right arg_vars in the right order for this group
+ -- Note [Record patterns]
+ select_arg_vars arg_vars ((arg_pats, _) : _)
+ | RecCon flds <- arg_pats
+ , let rpats = rec_flds flds
+ , not (null rpats) -- Treated specially; cf conArgPats
+ = ASSERT2( length fields1 == length arg_vars,
+ ppr con1 $$ ppr fields1 $$ ppr arg_vars )
+ map lookup_fld rpats
+ | otherwise
+ = arg_vars
+ where
+ fld_var_env = mkNameEnv $ zipEqual "get_arg_vars" fields1 arg_vars
+ lookup_fld rpat = lookupNameEnv_NF fld_var_env
+ (idName (unLoc (hsRecFieldId rpat)))
+
+-----------------
+compatible_pats :: (ConArgPats,a) -> (ConArgPats,a) -> Bool
+-- Two constructors have compatible argument patterns if the number
+-- and order of sub-matches is the same in both cases
+compatible_pats (RecCon flds1, _) (RecCon flds2, _) = same_fields flds1 flds2
+compatible_pats (RecCon flds1, _) _ = null (rec_flds flds1)
+compatible_pats _ (RecCon flds2, _) = null (rec_flds flds2)
+compatible_pats _ _ = True -- Prefix or infix con
+
+same_fields :: HsRecFields Id (LPat Id) -> HsRecFields Id (LPat Id) -> Bool
+same_fields flds1 flds2
+ = all2 (\f1 f2 -> unLoc (hsRecFieldId f1) == unLoc (hsRecFieldId f2))
+ (rec_flds flds1) (rec_flds flds2)
+
+
+-----------------
+selectConMatchVars :: [Type] -> ConArgPats -> DsM [Id]
+selectConMatchVars arg_tys (RecCon {}) = newSysLocalsDs arg_tys
+selectConMatchVars _ (PrefixCon ps) = selectMatchVars (map unLoc ps)
+selectConMatchVars _ (InfixCon p1 p2) = selectMatchVars [unLoc p1, unLoc p2]
+
+conArgPats :: [Type] -- Instantiated argument types