<div dir="ltr">I&#39;d also be very happy with some plugin interface that allows us to use more GhcMake functionality from the GHC API. For GHCJS we would want to run our own (STG -&gt; JavaScript) code generator on sources that need to be recompiled instead of letting GHC run its pipeline. Do you think that&#39;s possible with your proposal?<div>
<br></div><div>luite</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Jun 6, 2013 at 10:13 PM, Simon Marlow <span dir="ltr">&lt;<a href="mailto:marlowsd@gmail.com" target="_blank">marlowsd@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">+1.  I don&#39;t have any comments on the technical issues I&#39;m afraid, but the more ways we can extend GHC without having to change it directly, the better.<br>

<br>
Cheers,<br>
        Simon<div><div class="h5"><br>
<br>
On 05/06/13 12:51, Edsko de Vries wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
Sorry for the earlier mishap, here&#39;s the full email.<br>
<br>
Hi all,<br>
<br>
The plugin mechanism gives access to the program in Core; this suffices<br>
for many but not quite all purposes. Tools that need access to the<br>
original AST can call typecheckModule directly, but of course this<br>
requires using the GHC API directly. Moreover, even when using the GHC<br>
API directly anyway (as in my case), it means that tools cannot take<br>
advantage of ghc&#39;s infrastructure for dependency tracking, recompiling<br>
only changed modules, etc.<br>
<br>
Hence it would be useful to have &quot;source plugins&quot;, which can be used<br>
both externally and when using ghc API (in the latter case I guess<br>
&quot;hooks&quot; would be the more appropriate terminology). Currently &quot;core<br>
plugins&quot; are recorded as part of DynFlags as<br>
<br>
     pluginModNames        :: [ModuleName],<br>
     pluginModNameOpts     :: [(ModuleName,String)],<br>
<br>
This makes sense when thinking of plugins only as an external mechanism,<br>
but is less convenient when using them as internal hooks, too. In my<br>
draft patch I introduce a new type &quot;HscPlugin&quot; (described shortly) and added<br>
<br>
     sourcePlugins         :: [HscPlugin],<br>
<br>
to DynFlags. HscPlugin is a record of a pair of functions; having the<br>
actual record here rather than  a module name means that these functions<br>
can have a non-empty closure, which is obviously convenient when using<br>
this as a hook rather than an external plugin.<br>
<br>
In my current version HscPlugin looks like<br>
<br>
     data HscPlugin = HscPlugin {<br>
         runHscPlugin :: forall m. MonadIO m<br>
                      =&gt; DynFlags<br>
                      -&gt; TcGblEnv<br>
                      -&gt; m TcGblEnv<br>
       , runHscQQ     :: forall m. MonadIO m<br>
                      =&gt; Env TcGblEnv TcLclEnv<br>
                      -&gt; HsQuasiQuote Name<br>
                      -&gt; m (HsQuasiQuote Name)<br>
       }<br>
<br>
runHscPlugin is the main function; it gets passed the TcGblEnv (which<br>
contains the type checked AST as its tcd_binds field) and gets a change<br>
to return it modified (we don&#39;t currently take advantage of that; I did<br>
that only to be in line with &quot;core plugins&quot;).<br>
<br>
Unfortunately, the typechecked AST is only a subset of the renamed AST<br>
(see<br>
<a href="http://www.haskell.org/pipermail/ghc-devs/2013-February/000540.html" target="_blank">http://www.haskell.org/<u></u>pipermail/ghc-devs/2013-<u></u>February/000540.html</a>).<br>
The TcGblEnv contains a  tcg_rn_decls field, which is a reference to the<br>
full renamed (as opposed to typechecked) AST, but by default this is not<br>
initialized: the typechecker only optionally retains the renamed AST,<br>
and this is hardcoded to by False. In my current patch I have changed<br>
this so that it&#39;s hard coded to be True; ideally this should become an<br>
option in DynFlags (more ideal still would be if the type checked AST<br>
would not lose any information).<br>
<br>
Unfortunately, even the renamer loses information: quasi-quotes get<br>
expanded during renaming and all evidence of that there was ever a<br>
quasi-quote there has disappeared when the renamer returns. For this<br>
reason, the HscPlugin type that I&#39;m using at the moment also has a hook<br>
for quasi-quotes.<br>
<br>
So what I have currently done is:<br>
<br></div></div>
 1. Introduced the above HscPlugin type and added a corresponding field<br>
    to DynFlags<br>
 2. Call runHscQQ in the renamer whenever a quasi-quote gets expanded.<br>
 3. Make sure that the typechecker passes the result of the renamer through.<br>
 4. Call runHscPlugin on the result of the typechecker.<div class="im"><br>
<br>
In my client code I then combine the information obtained from these<br>
three sources (2, 3, 4).<br>
<br>
The path of least resistance for me currently to submit this as a patch<br>
for ghc therefore be to submit a patch that does precisely what I<br>
described above, mutatis mutandis based on your feedback, except that I<br>
would add an option to add to DynFlags that would tell the type checker<br>
whether or not to pass the result of the renamer through, rather than<br>
hardcoding it.<br>
<br>
It is a little bit messy mostly because parts of the AST get lost along<br>
the way: quasi-quotes in the renamer, data type declarations and other<br>
things during type checking. A more ideal way, but also more time<br>
consuming, would be to change this so that the renamer leaves evidence<br>
of the quasi-quotes in the tree, and the type checker returns the entire<br>
tree type checked, rather than just a subset. I think that ultimately<br>
this is the better approach, at least for our purposes -- I&#39;m not sure<br>
about other tools, but since this would be a larger change that affects<br>
larger parts of the ghc pipeline I&#39;m not sure that I&#39;ll be able to do it.<br>
<br>
Any and all feedback on the above would be appreciated!<br>
<br>
Edsko<br>
<br>
<br></div>
______________________________<u></u>_________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/ghc-devs" target="_blank">http://www.haskell.org/<u></u>mailman/listinfo/ghc-devs</a><br>
<br>
</blockquote>
<br>
<br>
______________________________<u></u>_________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/ghc-devs" target="_blank">http://www.haskell.org/<u></u>mailman/listinfo/ghc-devs</a><br>
</blockquote></div><br></div>