{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}
module Retrie.Subst (subst) where
import Control.Monad.Writer.Strict
import Data.Generics
import Retrie.Context
import Retrie.ExactPrint
import Retrie.Expr
import Retrie.GHC
import Retrie.Substitution
import Retrie.SYB
import Retrie.Types
subst
:: (MonadIO m, Data ast)
=> Substitution
-> Context
-> ast
-> TransformT m ast
subst sub ctxt =
everywhereMWithContextBut bottomUp (const False) updateContext f ctxt'
where
ctxt' = ctxt { ctxtSubst = Just sub }
f c =
mkM (substExpr c)
`extM` substPat c
`extM` substType c
`extM` substHsMatchContext c
`extM` substBind c
lookupHoleVar :: RdrName -> Context -> Maybe HoleVal
lookupHoleVar rdr ctxt = do
sub <- ctxtSubst ctxt
lookupSubst (rdrFS rdr) sub
substExpr
:: Monad m
=> Context
-> LHsExpr GhcPs
-> TransformT m (LHsExpr GhcPs)
#if __GLASGOW_HASKELL__ < 806
substExpr ctxt e@(L l1 (HsVar (L l2 v))) =
#else
substExpr ctxt e@(L l1 (HsVar x (L l2 v))) =
#endif
case lookupHoleVar v ctxt of
Just (HoleExpr eA) -> do
e' <- graftA (unparen <$> eA)
comments <- hasComments e'
unless comments $ transferEntryDPT e e'
transferAnnsT isComma e e'
parenify ctxt e'
Just (HoleRdr rdr) ->
#if __GLASGOW_HASKELL__ < 806
return $ L l1 $ HsVar $ L l2 rdr
#else
return $ L l1 $ HsVar x $ L l2 rdr
#endif
_ -> return e
substExpr _ e = return e
substPat
:: Monad m
=> Context
-> LPat GhcPs
-> TransformT m (LPat GhcPs)
#if __GLASGOW_HASKELL__ < 806
substPat ctxt p@(L l1 (VarPat (L l2 v))) =
#elif __GLASGOW_HASKELL__ < 808
substPat ctxt p@(L l1 (VarPat x (L l2 v))) =
#else
substPat ctxt (dL -> p@(L l1 (VarPat x (dL -> L l2 v)))) =
fmap composeSrcSpan $
#endif
case lookupHoleVar v ctxt of
Just (HolePat pA) -> do
p' <- graftA pA
transferEntryAnnsT isComma p p'
return p'
Just (HoleRdr rdr) ->
#if __GLASGOW_HASKELL__ < 806
return $ L l1 $ VarPat $ L l2 rdr
#else
return $ L l1 $ VarPat x $ L l2 rdr
#endif
_ -> return p
substPat _ p = return p
substType
:: Monad m
=> Context
-> LHsType GhcPs
-> TransformT m (LHsType GhcPs)
substType ctxt ty
| Just (L _ v) <- tyvarRdrName (unLoc ty)
, Just (HoleType tyA) <- lookupHoleVar v ctxt = do
ty' <- graftA (unparenT <$> tyA)
transferEntryAnnsT isComma ty ty'
parenifyT ctxt ty'
substType _ ty = return ty
substHsMatchContext
:: Monad m
=> Context
-> HsMatchContext RdrName
-> TransformT m (HsMatchContext RdrName)
substHsMatchContext ctxt (FunRhs (L l v) f s)
| Just (HoleRdr rdr) <- lookupHoleVar v ctxt =
return $ FunRhs (L l rdr) f s
substHsMatchContext _ other = return other
substBind
:: Monad m
=> Context
-> HsBind GhcPs
-> TransformT m (HsBind GhcPs)
substBind ctxt fb@FunBind{}
| L l v <- fun_id fb
, Just (HoleRdr rdr) <- lookupHoleVar v ctxt =
return fb { fun_id = L l rdr }
substBind _ other = return other