--- this rather ugly function converts the unpacked data con arguments back into
--- their packed form. It is almost the same as the version in DsUtils, except that
--- we use template locals here rather than newDsId (ToDo: merge these).
-
-rebuildConArgs
- :: DataCon -- the con we're matching on
- -> [Id] -- the source-level args
- -> [StrictnessMark] -- the strictness annotations (per-arg)
- -> CoreExpr -- the body
- -> Int -- template local
- -> (CoreExpr, [Id])
-
-rebuildConArgs con [] stricts body i = (body, [])
-rebuildConArgs con (arg:args) stricts body i | isTyVar arg
- = let (body', args') = rebuildConArgs con args stricts body i
- in (body',arg:args')
-rebuildConArgs con (arg:args) (str:stricts) body i
- = case maybeMarkedUnboxed str of
- Just (pack_con1, _) ->
- case splitProductType_maybe (idType arg) of
- Just (_, tycon_args, pack_con, con_arg_tys) ->
- ASSERT( pack_con == pack_con1 )
- let unpacked_args = zipWith mkTemplateLocal [i..] con_arg_tys
- (body', real_args) = rebuildConArgs con args stricts body
- (i + length con_arg_tys)
- in
- (
- Let (NonRec arg (mkConApp pack_con
- (map Type tycon_args ++
- map Var unpacked_args))) body',
- unpacked_args ++ real_args
- )
-
- _ -> let (body', args') = rebuildConArgs con args stricts body i
- in (body', arg:args')
+-- (mkReboxingAlt us con xs rhs) basically constructs the case
+-- alternative (con, xs, rhs)
+-- but it does the reboxing necessary to construct the *source*
+-- arguments, xs, from the representation arguments ys.
+-- For example:
+-- data T = MkT !(Int,Int) Bool
+--
+-- mkReboxingAlt MkT [x,b] r
+-- = (DataAlt MkT, [y::Int,z::Int,b], let x = (y,z) in r)
+--
+-- mkDataAlt should really be in DataCon, but it can't because
+-- it manipulates CoreSyn.
+
+mkReboxingAlt
+ :: [Unique] -- Uniques for the new Ids
+ -> DataCon
+ -> [Var] -- Source-level args
+ -> CoreExpr -- RHS
+ -> CoreAlt
+
+mkReboxingAlt us con args rhs
+ | not (any isMarkedUnboxed stricts)
+ = (DataAlt con, args, rhs)
+
+ | otherwise
+ = let
+ (binds, args') = go args stricts us
+ in
+ (DataAlt con, args', mkLets binds rhs)
+
+ where
+ stricts = dataConStrictMarks con
+
+ go [] stricts us = ([], [])
+
+ -- Type variable case
+ go (arg:args) stricts us
+ | isTyVar arg
+ = let (binds, args') = go args stricts us
+ in (binds, arg:args')
+
+ -- Term variable case
+ go (arg:args) (str:stricts) us
+ | isMarkedUnboxed str
+ = let
+ (_, tycon_args, pack_con, con_arg_tys)
+ = splitProductType "mkReboxingAlt" (idType arg)
+
+ unpacked_args = zipWith (mkSysLocal FSLIT("rb")) us con_arg_tys
+ (binds, args') = go args stricts (dropList con_arg_tys us)
+ con_app = mkConApp pack_con (map Type tycon_args ++ map Var unpacked_args)
+ in
+ (NonRec arg con_app : binds, unpacked_args ++ args')
+
+ | otherwise
+ = let (binds, args') = go args stricts us
+ in (binds, arg:args')