+ is_value_lam (Lam v e) -- Spot a value lambda, even if
+ | isId v = True -- it is inside a type lambda
+ | otherwise = is_value_lam e
+ is_value_lam other = False
+
+ -- Check for a constructor application
+ -- NB: this *precedes* the Var case, so that we catch nullary constrs
+argToPat in_scope con_env arg arg_occ
+ | Just (CV dc args) <- is_con_app_maybe con_env arg
+ , case arg_occ of
+ ScrutOcc _ -> True -- Used only by case scrutinee
+ BothOcc -> case arg of -- Used elsewhere
+ App {} -> True -- see Note [Reboxing]
+ other -> False
+ other -> False -- No point; the arg is not decomposed
+ = do { args' <- argsToPats in_scope con_env (args `zip` conArgOccs arg_occ dc)
+ ; return (True, mk_con_app dc (map snd args')) }
+
+ -- Check if the argument is a variable that
+ -- is in scope at the function definition site
+ -- It's worth specialising on this if
+ -- (a) it's used in an interesting way in the body
+ -- (b) we know what its value is
+argToPat in_scope con_env (Var v) arg_occ
+ | not (isLocalId v) || v `elemVarEnv` in_scope,
+ case arg_occ of { UnkOcc -> False; other -> True }, -- (a)
+ isValueUnfolding (idUnfolding v) -- (b)
+ = return (True, Var v)
+
+ -- Check for a variable bound inside the function.
+ -- Don't make a wild-card, because we may usefully share
+ -- e.g. f a = let x = ... in f (x,x)
+ -- NB: this case follows the lambda and con-app cases!!
+argToPat in_scope con_env (Var v) arg_occ
+ = return (False, Var v)
+
+ -- The default case: make a wild-card
+argToPat in_scope con_env arg arg_occ
+ = wildCardPat (exprType arg)
+
+wildCardPat :: Type -> UniqSM (Bool, CoreArg)
+wildCardPat ty = do { uniq <- getUniqueUs
+ ; let id = mkSysLocal FSLIT("sc") uniq ty
+ ; return (False, Var id) }
+
+argsToPats :: InScopeEnv -> ConstrEnv
+ -> [(CoreArg, ArgOcc)]
+ -> UniqSM [(Bool, CoreArg)]
+argsToPats in_scope con_env args
+ = mapUs do_one args
+ where
+ do_one (arg,occ) = argToPat in_scope con_env arg occ