+ let fw = \s -> E
+ in \x -> case x of
+ p -> fw
+ q -> \s -> E2
+ r -> fw
+
+Now we'll see that fw has arity 1, and will arity expand
+the \x to get what we want.
+
+\begin{code}
+-- mkWWargs is driven off the function type and arity.
+-- It chomps bites off foralls, arrows, newtypes
+-- and keeps repeating that until it's satisfied the supplied arity
+
+mkWWargs :: Type -> Arity
+ -> [Demand] -> Bool -> [Bool] -- Both these will in due course be derived
+ -- from the type. The [Bool] is True for a one-shot arg.
+ -- ** Both are infinite, extended with neutral values if necy **
+ -> UniqSM ([Var], -- Wrapper args
+ CoreExpr -> CoreExpr, -- Wrapper fn
+ CoreExpr -> CoreExpr, -- Worker fn
+ Type) -- Type of wrapper body
+
+mkWWargs fun_ty arity demands res_bot one_shots
+ | (res_bot || arity > 0) && (not (null tyvars) || n_arg_tys > 0)
+ -- If the function returns bottom, we feel free to
+ -- build lots of wrapper args:
+ -- \x. let v=E in \y. bottom
+ -- = \xy. let v=E in bottom
+ = getUniquesUs `thenUs` \ wrap_uniqs ->
+ let
+ val_args = zipWith4 mk_wrap_arg wrap_uniqs arg_tys demands one_shots
+ wrap_args = tyvars ++ val_args
+ in
+ mkWWargs new_fun_ty
+ (arity - n_args)
+ (drop n_args demands)
+ res_bot
+ (drop n_args one_shots) `thenUs` \ (more_wrap_args, wrap_fn_args, work_fn_args, res_ty) ->
+
+ returnUs (wrap_args ++ more_wrap_args,
+ mkLams wrap_args . wrap_fn_args,
+ work_fn_args . applyToVars wrap_args,
+ res_ty)
+ where
+ (tyvars, tau) = splitForAllTys fun_ty
+ (arg_tys, body_ty) = splitFunTys tau
+ n_arg_tys = length arg_tys
+ n_args | res_bot = n_arg_tys
+ | otherwise = arity `min` n_arg_tys
+ new_fun_ty | n_args == n_arg_tys = body_ty
+ | otherwise = mkFunTys (drop n_args arg_tys) body_ty
+
+mkWWargs fun_ty arity demands res_bot one_shots
+ = case splitNewType_maybe fun_ty of
+ Nothing -> returnUs ([], id, id, fun_ty)
+ Just rep_ty -> mkWWargs rep_ty arity demands res_bot one_shots `thenUs` \ (wrap_args, wrap_fn_args, work_fn_args, res_ty) ->
+ returnUs (wrap_args,
+ Note (Coerce fun_ty rep_ty) . wrap_fn_args,
+ work_fn_args . Note (Coerce rep_ty fun_ty),
+ res_ty)
+
+
+applyToVars :: [Var] -> CoreExpr -> CoreExpr
+applyToVars vars fn = mkVarApps fn vars
+
+mk_wrap_arg uniq ty dmd one_shot
+ = set_one_shot one_shot (setIdDemandInfo (mkSysLocal SLIT("w") uniq ty) dmd)
+ where
+ set_one_shot True id = setOneShotLambda id
+ set_one_shot False id = id
+\end{code}