{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Language.Haskell.Refact.Utils.Query where
--This module contains functions that retrieve sections of the ast. It is fairly high level.

import qualified GHC as GHC
import Language.Haskell.Refact.Utils.Monad
import Language.Haskell.Refact.Utils.Synonyms
import Language.Haskell.Refact.Utils.Types
import Language.Haskell.Refact.Utils.TypeUtils
import Data.Generics as SYB
import GHC.SYB.Utils as SYB
import Control.Applicative
import FastString
import RdrName

--Takes a single match and returns a tuple containing the grhs and the pattern
--Assumptions:
  -- Only a single pattern will be returned. Which pattern is returned depends on the behaviour of SYB.something. 
getVarAndRHS :: GHC.Match GHC.RdrName (GHC.LHsExpr GHC.RdrName) -> RefactGhc (GHC.LPat GHC.RdrName, ParsedGRHSs)
getVarAndRHS match = do
  let (Just pat) = SYB.something (Nothing `SYB.mkQ` varPat) (GHC.m_pats match)
  return (pat , GHC.m_grhss match)
    where varPat lPat@(GHC.L _ (GHC.VarPat _ )) = Just lPat
          varPat _ = Nothing

--Looks up the function binding at the given position. Returns nothing if the position does not contain a binding.
getHsBind :: (Data a) => SimpPos -> a -> Maybe (GHC.HsBind GHC.RdrName)
getHsBind pos a =
  let rdrNm = locToRdrName pos a in
  case rdrNm of
  Nothing -> Nothing
  (Just (GHC.L _ rNm)) -> SYB.everythingStaged SYB.Parser (<|>) Nothing (Nothing `SYB.mkQ` isBind) a
    where
#if __GLASGOW_HASKELL__ <= 710
        isBind (bnd@(GHC.FunBind (GHC.L _ name) _ _ _ _ _) :: GHC.HsBind GHC.RdrName)
#else
        isBind (bnd@(GHC.FunBind (GHC.L _ name) _ _ _ _) :: GHC.HsBind GHC.RdrName)
#endif
            | name == rNm = (Just bnd)
        isBind _ = Nothing

--It's common to want to know if an expression is just a certain var
--This function takes a String of the var and returns true of the given expression represents that var
isHsVar :: String -> ParsedExpr -> Bool
#if __GLASGOW_HASKELL__ <= 710
isHsVar str (GHC.HsVar rNm) =
#else
isHsVar str (GHC.HsVar (GHC.L _ rNm)) =
#endif
  let nm = mkVarUnqual (fsLit str) in
    rNm == nm
isHsVar _ _ = False