D is a general-purpose systems programming language with a C-like syntax that compiles to native code. It is statically typed and supports both automatic (garbage collected) and manual memory management. D programs are structured as modules that can be compiled separately and linked with external libraries to create native libraries or executables.
This document is the reference manual for the D Programming Language. For more information and other documents, see The D Language Website.
Phases of Compilation
The process of compiling is divided into multiple phases. Each phase has no dependence on subsequent phases. For example, the scanner is not perturbed by the semantic analyzer. This separation of the passes makes language tools like syntax directed editors relatively easy to produce. It also is possible to compress D source by storing it in ‘tokenized’ form.
- source character set
The source file is checked to see what character set it is, and the appropriate scanner is loaded. ASCII and UTF formats are accepted.
- script line
If the first line starts with "#!", then that line is ignored.
- lexical analysis
The source file is divided up into a sequence of tokens. Special tokens are replaced with other tokens. SpecialTokenSequences are processed and removed.
- syntax analysis
The sequence of tokens is parsed to form syntax trees.
- semantic analysis
The syntax trees are traversed to declare variables, load symbol tables, assign types, and in general determine the meaning of the program.
Optimization is an optional pass that tries to rewrite the program in a semantically equivalent, but faster executing, version.
- code generation
Instructions are selected from the target architecture to implement the semantics of the program. The typical result will be an object file, suitable for input to a linker.
A byte is the fundamental unit of storage. Each byte has 8 bits. Each byte has a unique address. A memory location is a sequence of one or more bytes exactly large enough to hold a scalar type. Multiple threads can access separate memory locations without interference.
Memory locations come in three groups:
- Thread local memory locations are accessible from only one thread at a time.
- Immutable memory locations cannot be written to during its lifetime. Immutable memory locations can be read from by multiple threads without synchronization.
- Shared memory locations are accessible from multiple threads.
Execution of a single thread on thread local and immutable memory locations is sequentially consistent. This means the result of the operations is the same as if it were executed in the order the operations appear in the program.
A memory location can be transferred from thread local to immutable or shared if there is only one reference to the location.
A memory location can be transferred from shared to immutable or thread local if there is only one reference to the location.
A memory location can be temporarily transferred from shared to local if synchronization is used to prevent any other threads from accessing the memory location during the duration.
An object is created when one of the following is executed:
- a definition
- a NewExpression
- a temporary is created
- changing which field of a union is active
An object spans a sequence of memory locations which may or may not be contiguous. It exists during construction, its lifetime, and destruction. Each object has a type, which is determined either statically or by runtime type information. The memory locations may include any combination of thread local, immutable, or shared memory locations.
Objects can be composed into a composed object. The objects that make up the composed object are subobjects. An object that is not the subobject of another object is a complete object. The lifetime of a subobject is always within the lifetime of its complete object.
An object's address is the address of the first byte of the first memory location for that object. Object addresses are distinct from each other unless one of the objects is nested within the other.