+ -- go_lam tries eta reduction
+ go_lam bs' subst (Lam b e)
+ = go_lam (b':bs') subst' e
+ where
+ (subst', b') = subst_opt_bndr subst b
+ go_lam bs' subst e
+ | Just etad_e <- tryEtaReduce bs e' = etad_e
+ | otherwise = mkLams bs e'
+ where
+ bs = reverse bs'
+ e' = simple_opt_expr subst e
+
+----------------------
+-- simple_app collects arguments for beta reduction
+simple_app :: Subst -> InExpr -> [OutExpr] -> CoreExpr
+simple_app subst (App e1 e2) as
+ = simple_app subst e1 (simple_opt_expr subst e2 : as)
+simple_app subst (Lam b e) (a:as)
+ = case maybe_substitute subst b a of
+ Just ext_subst -> simple_app ext_subst e as
+ Nothing -> Let (NonRec b2 a) (simple_app subst' e as)
+ where
+ (subst', b') = subst_opt_bndr subst b
+ b2 = add_info subst' b b'
+simple_app subst e as
+ = foldl App (simple_opt_expr subst e) as
+
+----------------------
+simple_opt_bind :: Subst -> CoreBind -> (Subst, Maybe CoreBind)
+simple_opt_bind subst (Rec prs)
+ = (subst'', Just (Rec (reverse rev_prs')))
+ where
+ (subst', bndrs') = subst_opt_bndrs subst (map fst prs)
+ (subst'', rev_prs') = foldl do_pr (subst', []) (prs `zip` bndrs')
+ do_pr (subst, prs) ((b,r), b')
+ = case maybe_substitute subst b r2 of
+ Just subst' -> (subst', prs)
+ Nothing -> (subst, (b2,r2):prs)
+ where
+ b2 = add_info subst b b'
+ r2 = simple_opt_expr subst r
+
+simple_opt_bind subst (NonRec b r)
+ = case maybe_substitute subst b r' of
+ Just ext_subst -> (ext_subst, Nothing)
+ Nothing -> (subst', Just (NonRec b2 r'))
+ where
+ r' = simple_opt_expr subst r
+ (subst', b') = subst_opt_bndr subst b
+ b2 = add_info subst' b b'
+
+----------------------
+maybe_substitute :: Subst -> InVar -> OutExpr -> Maybe Subst
+ -- (maybe_substitute subst in_var out_rhs)
+ -- either extends subst with (in_var -> out_rhs)
+ -- or returns Nothing
+maybe_substitute subst b r
+ | Type ty <- r -- let a::* = TYPE ty in <body>
+ = ASSERT( isTyCoVar b )
+ Just (extendTvSubst subst b ty)
+
+ | isId b -- let x = e in <body>
+ , safe_to_inline (idOccInfo b)
+ , isAlwaysActive (idInlineActivation b) -- Note [Inline prag in simplOpt]
+ , not (isStableUnfolding (idUnfolding b))
+ , not (isExportedId b)
+ = Just (extendIdSubst subst b r)
+
+ | otherwise
+ = Nothing
+ where