GHC API: 查找范围内的所有函数(及其类型)
GHC API: Find all functions (and their types) in scope
我正在尝试列出(打印)给定模块范围内的所有函数(及其类型)。
例如,我有这个模块:
{-# LANGUAGE NoImplicitPrelude #-}
module Reverse where
import Prelude ((==), String)
myString :: String
myString = "string"
我正在尝试使用 GHC API (8.0.2),但我似乎无法找到存储我要查找的信息的位置。
我已经设法找到范围内的所有功能,(但不是他们的类型,)用这个代码:
import Data.IORef
import DynFlags
import GHC
import GHC.LanguageExtensions
import GHC.Paths (libdir)
import HscTypes
import NameEnv
import OccName
import Outputable
import RdrName
import TcRnTypes
main = runGhc (Just libdir) $ do
liftIO $ print sets
dflags <- getSessionDynFlags
let compdflags =
(foldl xopt_set dflags [Cpp, ImplicitPrelude, MagicHash])
setSessionDynFlags compdflags
target <- guessTarget "Reverse.hs" Nothing
setTargets [target]
load LoadAllTargets
modSum <- getModSummary $ mkModuleName "Reverse"
parsedModule <- parseModule modSum
tmod <- typecheckModule parsedModule
let (tcenv, moddets) = tm_internals_ tmod
printO $ map (map gre_name) $ occEnvElts $ tcg_rdr_env tcenv
printO
:: (GhcMonad m, Outputable a)
=> a -> m ()
printO a = do
dfs <- getProgramDynFlags
liftIO $ putStrLn $ showPpr dfs a
我得到这个输出:
[[String], [==], [myString]]
当然,这只是我需要的数据的一半。
GHC API 相当混乱,你必须习惯大量的缩写、类型同义词和风格各异的代码库,但是找到范围内所有内容的名称和类型应该是可能的。
否则,如果您打错字,GHC 无法告诉您您的函数不在范围内。
的确,一旦你对一个模块进行了类型检查,所有相关信息都是可用的。
首先,您需要函数的所有 Name
s,您可以使用以下代码获得:
parsedModule <- parseModule modSum
tmod <- typecheckModule parsedModule
let (tcenv, moddets) = tm_internals_ tmod
let names = concatMap (map gre_name) $ occEnvElts $ tcg_rdr_env tcenv
然后您需要查找 Names
以获得 TyThing
和 lookupName
。
你会得到一个 Maybe TyThing
(Nothing
如果 Name
没有找到),当名称引用一个函数时,TyThing
将是 AnId i
其中 i
是您要查找的内容。
Id
只是一个带有类型的名称。
然后,您可以使用 varType
.
获取类型
您可能会争辩说,所有这些类型都使这个问题变得更加困难,但它们使我能够在不查看代码且没有文档的情况下弄清楚我需要做什么。
我正在尝试列出(打印)给定模块范围内的所有函数(及其类型)。
例如,我有这个模块:
{-# LANGUAGE NoImplicitPrelude #-}
module Reverse where
import Prelude ((==), String)
myString :: String
myString = "string"
我正在尝试使用 GHC API (8.0.2),但我似乎无法找到存储我要查找的信息的位置。 我已经设法找到范围内的所有功能,(但不是他们的类型,)用这个代码:
import Data.IORef
import DynFlags
import GHC
import GHC.LanguageExtensions
import GHC.Paths (libdir)
import HscTypes
import NameEnv
import OccName
import Outputable
import RdrName
import TcRnTypes
main = runGhc (Just libdir) $ do
liftIO $ print sets
dflags <- getSessionDynFlags
let compdflags =
(foldl xopt_set dflags [Cpp, ImplicitPrelude, MagicHash])
setSessionDynFlags compdflags
target <- guessTarget "Reverse.hs" Nothing
setTargets [target]
load LoadAllTargets
modSum <- getModSummary $ mkModuleName "Reverse"
parsedModule <- parseModule modSum
tmod <- typecheckModule parsedModule
let (tcenv, moddets) = tm_internals_ tmod
printO $ map (map gre_name) $ occEnvElts $ tcg_rdr_env tcenv
printO
:: (GhcMonad m, Outputable a)
=> a -> m ()
printO a = do
dfs <- getProgramDynFlags
liftIO $ putStrLn $ showPpr dfs a
我得到这个输出:
[[String], [==], [myString]]
当然,这只是我需要的数据的一半。
GHC API 相当混乱,你必须习惯大量的缩写、类型同义词和风格各异的代码库,但是找到范围内所有内容的名称和类型应该是可能的。 否则,如果您打错字,GHC 无法告诉您您的函数不在范围内。
的确,一旦你对一个模块进行了类型检查,所有相关信息都是可用的。
首先,您需要函数的所有 Name
s,您可以使用以下代码获得:
parsedModule <- parseModule modSum
tmod <- typecheckModule parsedModule
let (tcenv, moddets) = tm_internals_ tmod
let names = concatMap (map gre_name) $ occEnvElts $ tcg_rdr_env tcenv
然后您需要查找 Names
以获得 TyThing
和 lookupName
。
你会得到一个 Maybe TyThing
(Nothing
如果 Name
没有找到),当名称引用一个函数时,TyThing
将是 AnId i
其中 i
是您要查找的内容。
Id
只是一个带有类型的名称。
然后,您可以使用 varType
.
您可能会争辩说,所有这些类型都使这个问题变得更加困难,但它们使我能够在不查看代码且没有文档的情况下弄清楚我需要做什么。