Files
mercury/compiler/notes/coding_standards.html
Zoltan Somogyi f28db724d5 Update the coding standard to ask for each import_module to import
Estimated hours taken: 1
Branches: main

compiler/notes/coding_standards.html:
	Update the coding standard to ask for each import_module to import
	only one module even if the module is from the library.

	Update the coding standard to reflect current accepted practice
	with respect to indentation and the formatting of type definitions.
2005-03-21 05:51:25 +00:00

500 lines
13 KiB
HTML

<html>
<head>
<title>
Mercury Coding Standard for the Mercury Project
</title>
</head>
<body
bgcolor="#ffffff"
text="#000000"
>
<hr>
<!-------------------------->
<h1>
Mercury Coding Standard for the Mercury Project</h1>
<hr>
<!-------------------------->
<h2> Documentation </h2>
<p>
Each module should contain header comments which state
the module's name, main author(s), and purpose, and
give an overview of what the module does, what are the
major algorithms and data structures it uses, etc.
<p>
Everything that is exported from a module should have
sufficient documentation that it can be understood without reference
to the module's implementation section.
<p>
Each procedure that is implemented using foreign code
should have sufficient documentation about its interface that it
can be implemented just by referring to that documentation,
without reference to the module's implementation section.
<p>
Each predicate other than trivial access predicates should have
a short comment describing what the predicate is supposed to do,
and what the meaning of the arguments is. Ideally this description
should also note any conditions under which the predicate can fail
or throw an exception.
<p>
There should be a comment for each field of a structure saying
what the field represents.
<p>
Any user-visible changes such as new compiler options or new
features should be documented in appropriate section
of the Mercury documentation (usually the Mercury User's Guide
and/or the Mercury Reference Manual). Any major new features
should be documented in the NEWS file, as should even small
changes to the library interface, or anything else that might
cause anyone's existing code to break.
<p>
Any new compiler modules or other major design changes should
be documented in `compiler/notes/compiler_design.html'.
<p>
Any feature which is incompletely implemented should be mentioned in
`compiler/notes/work_in_progress.html'.
<h2> Naming </h2>
<p>
Variables should always be given meaningful names,
unless they are irrelevant to the code in question.
For example, it is OK to use single-character names
in an access predicate which just sets a single
field of a structure, such as
<pre>
bar_set_foo(Foo, bar(A, B, C, _, E), bar(A, B, C, Foo, E)).
</pre>
Variables which represent different states or different versions
of the same entity should be named Foo0, Foo1, Foo2, ..., Foo.
<p>
Predicates which get or set a field of a structure or ADT should
be named bar_get_foo and bar_set_foo respectively, where bar
is the name of the structure or ADT and foo is the name of the field.
<h2> Coding </h2>
<p>
Your code should make as much reuse of existing code as possible.
"cut-and-paste" style reuse is highly discouraged.
<p>
Your code should be efficient. Performance is a quite
serious issue for the Mercury compiler.
<p>
No fixed limits please!
(If you really must have a fixed limit, include detailed documentation
explaining why it was so hard to avoid.)
<p>
Only use DCG notation for parsing, not for threading implicit arguments.
Use state variables for threading the IO state etc. The conventional IO
state variable name is <code>!IO</code>.
<h2> Error handling </h2>
<p>
Code should check for both erroneous inputs from the user and also
invalid data being passed from other parts of the Mercury compiler.
You should also always check to make sure that the routines that you
call have succeed; make sure you don't silently ignore failures. (This
last point almost goes without saying in Mercury, but is particularly
important to bear in mind if you are writing any C code or shell
scripts, or if you are interfacing with the OS.)
<p>
Calls to error/1 should always indicate an internal software error, not
merely incorrect inputs from the user, or failure of some library routine
or system call. In the compiler,
use unexpected/2 or sorry/2 from error_util.m rather than error/1.
<p>
Error messages should follow a consistent format.
For compiler error messages, each line should start
with the source file name and line number in "%s:%03d: " format.
Compiler error messages should be complete sentences; they
should start with a capital letter and end in a full stop. For error
messages that are spread over more than one line (as are most of them),
the second and subsequent lines should be indented two spaces. If the
`--verbose-errors' option was set, you should print out additional text
explaining in detail what the error message means and what the likely
causes are.
The preferred method of printing error messages
is via the predicates in error_util.m;
use prog_out__write_context and io__write_strings
only if there is no way to add the capability you require to error_util.m.
<p>
Error messages from the runtime system should begin with the text
"Mercury Runtime:", preferably by using the MR_fatal_error() routine.
<p>
If a system call or C library function that sets errno fails, the
error message should be printed with perror() or should contain
strerror(errno). If it was a function manipulating some file, the
error message should include the filename.
<h2> Layout </h2>
<p>
Each module should be indented consistently,
with either 4 or 8 spaces per level of indentation.
The indentation should be consistently done,
either only with tabs or only with spaces.
A tab character should always mean 8 spaces;
if a module is indented using 4 spaces per level of indentation,
this should be indicated by four spaces,
not by a tab with tab stops set to 4.
<p>
Files that use 8 spaces per level of indentation
don't need any special setup.
Files that use 4 spaces per level of indentation
should have something like this at the top,
even before the copyright line:
<pre>
% vim: ft=mercury ts=4 sw=4 et
</pre>
<p>
No line should extend beyond 79 characters.
The reason we don't allow 80 character lines is that
these lines wrap around in diffs,
since diff adds an extra character at the start of each line.
<p>
String literals that don't fit on a single line should be
split by writing them as two or more strings concatenated using the
"++" operator; the compiler will evaluate this at compile time,
if --optimize-constant-propagation is enabled (i.e. at -O3 or higher).
<p>
Predicates that have only one mode should use predmode declarations
rather than having a separate mode declaration.
<p>
If-then-elses should always be parenthesized,
except that an if-then-else that occurs as the else
part of another if-then-else doesn't need to be parenthesized.
The condition of an if-then-else can either be on the same
line as the opening parenthesis and the `->',
<pre>
( test1 ->
goal1
; test2 ->
goal2
;
goal
)
</pre>
or, if the test is complicated, it can be on a line of its own:
<pre>
(
very_long_test_that_does_not_fit_on_one_line(VeryLongArgument1,
VeryLongArgument2)
->
goal1
;
test2a,
test2b,
->
goal2
;
test3 % would fit one one line, but separate for consistency
->
goal3
;
goal
).
</pre>
<p>
Disjunctions should always be parenthesized.
The semicolon of a disjunction should never be at the
end of a line -- put it at the start of the next line instead.
<p>
Type definitions should be formatted in one of the following styles:
<pre>
:- type my_type
---> my_type(
some_other_type % comment explaining it
).
:- type my_struct --->
my_struct(
field1, % comment explaining it
...
).
:- type some_other_type == int.
:- type foo
---> bar(
int, % comment explaining it
float % comment explaining it
)
; baz
; quux.
</pre>
<p>
If an individual clause is long, it should be broken into sections,
and each section should have a "block comment" describing what it does;
blank lines should be used to show the separation into sections.
Comments should precede the code to which they apply, rather than
following it.
<pre>
%
% This is a block comment; it applies to the code in the next
% section (up to the next blank line).
%
blah,
blah,
blahblah,
blah,
</pre>
If a particular line or two needs explanation, a "line" comment
<pre>
% This is a "line" comment; it applies to the next line or two
% of code
blahblah
</pre>
or an "inline" comment
<pre>
blahblah % This is an "inline" comment
</pre>
should be used.
<h2> Structuring </h2>
Code should generally be arranged so that procedures (or types, etc.)
are listed in top-down order, not bottom-up.
<p>
Code should be grouped into bunches of related predicates, functions,
etc., and sections of code that are conceptually separate should be
separated with dashed lines:
<pre>
%---------------------------------------------------------------------------%
</pre>
Ideally such sections should be identified by "section heading" comments
identifying the contents of the section, optionally followed by a more
detailed description. These should be laid out like this:
<pre>
%---------------------------------------------------------------------------%
%
% Section title
%
% Detailed description of the contents of the section and/or
% general comments about the contents of the section.
% This part may go one for several lines.
%
% It can even contain several paragraphs.
The actual code starts here.
</pre>
For example
<pre>
%---------------------------------------------------------------------------%
%
% Exception handling
%
% This section contains all the code that deals with throwing or catching
% exceptions, including saving and restoring the virtual machine registers
% if necessary.
%
% Note that we need to take care to ensure that this code is thread-safe!
:- type foo ---&gt; ...
</pre>
Double-dashed lines, i.e.
<pre>
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
</pre>
can also be used to indicate divisions into major sections.
Note that these dividing lines should not exceed the 79 character limit
(see above).
<h2> Module imports </h2>
Each group of :- import_module items should list only one module per line,
since this makes it much easier to read diffs
that change the set of imported modules.
In the compiler, when e.g. an interface section imports modules
from both the compiler and the standard library,
there should be two groups of imports,
the imports from the compiler first and then the ones from the library.
For the purposes of this rule,
consider the modules of mdbcomp to belong to the compiler.
<p>
Each group of import_module items should be sorted,
since this makes it easier to detect duplicate imports
and missing imports.
It also groups together the imported modules from the same package.
There should be no blank lines between
the imports of modules from different packages,
since this makes it harder to resort the group
with a single editor command.
<h2> Standard library predicates </h2>
The descriptive comment for any predicate or function that occurs in
the interface of a standard library module must be positioned above
the predicate/function declaration. It should be formatted like
the following example:
<pre>
% Description of predicate foo.
%
:- pred foo(...
:- mode foo(...
</pre>
A group of related predicate, mode and function declarations may be grouped
together under a single description provided that it is formatted as above.
If there is a function declaration in such a grouping then it should be listed
before the others.
For example:
<pre>
% Insert a new key and corresponding value into a map.
% Fail if the key already exists.
%
:- func map.insert(map(K, V), K, V) = map(K, V).
:- pred map.insert(map(K, V)::in, K::in, V::in, map(K, V)::out) is det.
</pre>
The reason for using this particular style is that the reference manual for
the standard library is automatically generated from the module interfaces
and we want, as much as is possible, to maintain a uniform appearance.
<h2> Testing </h2>
<p>
Every change should be tested before being committed.
The level of testing required depends on the nature of the change.
If this change fixes an existing bug, and is not likely to introduce
any new bugs, then just compiling it and running some tests
by hand is sufficient. If the change might break the compiler,
you should run a bootstrap check (using the `bootcheck' script)
before committing. If the change means that old versions of
the compiler will not be able to compile the new version of the
compiler, you must notify all the other Mercury developers.
<p>
In addition to testing before a change is committed, you need to make
sure that the code will not get broken in the future by adding tests to
the test suite. Every time you add a new feature, you should add some
test cases for that new feature to the test suite. Every time you fix
a bug, you should add a regression test to the test suite.
<h2> Committing changes </h2>
<p>
Before committing a change, you should get someone else to review your
changes.
<p>
The file <a href="reviews.html">compiler/notes/reviews.html</a>
contains more information on review policy.
<hr>
<!-------------------------->
Last update was $Date: 2005-03-21 05:51:25 $ by $Author: zs $@cs.mu.oz.au. <br>
</body>
</html>