{-# OPTIONS -Wall #-}

module Language.Haskell.HBB.ExprType (
    exprtype,
    exprtypeM,
    showExprTypeResult,
    Type
    ) where

import Language.Haskell.HBB.Internal.GHC
import Outputable
import GHC.Paths (libdir) -- GHC.Paths is available via cabal install ghc-paths
import GHC

-- | This function takes a filename and an expression and evaluates the type of
-- this expression in the context of the passed file. The result value is a
-- tuple where the first element is GHCs representation of the type and the
-- second one is the stringified version of the type.
--
-- The first two command line parameter is:
--
--  - The GHC options as string list (as they should appear on the command
--    line, e.g. @[\"-isrc\"]@)
exprtype :: [String] -> FilePath -> String -> IO (Type,String)
exprtype ghcOptions fn expr = 
    runGhcWithCmdLineFlags ghcOptions (Just libdir) $ exprtypeM fn expr

-- | This function creates a string of the result returned by exprtype or
-- exprtypeM.
--
-- The string has exactly the format that should be understood by text editors
-- that are using this mode.
showExprTypeResult :: (Type,String) -> String
showExprTypeResult = snd

-- | This is a variant of exprtype that runs within the GHC monad and therefore
-- allows a more fine-grained control over the behaviour of GHC.
exprtypeM :: GhcMonad m => FilePath -> String -> m (Type,String)
exprtypeM contextFile expr = do

    -- This function takes a file name and an expression (as string) and tries to
    -- get out the type of this expression in the context of the passed file.
    let getTypeOfExpr :: GhcMonad m => FilePath -> String -> m Type
        getTypeOfExpr filename e = do
            loadTargetsFromFilename          filename
            (modName,_) <- searchModGraphFor (Left filename)
            setContext [IIModule modName]
            exprType e

    updateDynFlagsToSuppressFileOutput
    ty   <- getTypeOfExpr contextFile expr
    flgs <- getSessionDynFlags
    let tyStr = showSDocForUser flgs neverQualify (pprParendType $ ty)
    return (ty,tyStr)