Skip to main content

Code

Code changes

Tests

If at all practicable, all new code should be tested to some extent. If writing a test is hard, we need to prioritize making it easier, and potentially block features if that is the case.

Documentation

Reference documentation should be added, in addition to release notes, for user visible changes.

FIXME(jade): what to do of release notes for dev facing stuff like Meson and build time diagnosis tools?

Benchmarking

Changes that touch the core of the evaluator or other performance critical code in Lix should be benchmarked.

See a procedure at https://git.lix.systems/lix-project/lix/issues/23, for now.

Changelist size

If a CL is too long to review, it should be split up into smaller pieces with tests. The exact length varies but passing the 1000 line mark should give significant thought to splitting.

  • When a CL is split, each commit should still be a valid state (tests passing, etc). If you must, you can gate in-progress changes with a flag or similar until the final commit. (Qyriad)

Commit messages

Include at least a sentence or two as to why you are making a commit. For example, it can be nice to have the reproduction of a bug in the commit message. The commit message is the message for your review.

There's no particular format or specific style for commit messages; just make sure they're descriptive and informative.

C++

While we hope to migrate the lix interpreter from C++ to Rust eventually, C++ is a language that is likely to exist for a long time, and we may end up having to use it in other contexts.

Lix is a C++20 codebase. Features of C++20 that compile on all supported platforms can be used.

Static vs anonymous namespace

Prefer anonymous namespace, both currently exist in the codebase (jade: any other opinions?).

Type Aliases with typedef vs using

Prefer using declarations, as they can be used in more places, can be templatized, and have clearer syntax. Both currently exist in the codebase. (Qyriad)

TODO/FIXME/XXX Comments

Something along the lines of:

  • TODO: acknowledgement that something is acceptably-for-now incomplete, especially if the scope of fixing it is high or unknown
  • FIXME: this should be fixed before the feature or major change that it's a part of is considered "ready"
  • XXX: this should not pass code review and should be considered a left-in mistake

Header files

Filenames

Headers should end with .hh. This reduces the likelihood anyone will try to include them from C files, which would require following the rules of both languages and is easy to get wrong.

The implementation of the functions declared in a .hh file should be in a .cc file of the same name, absent reasons to do otherwise.

Order-independence

Headers should not care what order they're loaded in.

The exception, for now, is config.h in the lix repo. This must always come before all other headers. This observation should not be taken to imply it must always be that way, but at the moment it's helpful to be aware of.

Idempotence

Use #pragma once, it helps. You can see this in most existing header files.

///@file and header documentation

///@file should be at the top of all nix headers - Doxygen and other tools require it to function.

Strongly consider adding a description of the purpose of a header file at the top of it in with @brief A sentence saying what it is for.

Source files

Filenames

Source files should end with .cc.

Nix language

Unsurprisingly Nix contains Nix code. Some amount is tests and a lot is packaging.

We use the (FIXME: alejandra? nixfmt?) formatter. (aspirational)

with

Prefer not to use with to bring things into scope as it obscures the source of variables and degrades language server diagnostics.

Use let inherit (attrset) attrs instead.