hermit-0.1.1.0: src/Language/HERMIT/Primitive/Common.hs
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances, FlexibleContexts, TupleSections #-}
-- | Note: this module should NOT export externals. It is for common
-- transformations needed by the other primitive modules.
module Language.HERMIT.Primitive.Common
( altFreeVarsT
, bindings
, bindingVarsT
, caseAltVarsT
, caseBinderVarT
, letVarsT
, wrongExprForm
) where
import GhcPlugins
import Control.Arrow
import Data.List
import Data.Monoid
import Language.HERMIT.Kure
import Language.HERMIT.Primitive.GHC
class BindEnv a where
bindings :: a -> [Id]
-- | All the identifiers bound in this binding group.
instance BindEnv CoreBind where
bindings (NonRec b _) = [b]
bindings (Rec bs) = map fst bs
instance BindEnv CoreAlt where
bindings (_,vs,_) = vs
instance BindEnv CoreExpr where
bindings (Lam b _) = [b]
bindings (Let bs _) = bindings bs
bindings (Case _ sc _ alts) = sc : (nub (concat (map bindings alts)))
bindings _ = []
instance BindEnv CoreProgram where
bindings prog = nub (concat (map bindings prog))
instance BindEnv CoreDef where
bindings (Def b _) = [b]
bindingVarsT :: TranslateH Core [Var]
bindingVarsT = translate $ \ c core -> case core of
ModGutsCore _ -> fail "Cannot get binding vars at topmost level"
ProgramCore x -> apply (promoteT ((arr bindings) :: TranslateH CoreProgram [Var])) c x
BindCore x -> apply (promoteT ((arr bindings) :: TranslateH CoreBind [Var])) c x
DefCore x -> apply (promoteT ((arr bindings) :: TranslateH CoreDef [Var])) c x
ExprCore x -> apply (promoteT ((arr bindings) :: TranslateH CoreExpr [Var])) c x
AltCore x -> apply (promoteT ((arr bindings) :: TranslateH CoreAlt [Var])) c x
-- TODO. Isn't there a better way to handle this ?
-- Although the work of this Translate is handled by bindingVarsT
-- This implementation fails for any expression that is not a Let.
-- This specific argument matching is required where it is used in Local/Let.hs and Local/Case.hs
letVarsT :: TranslateH CoreExpr [Var]
letVarsT = do Let bs _ <- idR
return (bindings bs)
-- | List of the list of Ids bound by each case alternative
caseAltVarsT :: TranslateH CoreExpr [[Id]]
caseAltVarsT = caseT mempty (const (extractT bindingVarsT)) $ \ () _ _ vs -> vs
-- | List of the list of Ids bound by each case alternative, including the Case binder in each list
caseAltVarsWithBinderT :: TranslateH CoreExpr [[Id]]
caseAltVarsWithBinderT = caseT mempty (const (extractT bindingVarsT)) $ \ () v _ vs -> map (v:) vs
-- | list containing the single Id of the case binder
caseBinderVarT :: TranslateH CoreExpr [Id]
caseBinderVarT = setFailMsg "Not a Case expression." $
do Case _ b _ _ <- idR
return [b]
-- | Free variables for a CoreAlt, returns a function, which accepts
-- the coreBndr name, before giving a result.
-- This is so we can use this with congruence combinators:
--
-- caseT id (const altFreeVarsT) $ \ _ bndr _ fs -> [ f bndr | f <- fs ]
altFreeVarsT :: TranslateH CoreAlt (Id -> [Var])
altFreeVarsT = altT freeVarsT $ \ _con ids frees coreBndr -> nub frees \\ nub (coreBndr : ids)
------------------------------------------------------------------------------
wrongExprForm :: String -> String
wrongExprForm form = "Expression does not have the form: " ++ form
------------------------------------------------------------------------------