|Version 1 (modified by nominolo, 3 years ago) (diff)|
GHC API Hooks
This document describes a proposal for a hooks interface to customise certain phases of GHC's source transformation facilities. A hook is simply a callback that is called at certain points in the program.
One option is to split GHC's stages into lots of small function calls and allow the user to wire these stages together as needed. Unfortunately, this is very difficult to do and wouldn't necessarily be very flexible since there are a number of expected invariants not encoded in the types.
Instead we identify "interesting" places inside the compiler and allow users of the GHC API to specify a call-back that gets invoked when execution reaches that place. For example, instead of calling typecheckRename function directly, we first look up whether there is a hook specified for and if so call that function instead. The hook may choose to perform its own renaming and type checking passes (unlikely) or call the GHC's typecheckRename function and inspect its output and generate additional files on disk.
The Hook datatype
Each hook has a potentially different type from all the other hooks. Additionally, we need to be able to communicate hooks to all the locations where they may be invoked. This is achieved by storing the list of hooks in the DynFlags. This, however, means that hooks cannot be defined as an ADT, as that would lead to huge cyclic imports (the data types used by the hooks will depend on DynFlags, but the DynFlags will depend on the hook data type. Instead we Hooks is an untyped key-value store. The keys are single constructor types and the Hooks map is indexed by their TypeRep. We recover the hook type via a type family: