+mkCoPrimCaseMatchResult :: Id -- Scrutinee
+ -> [(Literal, MatchResult)] -- Alternatives
+ -> MatchResult
+mkCoPrimCaseMatchResult var match_alts
+ = MatchResult CanFail mk_case
+ where
+ mk_case fail
+ = mapDs (mk_alt fail) match_alts `thenDs` \ alts ->
+ returnDs (Case (Var var) var ((DEFAULT, [], fail) : alts))
+
+ mk_alt fail (lit, MatchResult _ body_fn) = body_fn fail `thenDs` \ body ->
+ returnDs (LitAlt lit, [], body)
+
+
+mkCoAlgCaseMatchResult :: Id -- Scrutinee
+ -> [(DataCon, [CoreBndr], MatchResult)] -- Alternatives
+ -> MatchResult
+
+mkCoAlgCaseMatchResult var match_alts
+ | isNewTyCon tycon -- Newtype case; use a let
+ = ASSERT( null (tail match_alts) && null (tail arg_ids) )
+ mkCoLetsMatchResult [NonRec arg_id newtype_rhs] match_result
+
+ | otherwise -- Datatype case; use a case
+ = MatchResult fail_flag mk_case
+ where
+ -- Common stuff
+ scrut_ty = idType var
+ (tycon, _) = tcSplitTyConApp scrut_ty -- Newtypes must be opaque here
+
+ -- Stuff for newtype
+ (_, arg_ids, match_result) = head match_alts
+ arg_id = head arg_ids
+
+ newtype_rhs | isRecursiveTyCon tycon -- Recursive case; need a case
+ = Note (Coerce (idType arg_id) scrut_ty) (Var var)
+ | otherwise -- Normal case (newtype is transparent)
+ = Var var
+
+ -- Stuff for data types
+ data_cons = tyConDataCons tycon
+
+ match_results = [match_result | (_,_,match_result) <- match_alts]
+
+ fail_flag | exhaustive_case
+ = foldr1 orFail [can_it_fail | MatchResult can_it_fail _ <- match_results]
+ | otherwise
+ = CanFail
+
+ wild_var = mkWildId (idType var)
+ mk_case fail = mapDs (mk_alt fail) match_alts `thenDs` \ alts ->
+ returnDs (Case (Var var) wild_var (mk_default fail ++ alts))
+
+ mk_alt fail (con, args, MatchResult _ body_fn)
+ = body_fn fail `thenDs` \ body ->
+ getUniquesDs `thenDs` \ us ->
+ let
+ (binds, real_args) = rebuildConArgs args (dataConStrictMarks con) us
+ in
+ returnDs (DataAlt con, real_args, mkDsLets binds body)
+
+ mk_default fail | exhaustive_case = []
+ | otherwise = [(DEFAULT, [], fail)]
+
+ un_mentioned_constructors
+ = mkUniqSet data_cons `minusUniqSet` mkUniqSet [ con | (con, _, _) <- match_alts]
+ exhaustive_case = isEmptyUniqSet un_mentioned_constructors