2013-09-13 21:30:35 +00:00
|
|
|
Coding Style
|
|
|
|
============
|
|
|
|
|
|
|
|
[C++11](http://en.wikipedia.org/wiki/C%2B%2B11) features
|
|
|
|
--------------------------------------------------------
|
|
|
|
|
|
|
|
We make extensive use of new features in the C++ 11 standard.
|
|
|
|
Developers must be familiar with the standard to be able to understand
|
|
|
|
the code.
|
|
|
|
Here are some of the features that are extensively used.
|
|
|
|
|
|
|
|
- Type inference (aka `auto` keyword).
|
|
|
|
- Initializer lists.
|
|
|
|
- Lambda functions and expressions.
|
|
|
|
- `nullptr` constant.
|
|
|
|
- Strongly typed enumerations.
|
|
|
|
- Right angle bracket.
|
|
|
|
- Thread local storage.
|
|
|
|
- Threading facilities.
|
|
|
|
- Tuple types.
|
|
|
|
|
|
|
|
Comments
|
|
|
|
--------
|
|
|
|
|
|
|
|
The comments in the Lean codebase contain
|
|
|
|
[Doxygen](http://www.stack.nl/~dimitri/doxygen/) commands.
|
|
|
|
Doxygen is the de facto standard tool for generating documentation from
|
|
|
|
annotated C++ sources.
|
|
|
|
|
|
|
|
Namespaces
|
|
|
|
----------
|
|
|
|
|
|
|
|
All code is in the `lean` namespace. Each frontend is stored in a
|
|
|
|
separate nested namespace. For example, the SMT 2.0 frontend is stored
|
|
|
|
in the `lean::smt` namespace.
|
|
|
|
|
|
|
|
Exception: some debugging functions are stored outside of the `lean`
|
|
|
|
namespace. These functions are called `print` and are meant to be used
|
|
|
|
when debugging Lean using `gdb`.
|
|
|
|
|
|
|
|
Smart pointers
|
|
|
|
--------------
|
|
|
|
|
|
|
|
We only use `std::shared_ptr` template for class `C` only if we expect
|
|
|
|
to create only a few objects (< 1000) of class `C`. Otherwise, we
|
|
|
|
implement our own intrusive smart pointer. For example, the class
|
|
|
|
`expr` is an intrusive smart pointer to `expr_cell`. We may have
|
|
|
|
millions of `expr` objects. We say it is intrusive because the
|
|
|
|
reference counter is stored in `expr_cell`.
|
|
|
|
|
|
|
|
We use `std::unique_ptr` to make sure unique resources will be freed
|
|
|
|
correctly.
|
|
|
|
|
2013-10-28 15:31:46 +00:00
|
|
|
Template
|
|
|
|
--------
|
|
|
|
We organize template source code using the approach described at http://www.codeproject.com/Articles/3515/How-To-Organize-Template-Source-Code
|
|
|
|
|
2013-09-13 21:30:35 +00:00
|
|
|
Idioms
|
|
|
|
------
|
|
|
|
|
|
|
|
We use some popular C++ idioms:
|
|
|
|
|
|
|
|
- [Pimpl](http://c2.com/cgi/wiki?PimplIdiom)
|
|
|
|
- [RAII](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) Resource Acquisition Is Initialization
|
|
|
|
|
|
|
|
Formatting
|
|
|
|
----------
|
|
|
|
|
|
|
|
* We use 4 spaces for indentation.
|
|
|
|
|
|
|
|
* Class, method, and function names are lower case
|
|
|
|
We use `_` for composite names. Example: `type_checker`.
|
|
|
|
|
|
|
|
* Class/struct fields should start with the prefix `m_`.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
class point {
|
|
|
|
int m_x;
|
|
|
|
int m_y;
|
|
|
|
public:
|
|
|
|
...
|
|
|
|
};
|
|
|
|
|
|
|
|
* We do **not** use the `#ifndef-#define-#endif` idiom for header files.
|
|
|
|
Instead we use `#pragma once`.
|
|
|
|
|
|
|
|
* We write `type const & v` instead of `const type & v`.
|
|
|
|
|
|
|
|
* We use `const` extensively.
|
|
|
|
|
|
|
|
* `if-then-else`
|
|
|
|
|
|
|
|
The following forms are acceptable:
|
|
|
|
|
|
|
|
if (cond) {
|
|
|
|
...
|
|
|
|
} else {
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
and
|
|
|
|
|
|
|
|
if (cond)
|
|
|
|
statement1;
|
|
|
|
else
|
|
|
|
statement2;
|
|
|
|
|
|
|
|
In *exceptional cases*, we also use
|
|
|
|
|
|
|
|
if (cond) statement;
|
|
|
|
|
|
|
|
and
|
|
|
|
|
|
|
|
if (cond) statement1; else stament2;
|
|
|
|
|
|
|
|
* `if-then-else-if-else`
|
|
|
|
|
|
|
|
The following forms are acceptable:
|
|
|
|
|
|
|
|
if (cond) {
|
|
|
|
...
|
|
|
|
} else if (cond) {
|
|
|
|
...
|
|
|
|
} else {
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
and
|
|
|
|
|
|
|
|
if (cond)
|
|
|
|
statement1;
|
|
|
|
else if (cond)
|
|
|
|
statement2;
|
|
|
|
else
|
|
|
|
statement3;
|
|
|
|
|
|
|
|
* We frequently format code using extra spaces
|
|
|
|
|
|
|
|
For example, we write
|
|
|
|
|
|
|
|
environment const & m_env;
|
|
|
|
cache m_cache;
|
|
|
|
normalizer m_normalizer;
|
|
|
|
volatile bool m_interrupted;
|
|
|
|
|
|
|
|
instead of
|
|
|
|
|
|
|
|
environment const & m_env;
|
|
|
|
cache m_cache;
|
|
|
|
normalizer m_normalizer;
|
|
|
|
volatile bool m_interrupted;
|
|
|
|
|
|
|
|
* We use the macro `lean_assert` for assertions.
|
|
|
|
The macro `lean_assert` is extensively used when writing unit tests.
|
|
|
|
|
|
|
|
* Spaces in expressions
|
|
|
|
We write `a == b` instead of `a==b`.
|
|
|
|
Similarly, we write `x < y + 1` instead of `x<y+1`.
|
|
|
|
|
2013-09-14 03:30:48 +00:00
|
|
|
Google's C++ Style Guide
|
|
|
|
------------------------
|
|
|
|
|
2013-09-26 00:44:27 +00:00
|
|
|
We are using a modified version of [Google's C++ Style Guide][google-style].
|
|
|
|
We also have our version of Google's style checker [cpplint.py][cpplint].
|
|
|
|
You can run the checker over the codebase by typing:
|
2013-09-14 03:30:48 +00:00
|
|
|
|
2013-09-26 00:44:27 +00:00
|
|
|
make style
|
|
|
|
|
|
|
|
If you use Ninja, you can check by ``ninja style``. It is also a part of testcases and can be run by
|
|
|
|
|
|
|
|
ctest -R style_check
|
|
|
|
|
|
|
|
*Disabled* Features:
|
|
|
|
|
|
|
|
- Namespace should be terminated with "namespace"
|
2013-09-14 03:30:48 +00:00
|
|
|
- At least two spaces is best between code and comments
|
|
|
|
- Do not use ``dynamic_cast<>``. If you need to cast within a class
|
|
|
|
hierarchy, use ``static_cast<>`` to upcast. Google doesn't support
|
|
|
|
RTTI.
|
2013-09-26 00:44:27 +00:00
|
|
|
- "public:" should be preceded by a blank line
|
|
|
|
- Missing space before ``{``
|
2013-09-14 03:30:48 +00:00
|
|
|
- Found C system header after C++ system header. Should be:
|
2013-09-26 00:44:27 +00:00
|
|
|
environment.h, c system, c++ system, other.
|
2013-09-14 03:30:48 +00:00
|
|
|
- Labels should always be indented at least one space. If this is
|
|
|
|
a member-initializer list in a constructor or the base class list in
|
|
|
|
a class definition, the colon should be on the following line.
|
2013-09-26 00:44:27 +00:00
|
|
|
- You don't need a ``;`` after a ``}``
|
2013-09-14 03:30:48 +00:00
|
|
|
- No ``#ifndef`` header guard found
|
|
|
|
- Streams are highly discouraged.
|
2013-09-26 00:44:27 +00:00
|
|
|
- Extra space before ``(`` in function call
|
|
|
|
- Else clause should never be on same line as else
|
|
|
|
- Extra space before ``)``
|
|
|
|
- Is this a non-const reference? If so, make const or use a pointer.
|
|
|
|
- All parameters should be named in a function
|
|
|
|
|
|
|
|
Modified Features:
|
|
|
|
|
|
|
|
- Add ``#include <list>`` for ``list<>``
|
|
|
|
|
|
|
|
=> *Check* ``std::list`` instead of ``list`` because we do have our own ``lean::list`` type.
|
|
|
|
|
|
|
|
- Add ``#include <algorithm>`` for copy
|
|
|
|
|
|
|
|
=> *Check* ``std::copy`` instead of ``copy`` because we do have our own ``lean::copy`` method.
|
|
|
|
|
|
|
|
- Do not use namespace using-directives. Use using-declarations instead.
|
|
|
|
|
|
|
|
=> *Allow* this if filename contains "tests/"
|
|
|
|
|
|
|
|
- Small and focused functions are preferred: foo()
|
|
|
|
has xxx non-comment lines (error triggered by exceeding 500 lines).
|
|
|
|
|
|
|
|
=> *Allow* this if filename contains "tests/"
|
|
|
|
|
|
|
|
- Include the directory when naming .h files
|
|
|
|
|
|
|
|
=> *Allow* this if the included filename is "version.h" which is generated by cmake.
|
2013-09-14 03:30:48 +00:00
|
|
|
|
|
|
|
[google-style]: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
|
2013-09-26 00:44:27 +00:00
|
|
|
[cpplint]: /src/cmake/Modules/cpplint.py
|
2013-11-12 01:18:38 +00:00
|
|
|
|
|
|
|
Git pre-push hook
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
Since [git 1.8.2][git-pre-push-hook], git introduced *pre-push* hook
|
|
|
|
which is executed *before* actual push operation is performed. Using this,
|
|
|
|
we can *automatically* run the style checker over the changed files *before*
|
|
|
|
we push commits to repositories. This is useful because it prevents us
|
|
|
|
from accidentally pushing the commits which contain style problems.
|
|
|
|
|
|
|
|
[git-pre-push-hook]: https://github.com/git/git/blob/master/Documentation/RelNotes/1.8.2.txt
|
|
|
|
|
|
|
|
- Create ``<PROJECT_ROOT>/.git/hooks/pre-push`` file with the following contents:
|
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
IFS=' '
|
|
|
|
DIR="$( cd "$( dirname "$0" )" && pwd )"
|
|
|
|
CHECKER=$DIR/../../src/cmake/Modules/cpplint.py
|
|
|
|
while read local_ref local_sha remote_ref remote_sha;
|
|
|
|
do
|
|
|
|
CHANGED_FILES=`git diff --name-only $local_sha $remote_sha | grep '\(cpp\|h\)$'`
|
|
|
|
if [ ! -z "$CHANGED_FILES" -a "$CHANGED_FILES" != " " ]; then
|
|
|
|
echo $CHANGED_FILES | xargs $CHECKER
|
|
|
|
RET=$?
|
|
|
|
if [ $RET -ne 0 ]; then
|
|
|
|
echo "There is error(s) from style-check. Please fix them before push to the repo."
|
|
|
|
exit $RET
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
exit 0
|
|
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
- Give "exec" permission to the file
|
|
|
|
|
|
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
chmod +x <PROJECT_ROOT>/.git/hooks/pre-push
|
|
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Note that you need to change ``CHECKER`` variable if you want to use other
|
|
|
|
checkers.
|