summaryrefslogtreecommitdiff
path: root/docs/comm/the-beast/coding-style.html
blob: 41347c69022ce2c0916da0ec6902bfe4a41e2dc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
<!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 - Coding Style Guidelines</title>
  </head>

  <body BGCOLOR="FFFFFF">
    <h1>The GHC Commentary - Coding Style Guidelines</h1>
    
    <p>This is a rough description of some of the coding practices and
    style that we use for Haskell code inside <tt>ghc/compiler</tt>.

    <p>The general rule is to stick to the same coding style as is
    already used in the file you're editing.  If you must make
    stylistic changes, commit them separately from functional changes,
    so that someone looking back through the change logs can easily
    distinguish them.

    <h2>To literate or not to literate?</h2>

    <p>In GHC we use a mixture of literate (<tt>.lhs</tt>) and
    non-literate (<tt>.hs</tt>) source.  I (Simon M.) prefer to use
    non-literate style, because I think the
    <tt>\begin{code}..\end{code}</tt> clutter up the source too much,
    and I like to use Haddock-style comments (we haven't tried
    processing the whole of GHC with Haddock yet, though).

    <h2>To CPP or not to CPP?</h2>

    <p>We pass all the compiler sources through CPP.  The
    <tt>-cpp</tt> flag is always added by the build system.  

    <p>The following CPP symbols are used throughout the compiler:
    
    <dl>
      <dt><tt>DEBUG</tt></dt>

      <dd>Used to enables extra checks and debugging output in the
      compiler.  The <tt>ASSERT</tt> macro (see <tt>HsVersions.h</tt>)
      provides assertions which disappear when <tt>DEBUG</tt> is not
      defined.

      <p>All debugging output should be placed inside <tt>#ifdef
      DEBUG</tt>; we generally use this to provide warnings about
      strange cases and things that might warrant investigation.  When
      <tt>DEBUG</tt> is off, the compiler should normally be silent
      unless something goes wrong (exception when the verbosity level
      is greater than zero).

      <p>A good rule of thumb is that <tt>DEBUG</tt> shouldn't add
      more than about 10-20% to the compilation time.  This is the case
      at the moment.  If it gets too expensive, we won't use it.  For
      more expensive runtime checks, consider adding a flag - see for
      example <tt>-dcore-lint</tt>.
      </dd>

      <dt><tt>GHCI</tt></dt>
      
      <dd>Enables GHCi support, including the byte code generator and
      interactive user interface.  This isn't the default, because the
      compiler needs to be bootstrapped with itself in order for GHCi
      to work properly.  The reason is that the byte-code compiler and
      linker are quite closely tied to the runtime system, so it is
      essential that GHCi is linked with the most up-to-date RTS.
      Another reason is that the representation of certain datatypes
      must be consistent between GHCi and its libraries, and if these
      were inconsistent then disaster could follow.
      </dd>

    </dl>

    <h2>Platform tests</h2>

    <p>There are three platforms of interest to GHC:
 
    <ul>
      <li>The <b>Build</b> platform.  This is the platform on which we
      are building GHC.</li>
      <li>The <b>Host</b> platform.  This is the platform on which we
      are going to run this GHC binary, and associated tools.</li>
      <li>The <b>Target</b> platform.  This is the platform for which
      this GHC binary will generate code.</li>
    </ul>

    <p>At the moment, there is very limited support for having
    different values for buil, host, and target.  In particular:</p>

    <ul>
      <li>The build platform is currently always the same as the host
      platform.  The build process needs to use some of the tools in
      the source tree, for example <tt>ghc-pkg</tt> and
      <tt>hsc2hs</tt>.</li>
      
      <li>If the target platform differs from the host platform, then
      this is generally for the purpose of building <tt>.hc</tt> files
      from Haskell source for porting GHC to the target platform.
      Full cross-compilation isn't supported (yet).</li>
    </ul>

    <p>In the compiler's source code, you may make use of the
    following CPP symbols:</p>

    <ul>
      <li><em>xxx</em><tt>_TARGET_ARCH</tt></li>
      <li><em>xxx</em><tt>_TARGET_VENDOR</tt></li>
      <li><em>xxx</em><tt>_TARGET_OS</tt></li>
      <li><em>xxx</em><tt>_HOST_ARCH</tt></li>
      <li><em>xxx</em><tt>_HOST_VENDOR</tt></li>
      <li><em>xxx</em><tt>_HOST_OS</tt></li>
    </ul>
    
    <p>where <em>xxx</em> is the appropriate value:
    eg. <tt>i386_TARGET_ARCH</tt>.

    <h2>Compiler versions</h2>

    <p>GHC must be compilable by every major version of GHC from 5.02
    onwards, and itself.  It isn't necessary for it to be compilable
    by every intermediate development version (that includes last
    week's CVS sources).

    <p>To maintain compatibility, use <tt>HsVersions.h</tt> (see
    below) where possible, and try to avoid using <tt>#ifdef</tt> in
    the source itself.

    <h2>The source file</h2>

    <p>We now describe a typical source file, annotating stylistic
    choices as we go.

<pre>
{-# OPTIONS ... #-}
</pre>

    <p>An <tt>OPTIONS</tt> pragma is optional, but if present it
    should go right at the top of the file.  Things you might want to
    put in <tt>OPTIONS</tt> include:

    <ul>
      <li><tt>-#include</tt> options to bring into scope prototypes
      for FFI declarations</li>
      <li><tt>-fvia-C</tt> if you know that
      this module won't compile with the native code generator.
    </ul>

    <p>Don't bother putting <tt>-cpp</tt> or <tt>-fglasgow-exts</tt>
    in the <tt>OPTIONS</tt> pragma; these are already added to the
    command line by the build system.


<pre>
module Foo (
   T(..),
   foo,	     -- :: T -> T
 ) where
</pre>

    <p>We usually (99% of the time) include an export list.  The only
    exceptions are perhaps where the export list would list absolutely
    everything in the module, and even then sometimes we do it anyway.

    <p>It's helpful to give type signatures inside comments in the
    export list, but hard to keep them consistent, so we don't always
    do that.

<pre>
#include "HsVersions.h"
</pre>

    <p><tt>HsVersions.h</tt> is a CPP header file containing a number
    of macros that help smooth out the differences between compiler
    versions.  It defines, for example, macros for library module
    names which have moved between versions.  Take a look.

<pre>
-- friends
import SimplMonad

-- GHC
import CoreSyn
import Id           ( idName, idType )
import BasicTypes

-- libraries
import DATA_IOREF   ( newIORef, readIORef )

-- std
import List         ( partition )
import Maybe        ( fromJust )
</pre>

   <p>List imports in the following order:
   
   <ul>
     <li>Local to this subsystem (or directory) first</li>

     <li>Compiler imports, generally ordered from specific to generic
       (ie. modules from <tt>utils/</tt> and <tt>basicTypes/</tt>
       usually come last)</li>

     <li>Library imports</li>

     <li>Standard Haskell 98 imports last</li>
   </ul>

   <p>Import library modules from the <tt>base</tt> and
   <tt>haskell98</tt> packages only.  Use <tt>#defines</tt> in
   <tt>HsVersions.h</tt> when the modules names differ between
   versions of GHC (eg. <tt>DATA_IOREF</tt> in the example above).
   For code inside <tt>#ifdef GHCI</tt>, don't need to worry about GHC
   versioning (because we are bootstrapped).

   <p>We usually use import specs to give an explicit list of the
   entities imported from a module.  The main reason for doing this is
   so that you can search the file for an entity and find which module
   it comes from.  However, huge import lists can be a pain to
   maintain, so we often omit the import specs when they start to get
   long (actually I start omitting them when they don't fit on one
   line --Simon M.).  Tip: use GHC's <tt>-fwarn-unused-imports</tt>
   flag so that you get notified when an import isn't being used any
   more.

   <p>If the module can be compiled multiple ways (eg. GHCI
   vs. non-GHCI), make sure the imports are properly <tt>#ifdefed</tt>
   too, so as to avoid spurious unused import warnings.

   <p><em>ToDo: finish this</em>
  </body>
</html>