Changes between Version 33 and Version 34 of Commentary/CodingStyle


Ignore:
Timestamp:
Apr 24, 2011 10:03:52 PM (3 years ago)
Author:
megacz
Comment:

more section restructuring

Legend:

Unmodified
Added
Removed
Modified
  • Commentary/CodingStyle

    v33 v34  
    66This is a rough description of some of the coding practices and style that we use for Haskell code inside {{{compiler}}}.  For run-time system code see the [wiki:Commentary/Rts/Conventions Coding Style Guidelines for RTS C code].  Also see the wiki page on [wiki:WorkingConventions Working Conventions] for issues related to version control, workflow, testing, bug tracking and other miscellany. 
    77 
     8== General Style == 
     9 
    810The 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.  
     11 
     12It's much better to write code that is transparent than to write code that is short. 
     13 
     14Often it's better to write out the code longhand than to reuse a generic abstraction (not always, of course).  Sometimes it's better to duplicate some similar code than to try to construct an elaborate generalisation with only two instances.  Remember: other people have to be able to quickly understand what you've done, and overuse of abstractions just serves to obscure the ''really'' tricky stuff, and there's no shortage of that in GHC. 
    915 
    1016== Comments == 
     
    100106pragma; you are encouraged to remove this pragma and fix any warnings when working on a module. 
    101107 
    102 == Literate Haskell == 
    103  
    104 In GHC we use a mixture of literate ({{{.lhs}}}) and non-literate ({{{.hs}}}) source. I (Simon M.) prefer to use non-literate style, because I think the {{{\begin{code}..\end{code}}}} 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).  
    105  
    106 == The C Preprocessor (CPP) == 
    107  
    108 Currently we pass all the compiler sources through CPP. The -cpp flag is always added by the build system.  
    109 However, whenever possible we try to avoid using CPP, as it can hide code from the compiler (which means changes that work on one platform can break the build on another) and code using CPP can be harder to understand. 
    110  
    111 The following CPP symbols are used throughout the compiler:  
    112  
    113  '''DEBUG'''::  
    114   Used to enables extra checks and debugging output in the compiler. The ASSERT macro (see {{{HsVersions.h}}}) provides assertions which disappear when DEBUG is not defined.  
    115  
    116  However, whenever possible, it is better to us `debugIsOn` from the `Util` module, which is defined to be `True` when `DEBUG` is defined and `False` otherwise.  The ideal way to provide debugging output is to use a Haskell expression "`when debugIsOn $ ...`" to arrange that the compiler will be silent when `DEBUG` is off (unless of course something goes wrong or the verbosity level is nonzero). When option `-O` is used, GHC will easily sweep away the unreachable code. 
    117  
    118  As a last resort, debugging code can be placed inside `#ifdef DEBUG`, but since this strategy guarantees that only a fraction of the code is seen be the compiler on any one compilation, it is to be avoided when possible. 
    119  
    120  Regarding performance, a good rule of thumb is that `DEBUG` 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 `-dcore-lint`. 
    121  
    122 '''Trap, pitfall for using the ASSERT macro''': 
    123  
    124 The ASSERT macro uses CPP, and if you are unwise enough to try to write assertions using primed variables ({{{ASSERT (not $ intersectsBlockEnv b b')}}}), one possible outcome is that CPP silently fails to expand the ASSERT, and you get this very baffling error message: 
    125 {{{ 
    126 Not in scope: data constructor `ASSERT' 
    127 }}} 
    128 Now you can Google for this error message :-) 
    129  
    130  
    131  '''GHCI'''::  
    132   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.  
    133  
    134 == Compiler versions and language extensions == 
    135  
    136 GHC must be compilable by the previous two major releases, and itself. It isn't necessary for it to be compilable by every intermediate development version (that includes last week's darcs sources).  
    137  
    138 To maintain compatibility, use [wiki:Commentary/CodingStyle#HsVersions.h HsVersions.h] (see below) where possible, and try to avoid using #ifdef in the source itself.  
    139  
    140 Also, it is necessary to avoid certain language extensions.  In particular, the {{{ScopedTypeVariables}}} extension must not be used. 
    141  
    142 == Walk-through of a sample source file == 
    143  
    144 We now describe a typical source file, annotating stylistic choices as we go.  
    145  
    146 ===  The OPTIONS pragma === 
    147  
    148 An {{{{-# OPTIONS_GHC ... #-}}}} pragma is optional, but if present it should go right at the top of the file. Things you might want to put in OPTIONS include:  
    149  
    150  * {{{#include}}} options to bring into scope prototypes for FFI declarations  
    151  * {{{-fvia-C}}} if you know that this module won't compile with the native code generator.  (deprecated: 
    152    everything should compile with the NCG nowadays, but that wasn't always the case). 
    153  
    154 Don't bother putting `-cpp` or `-fglasgow-exts` in the `OPTIONS` pragma; these are already added to the command line by the build system.  
     108== Exports and Imports == 
    155109 
    156110=== Exports === 
     
    166120It'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.  
    167121 
    168 === {{{HsVersions.h}}} === 
    169 {{{HsVersions.h}}} 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 [[GhcFile(compiler/HsVersions.h)]]. 
    170 {{{ 
    171 #include "HsVersions.h" 
    172 }}} 
    173122 
    174123=== Imports === 
     
    214163If the module can be compiled multiple ways (eg. GHCI vs. non-GHCI), make sure the imports are properly `#ifdefed` too, so as to avoid spurious unused import warnings.  
    215164 
    216 === General Style === 
    217  
    218 It's much better to write code that is transparent than to write code that is short. 
    219  
    220 Often it's better to write out the code longhand than to reuse a generic abstraction (not always, of course).  Sometimes it's better to duplicate some similar code than to try to construct an elaborate generalisation with only two instances.  Remember: other people have to be able to quickly understand what you've done, and overuse of abstractions just serves to obscure the ''really'' tricky stuff, and there's no shortage of that in GHC. 
     165 
     166== Literate Haskell == 
     167 
     168In GHC we use a mixture of literate ({{{.lhs}}}) and non-literate ({{{.hs}}}) source. I (Simon M.) prefer to use non-literate style, because I think the {{{\begin{code}..\end{code}}}} 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).  
     169 
     170== The C Preprocessor (CPP) == 
     171 
     172Currently we pass all the compiler sources through CPP. The -cpp flag is always added by the build system.  
     173However, whenever possible we try to avoid using CPP, as it can hide code from the compiler (which means changes that work on one platform can break the build on another) and code using CPP can be harder to understand. 
     174 
     175The following CPP symbols are used throughout the compiler:  
     176 
     177 '''DEBUG'''::  
     178  Used to enables extra checks and debugging output in the compiler. The ASSERT macro (see {{{HsVersions.h}}}) provides assertions which disappear when DEBUG is not defined.  
     179 
     180 However, whenever possible, it is better to us `debugIsOn` from the `Util` module, which is defined to be `True` when `DEBUG` is defined and `False` otherwise.  The ideal way to provide debugging output is to use a Haskell expression "`when debugIsOn $ ...`" to arrange that the compiler will be silent when `DEBUG` is off (unless of course something goes wrong or the verbosity level is nonzero). When option `-O` is used, GHC will easily sweep away the unreachable code. 
     181 
     182 As a last resort, debugging code can be placed inside `#ifdef DEBUG`, but since this strategy guarantees that only a fraction of the code is seen be the compiler on any one compilation, it is to be avoided when possible. 
     183 
     184 Regarding performance, a good rule of thumb is that `DEBUG` 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 `-dcore-lint`. 
     185 
     186'''Trap, pitfall for using the ASSERT macro''': 
     187 
     188The ASSERT macro uses CPP, and if you are unwise enough to try to write assertions using primed variables ({{{ASSERT (not $ intersectsBlockEnv b b')}}}), one possible outcome is that CPP silently fails to expand the ASSERT, and you get this very baffling error message: 
     189{{{ 
     190Not in scope: data constructor `ASSERT' 
     191}}} 
     192Now you can Google for this error message :-) 
     193 
     194 
     195 '''GHCI'''::  
     196  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.  
     197 
     198== Compiler versions and language extensions == 
     199 
     200GHC must be compilable by the previous two major releases, and itself. It isn't necessary for it to be compilable by every intermediate development version (that includes last week's darcs sources).  
     201 
     202To maintain compatibility, use [wiki:Commentary/CodingStyle#HsVersions.h HsVersions.h] (see below) where possible, and try to avoid using #ifdef in the source itself.  
     203 
     204Also, it is necessary to avoid certain language extensions.  In particular, the {{{ScopedTypeVariables}}} extension must not be used. 
     205 
     206===  The OPTIONS pragma === 
     207 
     208An {{{{-# OPTIONS_GHC ... #-}}}} pragma is optional, but if present it should go right at the top of the file. Things you might want to put in OPTIONS include:  
     209 
     210 * {{{#include}}} options to bring into scope prototypes for FFI declarations  
     211 * {{{-fvia-C}}} if you know that this module won't compile with the native code generator.  (deprecated: 
     212   everything should compile with the NCG nowadays, but that wasn't always the case). 
     213 
     214Don't bother putting `-cpp` or `-fglasgow-exts` in the `OPTIONS` pragma; these are already added to the command line by the build system.  
     215 
     216=== {{{HsVersions.h}}} === 
     217{{{HsVersions.h}}} 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 [[GhcFile(compiler/HsVersions.h)]]. 
     218{{{ 
     219#include "HsVersions.h" 
     220}}} 
     221