+ flattenMultipleAltCaseExpr ::
+ BindMap
+ -- A list of bindings in effect
+ -> SignalMap -- The scrutinee
+ -> CoreBndr -- The binder to bind the scrutinee to
+ -> [CoreAlt] -- The alternatives
+ -> FlattenState ( [SignalMap], SignalMap) -- See expandExpr
+
+ flattenMultipleAltCaseExpr binds scrut b (a:a':alts) = do
+ (args, res) <- flattenSingleAltCaseExpr binds scrut b a
+ (args', res') <- flattenMultipleAltCaseExpr binds scrut b (a':alts)
+ case a of
+ (DataAlt datacon, bind_vars, expr) -> do
+ if isDontCare datacon
+ then do
+ -- Completely skip the dontcare cases
+ return (args', res')
+ else do
+ lit <- dataConToLiteral datacon
+ -- The scrutinee must be a single signal
+ let Single sig = scrut
+ -- Create a signal that contains a boolean
+ boolsigid <- genSignalId SigInternal TysWiredIn.boolTy
+ let expr = EqLit sig lit
+ addDef (UncondDef (Right expr) boolsigid)
+ -- Create conditional assignments of either args/res or
+ -- args'/res based on boolsigid, and return the result.
+ our_args <- zipWithM (mkConditionals boolsigid) args args'
+ our_res <- mkConditionals boolsigid res res'
+ return (our_args, our_res)
+ otherwise ->
+ error $ "Case patterns other than data constructors not supported in case alternative: " ++ (showSDoc $ ppr a)
+ where
+ -- Select either the first or second signal map depending on the value
+ -- of the first argument (True == first map, False == second map)
+ mkConditionals :: SignalId -> SignalMap -> SignalMap -> FlattenState SignalMap
+ mkConditionals boolsigid true false = do
+ let zipped = zipValueMaps true false
+ Traversable.mapM (mkConditional boolsigid) zipped