Try GP in your browser
Main
Download
Packages
Funding
SEARCH
Help / Community
FAQ
Documentation
Tutorials
Mailing Lists
Bugs
Timeline
Ateliers PARI/GP
Library
Publications
Contributed GP scripts
Links
Fun!
Development
Latest Changes
Version Control
Coding Guidelines
PariDroid
Logo
Tests & benchmarks
Buildlogs
Coverage Report
Doc Coverage
Refcards test
Benchmarks
WWW Stats
|
Coding guidelines
In order to keep the PARI/GP code consistent, please use the following
conventions when writing code that you intend to check into our repository or
submit to the development mailing list. This will save everybody's time!
Best practices
- Language: write all comments in english. Keep function and
variables names (in english) consistent and reasonably short. Only
use 7bit characters.
- Patches: please use unified diffs to send patches to
pari-dev, the BTS or the maintainers, as per
diff -u .
State what the object of a patch is and check that the patch contains no
useless chunk, unrelated to the patch object. Try to break big patches in
small independent units.
- Robustness: before sending a patch, try
make doc
and make test-all : nothing should be changed in the latter
unless you have a very good reason for it (state it), and then the patch must
include the updated output for the test. The code should compile with all
C89, C99 and C++ compilers; in particular, do not use gcc or MSVC extensions,
or C++/C99 one-line comments // blah .
- Globals: avoid adding global variables, even static to a code
module. When it is unavoidable (?), make sure whether you need the
THREAD modifier: do all threads need a copy of this or is it
safe to share it?
- Tests: write tests for new code in
src/test ; if you fix a bug,
you may add a regression test to the relevant test. Try not to change the
make bench subset: it is a common reference point.
- Reusability: write short generic functions, with obvious
functionality rather than huge monolithic ones. Avoid assumptions about the
inputs, then document explicitly what is left, e.g.
p must be
prime.
- Memory allocation: avoid using
malloc() /
free() , the PARI stack is at your disposal.
- Comment non-obvious code: document shortcomings (use
FIXME markers in the code); document each non-trivial function:
above the definition, and possibly in doc/usersch[5-8].tex ,
doc/develop.tex or src/functions/ .
Finalization / Cleanup
- Scopes and declarations: check that all variables have a sensible
scope, ideally the smallest possible scope. Define temporary variable at the
start of the block that needs them. (Only declare variables at the
beginning of a block.) A function must be either
static , or declared in paridecl.h or
paripriv.h . A function ending up in paridecl.h must
be documented in one of the doc/ manuals.
- Unreachable statements: if an unreachable statement
must be included (for instance because the compiler does not know that
pari_err cannot return), mark unreachable lines using a
/*LCOV_EXCL_LINE*/ comment.
- GP2C: If you add or modify a function in the
src/functions/ database, make sure the GP2C descriptions are up
to date. Or state that you were unable to update them.
- Diagnostics: integrate them within the
DEBUGLEVEL , DEBUGMEM scheme. Never use
printf() directly, use wrappers like err_printf() .
Use pari_warn() for warnings.
- Errors: use
pari_err() for fatal errors, never
exit() or abort() . Try to find an appropriate error
type for pari_err() , then use the appropriate
pari_err_XXX wrapper (leverages the compiler to check
arguments). Avoid e_MISC (free form error messages) if possible:
you lose in flexibility, but users can parse the error programmatically.
- The PARI stack: public functions should be
gerepileupto -safe and, if possible, memory clean (not leave
garbage on the stack). You may leave a few small objects on the stack to
avoid a huge garbage collection, but this should be documented;
stackdummy is often needed in this case.
Formatting, spacing and indentation
The most important is to be consistent with neighbouring code, never reformat
the latter so that it adapts to your style.
- Line length: no line should be longer than 80 characters unless
absolutely necessary. Do not leave trailing whitespace.
- Indentation: use 2 spaces for each indentation levels. Do not
use TABs but actual whitespace characters.
- Where to put spaces: do not put spaces before an opening
parenthesis or bracket when calling functions or indexing. Use them around
equal signs and after commas or semi-colons.
- Where to put braces: either of these is acceptable
if (a) { if (a)
code(); {
code(); code();
} code();
}
the first one being usually preferred. Avoid uneccessary open/close braces
and line breaks: use
if (a) code();
rather than
if (a) {
code();
}
- Nesting: to limit indentation levels, use
for (...) {
if (!a) continue;
...
}
rather than
for (...) {
if (a)
{
...
}
}
Try not to use repeated tests against a boolean flag to get out of
deeply nested constructions. Often, moving part of the loop code to a
subroutine and using a simple return is the best solution.
|