diff options
author | Adam Gundry <adam@well-typed.com> | 2014-11-20 13:32:26 +0000 |
---|---|---|
committer | Adam Gundry <adam@well-typed.com> | 2014-11-20 16:54:44 +0000 |
commit | 64cb49686457c233d0f58e5cfa324ad28a5453a3 (patch) | |
tree | 7037ca2fa8ad2702b1f2e73b7f3598a790afded4 /compiler/main/DynamicLoading.hs | |
parent | cce6318e8fdb086a8501a0c81ae1ee02eed67835 (diff) | |
download | haskell-64cb49686457c233d0f58e5cfa324ad28a5453a3.tar.gz |
Implement typechecker plugins
Summary:
See https://ghc.haskell.org/trac/ghc/wiki/Plugins/TypeChecker
This is based on work by Iavor Diatchki and Eric Seidel.
Test Plan: validate
Reviewers: simonpj, austin
Reviewed By: austin
Subscribers: gridaphobe, yav, thomie, carter
Differential Revision: https://phabricator.haskell.org/D489
Conflicts:
docs/users_guide/7.10.1-notes.xml
Diffstat (limited to 'compiler/main/DynamicLoading.hs')
-rw-r--r-- | compiler/main/DynamicLoading.hs | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/compiler/main/DynamicLoading.hs b/compiler/main/DynamicLoading.hs index 046d13cee5..95321cfb79 100644 --- a/compiler/main/DynamicLoading.hs +++ b/compiler/main/DynamicLoading.hs @@ -3,6 +3,9 @@ -- | Dynamically lookup up values from modules and loading them. module DynamicLoading ( #ifdef GHCI + -- * Loading plugins + loadPlugins, + -- * Force loading information forceLoadModuleInterfaces, forceLoadNameModuleInterface, @@ -25,13 +28,17 @@ import Finder ( findImportedModule, cannotFindModule ) import TcRnMonad ( initTcInteractive, initIfaceTcRn ) import LoadIface ( loadPluginInterface ) import RdrName ( RdrName, Provenance(..), ImportSpec(..), ImpDeclSpec(..) - , ImpItemSpec(..), mkGlobalRdrEnv, lookupGRE_RdrName, gre_name ) + , ImpItemSpec(..), mkGlobalRdrEnv, lookupGRE_RdrName + , gre_name, mkRdrQual ) +import OccName ( mkVarOcc ) import RnNames ( gresFromAvails ) import DynFlags +import Plugins ( Plugin, CommandLineOption ) +import PrelNames ( pluginTyConName ) import HscTypes import BasicTypes ( HValue ) -import TypeRep ( pprTyThingCategory ) +import TypeRep ( mkTyConTy, pprTyThingCategory ) import Type ( Type, eqType ) import TyCon ( TyCon ) import Name ( Name, nameModule_maybe ) @@ -48,6 +55,44 @@ import Data.Maybe ( mapMaybe ) import GHC.Exts ( unsafeCoerce# ) +loadPlugins :: HscEnv -> IO [(ModuleName, Plugin, [CommandLineOption])] +loadPlugins hsc_env + = do { plugins <- mapM (loadPlugin hsc_env) to_load + ; return $ map attachOptions $ to_load `zip` plugins } + where + dflags = hsc_dflags hsc_env + to_load = pluginModNames dflags + + attachOptions (mod_nm, plug) = (mod_nm, plug, options) + where + options = [ option | (opt_mod_nm, option) <- pluginModNameOpts dflags + , opt_mod_nm == mod_nm ] + +loadPlugin :: HscEnv -> ModuleName -> IO Plugin +loadPlugin hsc_env mod_name + = do { let plugin_rdr_name = mkRdrQual mod_name (mkVarOcc "plugin") + dflags = hsc_dflags hsc_env + ; mb_name <- lookupRdrNameInModuleForPlugins hsc_env mod_name + plugin_rdr_name + ; case mb_name of { + Nothing -> + throwGhcExceptionIO (CmdLineError $ showSDoc dflags $ hsep + [ ptext (sLit "The module"), ppr mod_name + , ptext (sLit "did not export the plugin name") + , ppr plugin_rdr_name ]) ; + Just name -> + + do { plugin_tycon <- forceLoadTyCon hsc_env pluginTyConName + ; mb_plugin <- getValueSafely hsc_env name (mkTyConTy plugin_tycon) + ; case mb_plugin of + Nothing -> + throwGhcExceptionIO (CmdLineError $ showSDoc dflags $ hsep + [ ptext (sLit "The value"), ppr name + , ptext (sLit "did not have the type") + , ppr pluginTyConName, ptext (sLit "as required")]) + Just plugin -> return plugin } } } + + -- | Force the interfaces for the given modules to be loaded. The 'SDoc' parameter is used -- for debugging (@-ddump-if-trace@) only: it is shown as the reason why the module is being loaded. forceLoadModuleInterfaces :: HscEnv -> SDoc -> [Module] -> IO () |