-letderec, letderectop :: Transform
-letderec c expr@(Let (Rec binds) res) = case liftable of
- -- Nothing is liftable, just return
- [] -> return expr
- -- Something can be lifted, generate a new let expression
- _ -> change $ mkNonRecLets liftable (Let (Rec nonliftable) res)
- where
- -- Make a list of all the binders bound in this recursive let
- bndrs = map fst binds
- -- See which bindings are liftable
- (liftable, nonliftable) = List.partition canlift binds
- -- Any expression that does not use any of the binders in this recursive let
- -- can be lifted into a nonrec let. It can't use its own binder either,
- -- since that would mean the binding is self-recursive and should be in a
- -- single bind recursive let.
- canlift (bndr, e) = not $ expr_uses_binders bndrs e
--- Leave all other expressions unchanged
-letderec c expr = return expr
--- Perform this transform everywhere
-letderectop = everywhere ("letderec", letderec)
-
---------------------------------
--- let simplification
---------------------------------
-letsimpl, letsimpltop :: Transform
--- Don't simplify a let that evaluates to another let, since this is already
--- normal form (and would cause infinite loops with letflat below).
-letsimpl c expr@(Let _ (Let _ _)) = return expr
--- Put the "in ..." value of a let in its own binding, but not when the
--- expression is already a local variable, or not representable (to prevent loops with inlinenonrep).
-letsimpl c expr@(Let binds res) = do
- repr <- isRepr res
- local_var <- Trans.lift $ is_local_var res
- if not local_var && repr
- then do
- -- If the result is not a local var already (to prevent loops with
- -- ourselves), extract it.
- id <- Trans.lift $ mkBinderFor res "foo"
- change $ Let binds (Let (NonRec id res) (Var id))
- else
- -- If the result is already a local var, don't extract it.
- return expr