module Retrie.FreeVars
( FreeVars
, substFVs
, elemFVs
, capturesFVs
) where
import Data.Generics hiding (Fixity)
import Retrie.ExactPrint.Annotated
import Retrie.GHC
import Retrie.Quantifiers
import Retrie.Substitution
newtype FreeVars = FreeVars (OccEnv FastString)
emptyFVs :: FreeVars
emptyFVs = FreeVars emptyOccEnv
instance Semigroup FreeVars where
(<>) = mappend
instance Monoid FreeVars where
mempty = emptyFVs
mappend (FreeVars m1) (FreeVars m2) = FreeVars $ plusOccEnv m2 m1
instance Show FreeVars where
show (FreeVars m) = show (occEnvElts m)
substFVs :: Substitution -> FreeVars
substFVs = foldSubst (f . snd) emptyFVs
where
f (HoleExpr e) fvs = freeVars emptyQs (astA e) <> fvs
f (HoleRdr rdr) fvs = rdrFV rdr <> fvs
f _ fvs = fvs
capturesFVs :: (Data a, Typeable a) => Quantifiers -> [RdrName] -> a -> Bool
capturesFVs qs binders thing = any (`elemOccEnv` fvEnv) $ map occName binders
where
FreeVars fvEnv = freeVars qs thing
freeVars :: (Data a, Typeable a) => Quantifiers -> a -> FreeVars
freeVars qs = everything (<>) (mkQ emptyFVs fvsExpr `extQ` fvsType)
where
fvsExpr :: HsExpr GhcPs -> FreeVars
fvsExpr e
| Just (L _ rdr) <- varRdrName e
, not $ isQ rdr qs = rdrFV rdr
fvsExpr _ = emptyFVs
fvsType :: HsType GhcPs -> FreeVars
fvsType ty
| Just (L _ rdr) <- tyvarRdrName ty
, not $ isQ rdr qs = rdrFV rdr
fvsType _ = emptyFVs
elemFVs :: RdrName -> FreeVars -> Bool
elemFVs rdr (FreeVars m) = elemOccEnv (occName rdr) m
rdrFV :: RdrName -> FreeVars
rdrFV rdr = FreeVars $ unitOccEnv (occName rdr) (rdrFS rdr)