-- | Generate a new name for the provided binding and run the inner
-- computation with that name in scope to replace the provided binding
-- Returns both the generated binding and the result of the inner
-- computation
--
-- Passing in the computation which is to be executed in the modified
-- environment makes this function a bit harder to use (or rather the
-- code using it less readable) because it does a lot of passing
-- functions as arguments, however it very nicely encapsulates the
-- scope changes which means they will never leak from where they are
-- supposed to be applied
ssaRename ::
       (MonadGenBnd m, MonadReader LocalScope m)
    => Binding
    -> (Binding -> m a)
    -> m a
ssaRename oldBnd cont = do
    newBnd <- generateBindingWith oldBnd
    local (HM.insert oldBnd newBnd) $ cont newBnd
ssaRename ::
       (MonadGenBnd m, MonadReader LocalScope m)
    => Binding
    -> (Binding -> m a)
    -> m a
ssaRename oldBnd cont = do
    newBnd <- generateBindingWith oldBnd
    local (HM.insert oldBnd newBnd) $ cont newBnd
ssaRename oldBnd cont = do
    newBnd <- generateBindingWith oldBnd
    local (HM.insert oldBnd newBnd) $ cont newBnd