Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
143 lines (101 sloc) 5.3 KB
== MCI: Managed Compiler Infrastructure ==
-- Style --
This is a guide to the general code style used in the MCI source base.
If you're contributing code to the project, you should make sure to
follow these. We are rather strict about these rules as we believe that
they help us keep a clean and consistent source base.
++ Indentation ++
We indent with 4 spaces, always, everywhere. Do not use hard tabs.
++ Braces ++
Braces always go on a separate line. Never put them on the same line as
anything else except in lambda bodies. In other words, use Allman style
++ Spacing ++
One place where spacing is very important is in expressions. You should
always put a space on all sides of binary and ternary operators, for example.
Note that this is not necessary for unary operators, including typeof, typeid,
is, assert, and so on.
Spacing is not necessary in function calls either (other than after a comma).
For example, you should do:
* foo();
* foo(bar);
* foo(bar, baz);
* foo!bar(baz);
* foo!(bar, baz)();
Additionally, always put a space after a block statement keyword. That is:
* if (...)
* while (...)
* for (...)
++ Naming ++
In general, we follow the naming conventions of Phobos, the standard
library for D:
* Module and package names should be all lower case, and should not
use underscores. All module names must start with "mci" followed by
the name of the library/executable (for example, "mci.core.tuple").
* Type names should be PascalCase.
* Function and property names should be camelCase.
* Public field names should be camelCase, while private field names
should be _camelCase.
* Enum member names should be camelCase.
* Template mixin names should be PascalCase.
* The name of templates that resolve to types should be PascalCase.
Otherwise, they should be camelCase.
You should have a VERY good reason if you're going to deviate from these
naming rules. We want to keep the MCI source base consistent with standard
naming in D so that it feels natural to use it together with Phobos.
++ Comments ++
Comments should be written in clear, concise English with correct grammar
(yes, this includes punctuation). Avoid using abbreviations and acronyms
unless they are generally well-understood in the context. Also, you should
avoid overly verbose comments (often referred to as literate programming),
as they make it harder to read the code. In general, don't comment on the
obvious or on things that are considered common sense.
Good comments:
* // Do some space optimizations.
* // Revert to the previous token.
Bad comments:
* // do some space opts
* // revert to prev tok
++ Contracts ++
One of the most important goals of the MCI is to provide a clear and easy
to use API surface. Therefore, we make heavy use of D's support for design
by contract. In general, ALL public entry points to the API should contain
contracts. It also helps to use them internally.
In other words: Spam in/out contracts, invariants, and asserts everywhere
as you see fit. Better safe than sorry. Keep in mind that these checks are
removed from release builds, so performance is not extremely important.
That being said, try not to assert the obvious. Too many redundant asserts
can also clutter code. Strike a right balance.
++ Storage ++
One problem with global state is that it may be hard to decide whether it
goes into thread-local or global storage. In general, go by the rule that
if you cannot come up with a reason to put a variable in global storage,
it should probably be in TLS.
++ Visiblity Modifiers ++
Use visibility modifiers on all declarations except imports (which are private
by default). It is better to be explicit about visibility so that mistakes
such as accidentally exposing private code won't happen.
++ Const/Immutable/Shared ++
You should generally avoid these type modifiers.
There are lots of problems with shared, in particular. It only ensures safety
on a low level, which is almost always useless in the MCI. Apart from that,
it is a highly viral type modifier which tends to make it extremely annoying
to work with the API. A cast can remove it, but that goes against the entire
safety it's supposed to offer. So, avoid this modifier by all means.
The const and immutable modifiers are much less problematic, but unfortunately
are not implemented correctly and without bugs in any current compilers. For
this reason, we generally avoid them as well. We do plan to make more use of
them once compilers get less broken support for them.
++ Scope Modifier ++
Using the scope modifier on delegate parameters when possible is, in general,
good practice. It helps ensure that delegates aren't unnecessarily allocated
in the GC heap when they aren't escaped from the function using them.
++ Initialization Types ++
When initializing fields or global variables, it is generally preferable to
use typeof:
* foo = new typeof(foo)(); // For classes.
* bar = typeof(bar)(); // For structs.
This usually results in less typing and makes it easier to refactor code.
This is, of course, only usable when the field or variable is not declared as
an interface or abstract class, so in those cases, it is fine to use an
explicit type.
Jump to Line
Something went wrong with that request. Please try again.