Test Trac #9036
[ghc.git] / docs / comm / exts / th.html
1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
2 <html>
3 <head>
4 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
5 <title>The GHC Commentary - Template Haskell</title>
6 </head>
7
8 <body BGCOLOR="FFFFFF">
9 <h1>The GHC Commentary - Template Haskell</h1>
10 <p>
11 The Template Haskell (TH) extension to GHC adds a meta-programming
12 facility in which all meta-level code is executed at compile time. The
13 design of this extension is detailed in "Template Meta-programming for
14 Haskell", Tim Sheard and Simon Peyton Jones, <a
15 href="http://portal.acm.org/toc.cfm?id=581690&type=proceeding&coll=portal&dl=ACM&part=series&WantType=proceedings&idx=unknown&title=unknown">ACM
16 SIGPLAN 2002 Haskell Workshop,</a> 2002. However, some of the details
17 changed after the paper was published.
18 </p>
19
20 <h2>Meta Sugar</h2>
21 <p>
22 The extra syntax of TH (quasi-quote brackets, splices, and reification)
23 is handled in the module <a
24 href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/deSugar/DsMeta.hs"><code>DsMeta</code></a>.
25 In particular, the function <code>dsBracket</code> desugars the four
26 types of quasi-quote brackets (<code>[|...|]</code>,
27 <code>[p|...|]</code>, <code>[d|...|]</code>, and <code>[t|...|]</code>)
28 and <code>dsReify</code> desugars the three types of reification
29 operations (<code>reifyType</code>, <code>reifyDecl</code>, and
30 <code>reifyFixity</code>).
31 </p>
32
33 <h3>Desugaring of Quasi-Quote Brackets</h3>
34 <p>
35 A term in quasi-quote brackets needs to be translated into Core code
36 that, when executed, yields a <em>representation</em> of that term in
37 the form of the abstract syntax trees defined in <a
38 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>.
39 Within <code>DsMeta</code>, this is achieved by four functions
40 corresponding to the four types of quasi-quote brackets:
41 <code>repE</code> (for <code>[|...|]</code>), <code>repP</code> (for
42 <code>[p|...|]</code>), <code>repTy</code> (for <code>[t|...|]</code>),
43 and <code>repTopDs</code> (for <code>[d|...|]</code>). All four of
44 these functions receive as an argument the GHC-internal Haskell AST of
45 the syntactic form that they quote (i.e., arguments of type <a
46 href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/hsSyn/HsExpr.lhs"><code>HsExpr</code></a><code>.HsExpr
47 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>,
48 <a
49 href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/hsSyn/HsTypes.lhs"><code>HsType</code></a><code>.HsType
50 Name</code>, and <a
51 href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/hsSyn/HsDecls.lhs"><code>HsDecls</code></a><code>.HsGroup
52 Name</code>, respectively).
53 </p>
54 <p>
55 To increase the static type safety in <code>DsMeta</code>, the functions
56 constructing representations do not just return plain values of type <a
57 href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/coreSyn/CoreSyn.lhs"><code>CoreSyn</code></a>
58 <code>.CoreExpr</code>; instead, <code>DsMeta</code> introduces a
59 parametrised type <code>Core</code> whose dummy type parameter indicates
60 the source-level type of the value computed by the corresponding Core
61 expression. All construction of Core fragments in <code>DsMeta</code>
62 is performed by smart constructors whose type signatures use the dummy
63 type parameter to constrain the contexts in which they are applicable.
64 For example, a function that builds a Core expression that evaluates to
65 a TH type representation, which has type
66 <code>Language.Haskell.TH.Syntax.Type</code>, would return a value of
67 type
68 </p>
69 <blockquote>
70 <pre>
71 Core Language.Haskell.TH.Syntax.Type</pre>
72 </blockquote>
73
74 <h3>Desugaring of Reification Operators</h3>
75 <p>
76 The TH paper introduces four reification operators:
77 <code>reifyType</code>, <code>reifyDecl</code>,
78 <code>reifyFixity</code>, and <code>reifyLocn</code>. Of these,
79 currently (= 9 Nov 2002), only the former two are implemented.
80 </p>
81 <p>
82 The operator <code>reifyType</code> receives the name of a function or
83 data constructor as its argument and yields a representation of this
84 entity's type in the form of a value of type
85 <code>TH.Syntax.Type</code>. Similarly, <code>reifyDecl</code> receives
86 the name of a type and yields a representation of the type's declaration
87 as a value of type <code>TH.Syntax.Decl</code>. The name of the reified
88 entity is mapped to the GHC-internal representation of the entity by
89 using the function <code>lookupOcc</code> on the name.
90 </p>
91
92 <h3>Representing Binding Forms</h3>
93 <p>
94 Care needs to be taken when constructing TH representations of Haskell
95 terms that include binding forms, such as lambda abstractions or let
96 bindings. To avoid name clashes, fresh names need to be generated for
97 all defined identifiers. This is achieved via the routine
98 <code>DsMeta.mkGenSym</code>, which, given a <code>Name</code>, produces
99 a <code>Name</code> / <code>Id</code> pair (of type
100 <code>GenSymBind</code>) that associates the given <code>Name</code>
101 with a Core identifier that at runtime will be bound to a string that
102 contains the fresh name. Notice the two-level nature of this
103 arrangement. It is necessary, as the Core code that constructs the
104 Haskell term representation may be executed multiple types at runtime
105 and it must be ensured that different names are generated in each run.
106 </p>
107 <p>
108 Such fresh bindings need to be entered into the meta environment (of
109 type <a
110 href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/deSugar/DsMonad.lhs"><code>DsMonad</code></a><code>.DsMetaEnv</code>),
111 which is part of the state (of type <code>DsMonad.DsEnv</code>)
112 maintained in the desugarer monad (of type <code>DsMonad.DsM</code>).
113 This is done using the function <code>DsMeta.addBinds</code>, which
114 extends the current environment by a list of <code>GenSymBind</code>s
115 and executes a subcomputation in this extended environment. Names can
116 be looked up in the meta environment by way of the functions
117 <code>DsMeta.lookupOcc</code> and <code>DsMeta.lookupBinder</code>; more
118 details about the difference between these two functions can be found in
119 the next subsection.
120 </p>
121 <p>
122 NB: <code>DsMeta</code> uses <code>mkGenSym</code> only when
123 representing terms that may be embedded into a context where names can
124 be shadowed. For example, a lambda abstraction embedded into an
125 expression can potentially shadow names defined in the context it is
126 being embedded into. In contrast, this can never be the case for
127 top-level declarations, such as data type declarations; hence, the type
128 variables that a parametric data type declaration abstracts over are not
129 being gensym'ed. As a result, variables in defining positions are
130 handled differently depending on the syntactic construct in which they
131 appear.
132 </p>
133
134 <h3>Binders Versus Occurrences</h3>
135 <p>
136 Name lookups in the meta environment of the desugarer use two functions
137 with slightly different behaviour, namely <code>DsMeta.lookupOcc</code>
138 and <code>lookupBinder</code>. The module <code>DsMeta</code> contains
139 the following explanation as to the difference of these functions:
140 </p>
141 <blockquote>
142 <pre>
143 When we desugar [d| data T = MkT |]
144 we want to get
145 Data "T" [] [Con "MkT" []] []
146 and *not*
147 Data "Foo:T" [] [Con "Foo:MkT" []] []
148 That is, the new data decl should fit into whatever new module it is
149 asked to fit in. We do *not* clone, though; no need for this:
150 Data "T79" ....
151
152 But if we see this:
153 data T = MkT
154 foo = reifyDecl T
155
156 then we must desugar to
157 foo = Data "Foo:T" [] [Con "Foo:MkT" []] []
158
159 So in repTopDs we bring the binders into scope with mkGenSyms and addBinds,
160 but in dsReify we do not. And we use lookupOcc, rather than lookupBinder
161 in repTyClD and repC.</pre>
162 </blockquote>
163 <p>
164 This implies that <code>lookupOcc</code>, when it does not find the name
165 in the meta environment, uses the function <code>DsMeta.globalVar</code>
166 to construct the <em>original name</em> of the entity (cf. the TH paper
167 for more details regarding original names). This name uniquely
168 identifies the entity in the whole program and is in scope
169 <em>independent</em> of whether the user name of the same entity is in
170 scope or not (i.e., it may be defined in a different module without
171 being explicitly imported) and has the form &lt;module&gt;:&lt;name&gt;.
172 <strong>NB:</strong> Incidentally, the current implementation of this
173 mechanisms facilitates breaking any abstraction barrier.
174 </p>
175
176 <h3>Known-key Names for Template Haskell</h3>
177 <p>
178 During the construction of representations, the desugarer needs to use a
179 large number of functions defined in the library
180 <code>Language.Haskell.TH.Syntax</code>. The names of these functions
181 need to be made available to the compiler in the way outlined <a
182 href="../the-beast/prelude.html">Primitives and the Prelude.</a>
183 Unfortunately, any change to <a
184 href="http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/prelude/PrelNames.lhs"><code>PrelNames</code></a>
185 triggers a significant amount of recompilation. Hence, the names needed
186 for TH are defined in <code>DsMeta</code> instead (at the end of the
187 module). All library functions needed by TH are contained in the name
188 set <code>DsMeta.templateHaskellNames</code>.
189 </p>
190
191 <p><small>
192 <!-- hhmts start -->
193 Last modified: Wed Nov 13 18:01:48 EST 2002
194 <!-- hhmts end -->
195 </small>
196 </body>
197 </html>