summaryrefslogtreecommitdiff
path: root/docs/comm/exts/th.html
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2006-04-07 02:05:11 +0000
committerSimon Marlow <simonmar@microsoft.com>2006-04-07 02:05:11 +0000
commit0065d5ab628975892cea1ec7303f968c3338cbe1 (patch)
tree8e2afe0ab48ee33cf95009809d67c9649573ef92 /docs/comm/exts/th.html
parent28a464a75e14cece5db40f2765a29348273ff2d2 (diff)
downloadhaskell-0065d5ab628975892cea1ec7303f968c3338cbe1.tar.gz
Reorganisation of the source tree
Most of the other users of the fptools build system have migrated to Cabal, and with the move to darcs we can now flatten the source tree without losing history, so here goes. The main change is that the ghc/ subdir is gone, and most of what it contained is now at the top level. The build system now makes no pretense at being multi-project, it is just the GHC build system. No doubt this will break many things, and there will be a period of instability while we fix the dependencies. A straightforward build should work, but I haven't yet fixed binary/source distributions. Changes to the Building Guide will follow, too.
Diffstat (limited to 'docs/comm/exts/th.html')
-rw-r--r--docs/comm/exts/th.html197
1 files changed, 197 insertions, 0 deletions
diff --git a/docs/comm/exts/th.html b/docs/comm/exts/th.html
new file mode 100644
index 0000000000..dbb168aa0e
--- /dev/null
+++ b/docs/comm/exts/th.html
@@ -0,0 +1,197 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
+ <title>The GHC Commentary - Template Haskell</title>
+ </head>
+
+ <body BGCOLOR="FFFFFF">
+ <h1>The GHC Commentary - Template Haskell</h1>
+ <p>
+ The Template Haskell (TH) extension to GHC adds a meta-programming
+ facility in which all meta-level code is executed at compile time. The
+ design of this extension is detailed in "Template Meta-programming for
+ Haskell", Tim Sheard and Simon Peyton Jones, <a
+ href="http://portal.acm.org/toc.cfm?id=581690&type=proceeding&coll=portal&dl=ACM&part=series&WantType=proceedings&idx=unknown&title=unknown">ACM
+ SIGPLAN 2002 Haskell Workshop,</a> 2002. However, some of the details
+ changed after the paper was published.
+ </p>
+
+ <h2>Meta Sugar</h2>
+ <p>
+ The extra syntax of TH (quasi-quote brackets, splices, and reification)
+ is handled in the module <a
+ href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/deSugar/DsMeta.hs"><code>DsMeta</code></a>.
+ In particular, the function <code>dsBracket</code> desugars the four
+ types of quasi-quote brackets (<code>[|...|]</code>,
+ <code>[p|...|]</code>, <code>[d|...|]</code>, and <code>[t|...|]</code>)
+ and <code>dsReify</code> desugars the three types of reification
+ operations (<code>reifyType</code>, <code>reifyDecl</code>, and
+ <code>reifyFixity</code>).
+ </p>
+
+ <h3>Desugaring of Quasi-Quote Brackets</h3>
+ <p>
+ A term in quasi-quote brackets needs to be translated into Core code
+ that, when executed, yields a <em>representation</em> of that term in
+ the form of the abstract syntax trees defined in <a
+ href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/libraries/template-haskell/Language/Haskell/TH/Syntax.hs"><code>Language.Haskell.TH.Syntax</code></a>.
+ Within <code>DsMeta</code>, this is achieved by four functions
+ corresponding to the four types of quasi-quote brackets:
+ <code>repE</code> (for <code>[|...|]</code>), <code>repP</code> (for
+ <code>[p|...|]</code>), <code>repTy</code> (for <code>[t|...|]</code>),
+ and <code>repTopDs</code> (for <code>[d|...|]</code>). All four of
+ these functions receive as an argument the GHC-internal Haskell AST of
+ the syntactic form that they quote (i.e., arguments of type <a
+ href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/hsSyn/HsExpr.lhs"><code>HsExpr</code></a><code>.HsExpr
+ Name</code>, <a href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/hsSyn/HsPat.lhs"><code>HsPat</code></a><code>.HsPat Name</code>,
+ <a
+ href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/hsSyn/HsTypes.lhs"><code>HsType</code></a><code>.HsType
+ Name</code>, and <a
+ href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/hsSyn/HsDecls.lhs"><code>HsDecls</code></a><code>.HsGroup
+ Name</code>, respectively).
+ </p>
+ <p>
+ To increase the static type safety in <code>DsMeta</code>, the functions
+ constructing representations do not just return plain values of type <a
+ href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/coreSyn/CoreSyn.lhs"><code>CoreSyn</code></a>
+ <code>.CoreExpr</code>; instead, <code>DsMeta</code> introduces a
+ parametrised type <code>Core</code> whose dummy type parameter indicates
+ the source-level type of the value computed by the corresponding Core
+ expression. All construction of Core fragments in <code>DsMeta</code>
+ is performed by smart constructors whose type signatures use the dummy
+ type parameter to constrain the contexts in which they are applicable.
+ For example, a function that builds a Core expression that evaluates to
+ a TH type representation, which has type
+ <code>Language.Haskell.TH.Syntax.Type</code>, would return a value of
+ type
+ </p>
+ <blockquote>
+ <pre>
+Core Language.Haskell.TH.Syntax.Type</pre>
+ </blockquote>
+
+ <h3>Desugaring of Reification Operators</h3>
+ <p>
+ The TH paper introduces four reification operators:
+ <code>reifyType</code>, <code>reifyDecl</code>,
+ <code>reifyFixity</code>, and <code>reifyLocn</code>. Of these,
+ currently (= 9 Nov 2002), only the former two are implemented.
+ </p>
+ <p>
+ The operator <code>reifyType</code> receives the name of a function or
+ data constructor as its argument and yields a representation of this
+ entity's type in the form of a value of type
+ <code>TH.Syntax.Type</code>. Similarly, <code>reifyDecl</code> receives
+ the name of a type and yields a representation of the type's declaration
+ as a value of type <code>TH.Syntax.Decl</code>. The name of the reified
+ entity is mapped to the GHC-internal representation of the entity by
+ using the function <code>lookupOcc</code> on the name.
+ </p>
+
+ <h3>Representing Binding Forms</h3>
+ <p>
+ Care needs to be taken when constructing TH representations of Haskell
+ terms that include binding forms, such as lambda abstractions or let
+ bindings. To avoid name clashes, fresh names need to be generated for
+ all defined identifiers. This is achieved via the routine
+ <code>DsMeta.mkGenSym</code>, which, given a <code>Name</code>, produces
+ a <code>Name</code> / <code>Id</code> pair (of type
+ <code>GenSymBind</code>) that associates the given <code>Name</code>
+ with a Core identifier that at runtime will be bound to a string that
+ contains the fresh name. Notice the two-level nature of this
+ arrangement. It is necessary, as the Core code that constructs the
+ Haskell term representation may be executed multiple types at runtime
+ and it must be ensured that different names are generated in each run.
+ </p>
+ <p>
+ Such fresh bindings need to be entered into the meta environment (of
+ type <a
+ href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/deSugar/DsMonad.lhs"><code>DsMonad</code></a><code>.DsMetaEnv</code>),
+ which is part of the state (of type <code>DsMonad.DsEnv</code>)
+ maintained in the desugarer monad (of type <code>DsMonad.DsM</code>).
+ This is done using the function <code>DsMeta.addBinds</code>, which
+ extends the current environment by a list of <code>GenSymBind</code>s
+ and executes a subcomputation in this extended environment. Names can
+ be looked up in the meta environment by way of the functions
+ <code>DsMeta.lookupOcc</code> and <code>DsMeta.lookupBinder</code>; more
+ details about the difference between these two functions can be found in
+ the next subsection.
+ </p>
+ <p>
+ NB: <code>DsMeta</code> uses <code>mkGenSym</code> only when
+ representing terms that may be embedded into a context where names can
+ be shadowed. For example, a lambda abstraction embedded into an
+ expression can potentially shadow names defined in the context it is
+ being embedded into. In contrast, this can never be the case for
+ top-level declarations, such as data type declarations; hence, the type
+ variables that a parametric data type declaration abstracts over are not
+ being gensym'ed. As a result, variables in defining positions are
+ handled differently depending on the syntactic construct in which they
+ appear.
+ </p>
+
+ <h3>Binders Versus Occurences</h3>
+ <p>
+ Name lookups in the meta environment of the desugarer use two functions
+ with slightly different behaviour, namely <code>DsMeta.lookupOcc</code>
+ and <code>lookupBinder</code>. The module <code>DsMeta</code> contains
+ the following explanation as to the difference of these functions:
+ </p>
+ <blockquote>
+ <pre>
+When we desugar [d| data T = MkT |]
+we want to get
+ Data "T" [] [Con "MkT" []] []
+and *not*
+ Data "Foo:T" [] [Con "Foo:MkT" []] []
+That is, the new data decl should fit into whatever new module it is
+asked to fit in. We do *not* clone, though; no need for this:
+ Data "T79" ....
+
+But if we see this:
+ data T = MkT
+ foo = reifyDecl T
+
+then we must desugar to
+ foo = Data "Foo:T" [] [Con "Foo:MkT" []] []
+
+So in repTopDs we bring the binders into scope with mkGenSyms and addBinds,
+but in dsReify we do not. And we use lookupOcc, rather than lookupBinder
+in repTyClD and repC.</pre>
+ </blockquote>
+ <p>
+ This implies that <code>lookupOcc</code>, when it does not find the name
+ in the meta environment, uses the function <code>DsMeta.globalVar</code>
+ to construct the <em>original name</em> of the entity (cf. the TH paper
+ for more details regarding original names). This name uniquely
+ identifies the entity in the whole program and is in scope
+ <em>independent</em> of whether the user name of the same entity is in
+ scope or not (i.e., it may be defined in a different module without
+ being explicitly imported) and has the form &lt;module&gt;:&lt;name&gt;.
+ <strong>NB:</strong> Incidentally, the current implementation of this
+ mechanisms facilitates breaking any abstraction barrier.
+ </p>
+
+ <h3>Known-key Names for Template Haskell</h3>
+ <p>
+ During the construction of representations, the desugarer needs to use a
+ large number of functions defined in the library
+ <code>Language.Haskell.TH.Syntax</code>. The names of these functions
+ need to be made available to the compiler in the way outlined <a
+ href="../the-beast/prelude.html">Primitives and the Prelude.</a>
+ Unfortunately, any change to <a
+ href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/prelude/PrelNames.lhs"><code>PrelNames</code></a>
+ triggers a significant amount of recompilation. Hence, the names needed
+ for TH are defined in <code>DsMeta</code> instead (at the end of the
+ module). All library functions needed by TH are contained in the name
+ set <code>DsMeta.templateHaskellNames</code>.
+ </p>
+
+ <p><small>
+<!-- hhmts start -->
+Last modified: Wed Nov 13 18:01:48 EST 2002
+<!-- hhmts end -->
+ </small>
+ </body>
+</html>