Closed conal closed 10 years ago
Here's my current working version. Feedback, please.
-- | case foo of { ... ; p -> let x = u in v ; ... } ==>
-- let x = u in case foo of { ... ; p -> v ; ... }
--
-- where no variable in `p` occurs freely in `u`, and where `x` is not one of
-- the variables in `p`.
letFloatCaseAltR :: ReExpr
letFloatCaseAltR =
do Case scrut w ty alts <- id
(b,alts') <- letFloatOneAltR alts
return $ Let b (Case scrut w ty alts')
-- Perform the first safe let-floating out of a case alternative
letFloatOneAltR :: [CoreAlt] -> TransformH x (CoreBind,[CoreAlt])
letFloatOneAltR [] = fail "no alternatives safe to let-float"
letFloatOneAltR (alt:rest) =
(do (bind,alt') <- letFloatAltR alt
return (bind,alt':rest))
<+
(second (alt :) <$> letFloatOneAltR rest)
-- (p -> let bind in e) ==> (bind, p -> e)
letFloatAltR :: CoreAlt -> TransformH x (CoreBind,CoreAlt)
letFloatAltR (con,vs,Let bind@(NonRec x a) body)
| isEmptyVarSet (vset `intersectVarSet` freeVarsExpr a)
&& not (x `elemVarSet` vset)
= return (bind,(con,vs,body))
where
vset = mkVarSet vs
letFloatAltR _ = fail "letFloatAltR: not applicable"
-- TODO: consider variable occurrence conditions more carefully
I've added this in b799ed8bb5fee861cad0707a16bd9d37b8a22f87
Thanks for the starting point. I adapted your code in a couple ways:
Is there a
let-float
variation for when the let binding is in acase
alternative? Something like the following:where no variable in
p
occurs inu
and wherex
is not one of the variables inp
.If HERMIT doesn't have such a rewrite, is it because the need hasn't arisen?