You will find here a summary of the different things you should do / look up to contribute to the project.
- First, fork the repository
- Then, clone your fork:
- HTTPS:
git clone https://github.com/<username>/Ark.git
- or SSH:
git clone [email protected]:<username>/Ark.git
- HTTPS:
- Install the pre-commit hooks:
pre-commit install
(you may need to install pre-commit first) - Create a branch for your feature:
git switch -c feat/my-awesome-idea
- When you're done, push it to your fork and submit a pull request
Don't know what to work on? No worries, we have a list of things to do.
For an in-depth explanation: Understanding the project architecture.
For a quick glance at the organization of the project, check this out:
The repository for this is ArkScript-lang/modules, and the language used is C++.
See the guide to create a module.
Code formatting as well as static analysis is handled through pre-commit
and its hooks. If you don't have it installed, refer back to Contributing#Starting.
Build the tests using -DARK_TESTS=On
.
Run the unittests
target to:
- run various C++ unit tests,
- run error messages testing,
- run AST & parsing tests,
- run formatting tests,
- run language tests (
tests/unittests/resources/LangSuite/
)
The easiest tests to add are snapshot tests, in tests/unittests/resources/...Suite/
. They expect an input .ark
file and a desired output file (.expected
or .json
depending on the suite).
- ASTSuite tests the AST parsing, which is then dumped to JSON by the JsonCompiler
- BytecodeReaderSuite tests the decoding of ArkScript bytecode files
- CompilerSuite tests the IR generation and optimization
- DiagnosticsSuite tests the generation of error messages
- compileTime for errors generated by the compiler
- runtime for errors generated by the virtual machine
- FormatterSuite tests the code formatter. Input is badly formatted, output is the expected formatted code
- LangSuite are unit tests written in ArkScript itself, testing the builtins and the language
- NameResolutionSuite tests the resolution of names and packages with import directives
- OptimizerSuite tests the AST optimizer. Nodes should be removed by this pass, we ensure they are not present in the final AST
- ParserSuite tests the parser, along with parsing specific errors
- failure for the parsing failures
- success for the successful parsing, output is the pretty printed AST
It is recommended to add -DARK_COVERAGE=On
to generate coverage reports, this way you can check if your feature has sufficient test coverage instead of waiting on the CI.
Generate coverage reports with cmake --build build --target coverage
, it will generate HTML files under build/coverage/
(main file is index.html
).
- Avoid
auto
whenever possible. Using it is tolerated for complex types such as iterators - Indent with 4 spaces
- Every brace (
{
,}
) must be on its own line - Conditions with a single statement (eg
if (condition) do_this();
) do not need to be enclosed in braces - Put a space between
for
,while
,if
and(...)
, around each=
sign (wherever it is, even in for-loops), between#include
and the file to include - Prefer
enum class
overenum
- Left-const over right-const
- The
*
and&
are part of the type:
// AVOID THIS
int *i = new int(5);
int &j = k;
// PREFERRED
int* i = new int(5);
int& j = k;
- Naming:
- Methods and functions: camelCase
- Variables: snake_case
- Constant expressions: PascalCase
- Enumeration members: PascalCase
- For-each loops should use const references or rvalue references instead of plain copies:
// AVOID THIS
for (auto value : container)
// PREFERRED
for (const auto& value : container)
for (auto&& value : container)
- For-loops should be optimized whenever possible, as follows:
// AVOID THIS
for (std::size_t i = 0; i < container.size(); ++i)
...
// PREFERRED
for (std::size_t i = 0, end = container.size(); i < end; i++)
...
- Header-guards should be written using
#ifndef
,#define
and#endif
, the define being in MACRO_CASE - Functions and methods which can not throw exceptions must be marked
noexcept
- In header files, have a blank line between each method / function / structure / constant ; also put blank lines around include blocks
- In classes, avoid using
this
. Prefix every member variable withm_
- In classes, do not define the methods in the header file, only in the source file (unless they are
inline
or templated) - Add Doxygen file comments at the top of each newly created header file:
/**
* @file Lexer.hpp
* @author Alexandre Plateau ([email protected])
* @brief Tokenize ArkScript code
* @version 0.1
* @date 2020-10-27
*
* @copyright Copyright (c) 2020
*
*/
#include <bla>
code...
Snippet to recapitulate guidelines for headers:
/**
* @file Lexer.hpp
* @author Alexandre Plateau ([email protected])
* @brief Tokenize ArkScript code
* @version 0.1
* @date 2020-10-27
*
* @copyright Copyright (c) 2020
*
*/
#ifndef HEADER_GUARD
#define HEADER_GUARD
#include <Ark/Compiler/Something.hpp>
#include <vector>
namespace Ark
{
/**
* @brief doxygen documentation about the class
*
*/
class Lexer
{
public:
/**
* @brief doxygen documentation here
*
*/
Lexer();
/**
* @brief doxygen documentation here
*
* @param a_parameter defines the power of the flux capacitor
*/
void aMethod(const std::string& a_parameter);
private:
int m_member; ///< This is a doxygen comment
};
}
#endif // Adding an empty line at the end of each file is strongly advised
Check out the Coding guidelines. We are quite flexible about it, those are just general guidelines to produce a readable ArkScript code.