https://wiki.dlang.org/api.php?action=feedcontributions&user=NickTreleaven&feedformat=atomD Wiki - User contributions [en]2024-03-28T22:43:59ZUser contributionsMediaWiki 1.31.2https://wiki.dlang.org/?title=Differences_With_TDPL&diff=10211Differences With TDPL2024-01-17T11:17:34Z<p>NickTreleaven: /* Synchronized Classes */ add link to tail shared issue</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias & Enum Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP42.md<br />
<br />
=== Attribute Inference for Templates and Function Literals ===<br />
http://dlang.org/function.html#function-attribute-inference<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
For example code, see:<br />
http://forum.dlang.org/post/mfjmysleuwfohoxcslpf@forum.dlang.org<br />
<br />
=== DIP25 - return ref ===<br />
https://dlang.org/spec/function.html#return-ref-parameters<br />
<br />
=== DIP60 - @nogc function attribute ===<br />
https://wiki.dlang.org/DIP60<br />
<br />
=== DIP1000 - scoped pointers ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md#fundamentals-of-scope<br />
<br />
=== DIP1010 - static foreach ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1010.md<br />
<br />
== Unimplemented / Incomplete Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Synchronized Classes ===<br />
<br />
For the most part, synchronized for classes currently acts like it does in Java with synchronized being on functions. The compiler does complain about having public members if a class is marked as synchronized, but none of the stuff like [https://issues.dlang.org/show_bug.cgi?id=24269 automatically stripping off the outer layer of shared] in member functions is implemented, and the compiler allows you to put synchronized on individual functions without putting it on the class, which TDPL explicitly says is disallowed.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet. In particular, shared has no implicit memory barriers, and it's not clear that it ever will (they're not cheap). shared is usable as-is via atomic operations (as described in TDPL) or locking mutexes (be it explicit or via synchronized), but without synchronized classes, using shared typically requires temporarily, explicitly casting shared away after protecting the object with a lock so that it can be operated on as if it were thread-local while protected by the lock.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.<br />
<br />
[[Category:Learn]]</div>NickTreleavenhttps://wiki.dlang.org/?title=DMD_Source_Guide&diff=10182DMD Source Guide2023-09-08T11:48:49Z<p>NickTreleaven: Tweak heading /* View emitted templates instances and string/mixins */</p>
<hr />
<div>== Overview ==<br />
<br />
=== Major components ===<br />
<br />
All D compilers are divided into two parts: the front-end and the back-end.<br />
<br />
The front-end (DMD-FE) implements all things D-specific: lexing and parsing D syntax, instantiating templates, producing error messages, etc. The same front-end code is used by [[DMD]], [[GDC]] and [[LDC]].<br />
<br />
The back-end is what emits machine code. It contains code generation, optimization, object file writing, etc. The back-end is specific to each D compiler: DMD uses a D-specific Boost-licensed (as of April 2017) back-end, LDC uses [[LLVM]], and GDC uses [[GCC]] for their respective back-end processing.<br />
<br />
There is also a glue layer, which is the interface between the front-end and back-end. This component is custom for each D compiler.<br />
<br />
=== Compilation cycle ===<br />
<br />
D source code goes through the following stages when compiled:<br />
<br />
* First, the file is loaded into memory as-is, and converted to UTF-8 when necessary.<br />
* The lexer transforms the file into an array of tokens. There is no structure yet at this point - just a flat list of tokens. (lexer.c)<br />
* The parser then builds a simple AST out of the token stream. (parser.c)<br />
* The AST is then semantically processed. This is done in three stages (called semantic, semantic2 and semantic3). This is done in a loop in mars.c. Each pass transforms the AST to be closer to the final representation: types are resolved, templates are instantiated, etc.<br />
:1. The "semantic" phase will analyze the full signature of all declarations. For example:<br />
::* members of aggregate type<br />
::* function parameter types and return type<br />
::* variable types<br />
::* evaluation of pragma(msg)<br />
:<br />
:2. The "semantic2" phase will analyze some additional part of the declarations, For example:<br />
::* initializer of variable declarations<br />
::* evaluation of static assert condition<br />
:<br />
:3. The "semantic3" phase will analyze the body of function declarations.<br />
::If a function is declared in the module which is not directly compiled (== not listed in the command line), semantic3 pass won't analyze its body.<br />
:<br />
:4. During each phases, some declarations will partially invoke the subsequent phases due to resolve forward reference, For example:<br />
<br />
immutable string x = "hello";<br />
static if (x == "hello") { ... }<br />
// The static if condition will invoke semantic2 of the variable 'x'<br />
<br />
auto foo() { ... }<br />
typeof(&foo) fp;<br />
// "semantic" phase of the variable 'fp' will run "semantic3" of 'foo'<br />
// to demand the full signature of the function (== infer the return type)<br />
<br />
string foo() { ... }<br />
mixin(foo());<br />
// For CTFE, the mixin declaration will invoke the semantic3 of 'foo'<br />
* Finally, the AST is handed over to the glue layer, which feeds it into the back-end, which in turn produces machine code and object files.<br />
<br />
=== Runtime interoperability ===<br />
<br />
Non-trivial operations (e.g. memory allocation, array operations) are implemented in the D runtime. The compiler integrates with the runtime using a number of so-called hook functions (which by convention have the <tt>_d_</tt> name prefix).<br />
<br />
A list can be found here: [[Runtime_Hooks]]<br />
<br />
=== Details ===<br />
<br />
''Note: This section may be considerably outdated. Please bring it up to date where you can.''<br />
<br />
There are a number of types that are stored in various nodes that are never actually used in the front end. They are merely stored and passed around as pointers. <br />
<br />
* Symbol - Appears to have something to do with the names used by the linker. Appears to be used by Dsymbol and its subclasses.<br />
* dt_t - "Data to be added to the data segment of the output object file" ''source: todt.c''<br />
* elem - A node in the internal representation.<br />
<br />
The code generator is split among the various AST nodes. Certain methods of almost every AST node are part of the code generator.<br />
<br />
(it's an interesting solution to the problem. It would have never occurred to a Java programmer)<br />
<br />
Most notably:<br />
* all Statement subclasses must define a toIR method<br />
* All Expression subclasses must define a toElem method<br />
* Initializers and certain Expression subclasses must define toDt<br />
* Declarations must define toObjFile<br />
* Dsymbol subclasses must define toSymbol<br />
<br />
==== Other things ====<br />
Floating point libraries seem to be atrociously incompatible between compilers. Replacing strtold with strtod may be necessary, for instance. (this does "break" the compiler, however: it will lose precision on literals of type 'real')<br />
-- AndyFriesen<br />
<br />
==== Intermediate Representation ====<br />
<br />
'''From [http://www.digitalmars.com/webnews/newsgroups.php?art_group=D.gnu&article_id=762 NG:D.gnu/762]'''<br />
<br />
I've been looking at trying to hook the DMD frontend up to LLVM (www.llvm.org), but I've been having some trouble. The LLVM IR (Intermediate Representation) is very well documented, but I'm having a rough time figuring out how DMD holds its IR. Since at least three people (David, Ben, and Walter) seem to have understand, I thought I'd ask for guidance.<br />
<br />
What's the best way to traverse the DMD IR once I've run the three semantic phases? As far as I can tell it's all held in the SymbolTable as a bunch of Symbols. Is there a good way to traverse that and reconstruct it into another IR?<br />
<br />
----<br />
<br />
'''From [http://www.digitalmars.com/webnews/newsgroups.php?art_group=D.gnu&article_id=764 NG:D.gnu/764]'''<br />
<br />
There isn't a generic visitor interface. Instead, there are several methods with are responsible for emiting code/data and then calling that method for child objects. Start by implementing Module::genobjfile and loop over the 'members' array, calling each Dsymbol object's toObjFile method. From there, you will need to implement these methods:<br />
<br />
Dsymbol (and descendents) ::toObjFile -- Emits code and data for objects that have generally have a symbol name and storage in memory. Containers like ClassDeclaration also have a 'members' array with child Dsymbols. Most of these are descendents of the Declaration class.<br />
<br />
Statement (and descendents) ::toIR -- Emits instructions. Usually, you just call toObjFile, toIR, toElem, etc. on the statement's fields and string the results together in the IR.<br />
<br />
Expression (and descendents) ::toElem -- Returns a back end representation of numeric constants, variable references, and operations that expression trees are composed of. This was very simple for GCC because the back end already had the code to convert expression trees to ordered instructions. If LLVM doesn't do this, I think you could generate the instructions here since LLVM has SSA.<br />
<br />
Type (and descendents) ::toCtype -- Returns the back end representation of the type. Note that a lot of classes don't override this -- you just need to do a switch on the 'ty' field in Type::toCtype.<br />
<br />
Dsymbol (and descendents) ::toSymbol -- returns the back end reference to the object. For example, FuncDeclaration::toSymbol could return a llvm::Function. These are already implemented in tocsym.c, but you will probably rewrite them to create LLVM objects. <br />
<br />
----<br />
<br />
(Thread: http://digitalmars.com/d/archives/D/gnu/762.html)<br />
<br />
==== Inliner ====<br />
<br />
DMD's inliner is part of the frontend, existing entirely in the file '''inline.c'''.<br />
<br />
This inliner is conceptually quite simple: It traverses the AST looking for function calls. Each function found is analysed for cost by adding up the number of expression nodes in its body. Anything non-inlinable counts as "maximum cost". If the total cost is below the maximum, the function call is inlined.<br />
<br />
In DMD's AST, certain statements cannot currently be represented as expressions (such as non-unrolled loops and throwing). Because of this, the inliner makes a distinction between two main types of inlining:<br />
<br />
* Converting a function call to an inline expression: This must be used whenever the function's return value is actually used. Ex: "x = foo();" or "2 + foo()".<br />
* Converting a function call to an inline statement: Used when a function's return value is ignored, or when calling a void function.<br />
<br />
Those two scenarios are inlined by mostly separate codepaths. Cost analysis is mostly the same codepath, but "inlinable as a statement" and "inlinable as an expression" are separate decisions (again, due to certain statements not being representable as expressions).<br />
<br />
The inliner is divided into four main parts:<br />
<br />
* Main entry point: '''inlineScan''' (which utilizes class '''InlineScanVisitor''' and function '''expandInline''')<br />
* Cost analysis (to determine inlinability): '''canInline''' and class '''InlineCostVisitor'''<br />
* Inlining a function call as a statement: '''inlineAsStatement''' and its embedded class '''InlineAsStatement'''<br />
* Inlining a function call as an expression: '''doInline''' and its embedded class '''InlineStatement'''<br />
<br />
===== Inliner: Main Entry Point =====<br />
<br />
The whole inliner is driven by the '''inlineScan''' function and '''InlineScanVisitor''' class, but the bulk of the real work is performed by '''expandInline''' (described in this section) and the other three main parts of the inliner (described in the following sections).<br />
<br />
The global function '''inlineScan''' is the inliner's main entry point. This uses class '''InlineScanVisitor''' to traverse the AST looking for function calls to inline, and inlining them as they're found. Whenever '''InlineScanVisitor''' finds an inlinable function call (determined by the cost analyzer), it calls '''expandInline''' to start the inlining process.<br />
<br />
'''InlineScanVisitor''' also decides whether to inline as a statement or an expression based on the type of AST node found:<br />
<br />
* '''ExpStatement''': Implies the function either has no return value, or the return value is unused. Therefore, inline as a statement (if permitted by cost analysis).<br />
* '''CallExp''': Implies the function returns a value which is used. Therefore, inline as an expression (if permitted by cost analysis).<br />
<br />
Called by '''InlineScanVisitor''', '''expandInline''' drives the actual inlining for both "as statement" and "as expression" cases. It converts the function call scaffolding, parameters and return value (if any) into the appropriate inline statement or expression. To inline the function's body, '''expandInline''' hands over to either '''inlineAsStatement''' (if inlining the call as a statement) or '''doInline''' (if inlining the call as an expression).<br />
<br />
===== Inliner: Cost Analysis =====<br />
<br />
The function '''canInline''', unsurprisingly, determines if a function can be inlined. To decide this, it uses class '''InlineCostVisitor''', which traverses the AST calculating a sum of all costs involved.<br />
<br />
'''InlineCostVisitor''' is a '''Visitor''' class which works just like any other AST visitor class in DMD, or any other usage of the [http://en.wikipedia.org/wiki/Visitor_pattern visitor pattern]: It contains a '''visit''' function for each AST node type supported by the inliner. Each '''visit''' function traverses its children nodes (if any) by calling the child node's '''accept''' function, passing the visitor class itself as an argument. Then the node's '''accept''' automatically calls its corresponding '''visit''' function.<br />
<br />
Any type of node not supported by '''InlineCostVisitor''' automatically calls a default function '''InlineCostVisitor::visit(Statement *s)''', which flags the function being analyzed as non-inlinable.<br />
<br />
The actual '''cost''' variable is slightly complicated since it's really two packed values:<br />
<br />
The low 12-bits of '''cost''' are the actual accumulated cost. A value of 1 is added for every inlinable expression node in the function's body (ex: "a+b*c" has a cost of 2: One for the multiplication and one for the addition). Anything that can't be inlined, or that the cost analyzer knows nothing about, adds a cost of '''COST_MAX'''. If this total cost, in the low 12-bits, is at least '''COST_MAX''' (determined by the helper function '''tooCostly'''), the function is considered non-inlinable.<br />
<br />
The upper bits of '''cost''' (bits 13 and up) are separate from the actual cost and keep track of whether the function can be inlined as an expression. Whenever a statement is found which can be inlined ''only'' as a statement (and cannot be converted to an expression), this is flagged by adding '''STATEMENT_COST''' to '''cost'''.<br />
<br />
Note: It looks as if at one point in time there had been a limit (or perhaps plans to eventually limit) the number of statements allowed in inlined functions, just as there's currently a limit to the number of expression nodes. But this does not currently appear to be enforced, so '''STATEMENT_COST''' is essentially used as a "this can only be inlined as a statement" flag.<br />
<br />
Sometimes expressions are evaluated for cost by simply visiting the the expression node, via the node's '''accept''' function. Other times, the helper function '''InlineCostVisitor::expressionInlineCost''' is used instead. The benefit of '''expressionInlineCost''' is it automatically halts analysis of an expression as soon as it reaches '''COST_MAX'''.<br />
<br />
The '''canInline''' function caches its results in two members of '''FuncDeclaration''': In '''ILS inlineStatusStmt''' (for inlinability as a statement) and '''ILS inlineStatusExp''' (for inlinability as an expression). '''ILS''' is an enum defined in '''declaration.h''' supporting three states: '''ILSuninitialized''' (not yet cached), '''ILSno''' (not inlinable) and '''ILSyes''' (inlinable).<br />
<br />
===== Inliner: Inlining as a Statement =====<br />
<br />
Any functions DMD is capable of inlining, can be inlined as a statement. As explained above, this is performed whenever a function call ignores the return value, or has no return value. In this case, the function's body is inlined via '''inlineAsStatement'''. Internally, '''inlineAsStatement''' works using its embedded visitor class '''InlineAsStatement'''.<br />
<br />
To paraphrase a comment in '''inline.c''', this inlining is done by converting to a statement, copying the trees of the function to be inlined, and renaming the variables. Most of this is fairly straightforward: Much like the cost analyzer's '''InlineCostVisitor''' class, the '''InlineAsStatement''' class has a '''visit''' function for each supported type of statement and expression. Each of these visitors copies the node, makes any adjustments if necessary, and then visits all subnodes by calling their '''accept''' functions.<br />
<br />
There's also a default catch-all function which asserts, indicating the cost analyzer failed to disallow something which has no corresponding visitor in '''InlineAsStatement'''.<br />
<br />
===== Inliner: Inlining as an Expression =====<br />
<br />
''Some'', but not all, inlinable functions can be inlined as an expression. This must be done whenever a function call uses the return value (Ex: "x = foo();" or "2 + foo()"). In this case, inlining the function's body as an expression works very much like inlining it as a statement (see the section above), but with a separate code path and a few differences:<br />
<br />
* The function body is inlined by '''doInline''' instead of '''inlineAsStatement'''.<br />
* There are two overloads of '''doInline''': One to inline expressions ''as'' expressions, and one to convert statements ''to'' inline expressions.<br />
* As discussed in the sections above, not all statements can be converted to expressions. Because of this, these statements' corresponding '''visit''' functions are omitted from '''doInline''', since the cost analyzer should have already prevented the inliner from attempting to inline any offending functions.<br />
<br />
===== Inliner: How to Add More Support =====<br />
<br />
If a particular statement is unsupported by the inliner (thereby preventing any function using it from being inlined), support can be added like this:<br />
<br />
* Add an overload of '''InlineCostVisitor::visit''' for the type of AST node you wish to support. Following the example of the other visit functions:<br />
:* Increase '''cost''' however is appropriate.<br />
:* Add '''STATEMENT_COST''' to '''cost''' if the statement cannot be converted to an expression (ex: '''ForStatement''' and '''ThrowStatement'''). This allows you to omit a corresponding overload of '''doInline's''' '''InlineStatement::visit'''.<br />
:* Add '''COST_MAX''' to '''cost''' for any situations that are not inlinable.<br />
:* Call '''accept''' on all subnodes. If the subnode is an expression, it may be better to use '''expressionInlineCost''' instead since this will automatically halt analysis as soon as the expression's cost reaches the maximum.<br />
* In '''inlineAsStatement''', add an overload of '''InlineAsStatement::visit''' for the appropriate AST node type. Following the example of the other visit overloads: Copy the node, make any adjustments if necessary, and traverse to all subnodes.<br />
* If the statement can be converted to an expression (ex: '''IfStatement'''), then inside the '''Statement''' overload of '''doInline''', add an overload of '''InlineStatement::visit''' for the appropriate AST node type. Following the other examples, convert the node to an expression, make any adjustments if necessary, and traverse to all subnodes.<br />
<br />
==== The Back End ====<br />
<br />
DMD's internal representation uses expression trees with 'elem' nodes (defined in el.h). The "Rosetta Stone" for understanding the backend is enum OPER in oper.h. This lists all the types of nodes which can be in an expression tree.<br />
<br />
If you compile dmd with debug on, and compile with:<br />
<br />
-O --c<br />
<br />
you'll get reports of the various optimizations done.<br />
<br />
Other useful undocumented flags:<br />
<br />
--b show block optimisation<br />
--f full output<br />
--r show register allocation<br />
--x suppress predefined C++ stuff<br />
--y show output to Intermediate Language (IL) buffer<br />
<br />
Others which are present in the back-end but not exposed as DMD flags are:<br />
debuge show exception handling info<br />
debugs show common subexpression eliminator<br />
<br />
<br />
The most important entry point from the front-end to the backend is writefunc() in out.c, which optimises a function, and then generates code for it.<br />
<br />
* writefunc() sets up the parameters, then calls codgen() to generate the code inside the function.<br />
* it generates code for each block. Then puts vars in registers.<br />
* generates function start code, does pinhole optimisation. (cod3.pinholeopt()).<br />
* does jump optimisation<br />
* emit the generated code in codout().<br />
* writes switch tables<br />
* writes exception tables (nteh_gentables() or except_gentables()<br />
<br />
In cgcod.c, blcodgen() generates code for a basic block. Deals with the way the block ends (return, switch,<br />
if, etc).<br />
<br />
cod1.gencodelem() does the codegen inside the block. It just calls codelem().<br />
<br />
cgcod.codelem() generates code for an elem. This distributes code generation depending on elem type.<br />
<br />
Most x86 integer code generation happens in cod1,cod2, cod3, cod4, and cod5.c<br />
Floating-point code generation happens in cg87. Compared to the integer code generation, the x87 code generator is extremely simple. Most importantly, it cannot cope with common subexpressions. This is the primary reason why it is less efficient than compilers from many other vendors.<br />
<br />
===== Optimiser =====<br />
The main optimiser is in go.c, optfunc().<br />
This calls:<br />
* blockopt.c blockopt(iter) -- branch optimisation on basic blocks, iter = 0 or 1.<br />
* gother.c constprop() -- constant propagation<br />
* gother.c copyprop() -- copy propagation<br />
* gother.c rmdeadass() -- remove dead assignments<br />
* gother.c verybusyexp() -- very busy expressions<br />
* gother.c deadvar() -- eliminate dead variables<br />
<br />
* gloop.c loopopt() -- remove loop invariants and induction vars. Do loop rotation<br />
<br />
* gdag.c boolopt() -- optimize booleans.<br />
* gdag.c builddags() -- common subexpressions<br />
<br />
* el.c el_convert() -- Put float and string literals into the data segment<br />
* el.c el_combine() -- merges two expressions (uses a comma-expression to join them).<br />
* glocal.c localize() -- improve expression locality<br />
<br />
<br />
* cod3.c pinholeopt() -- Performs peephole optimisation. Doesn't do much, could do a lot more.<br />
<br />
===== Code generation =====<br />
The code generation for each function is done individually. Each function is placed into its own COMDAT segment in the obj file.<br />
The function is divided into blocks, which are linear sections of code ending with a jump or other control instruction (http://en.wikipedia.org/wiki/Basic_block).<br />
<br />
===== Scheduler (cgsched.c) =====<br />
<br />
Pentium only<br />
<br />
== Source files ==<br />
<br />
''Note: This section may be considerably outdated. If it's wrong, please correct it. If it's not here, please add it.''<br />
<br />
=== Front end ===<br />
See the [https://github.com/dlang/dmd/blob/master/compiler/src/dmd/README.md official docs].<br />
<br />
{| class="wikitable" |<br />
! File || Function<br />
|-<br />
| access.d || Access check ('''private''', '''public''', '''package''' ...)<br />
|-<br />
| aliasthis.d || Implements the '''[http://digitalmars.com/d/2.0/class.html#AliasThis alias this]''' D symbol.<br />
|-<br />
| argtypes.d || Convert types for argument passing (e.g. '''char''' are passed as '''ubyte''').<br />
|-<br />
| arrayop.d || [http://digitalmars.com/d/2.0/arrays.html#array-operations Array operations] (e.g. ''a[] = b[] + c[]'').<br />
|-<br />
| attrib.d || [http://digitalmars.com/d/2.0/attribute.html Attributes] i.e. storage class ('''const''', '''@safe''' ...), linkage ('''extern(C)''' ...), protection ('''private''' ...), alignment ('''align(1)''' ...), anonymous aggregate, '''pragma''', '''static if''' and '''mixin'''.<br />
|-<br />
| bit.d || Generate bit-level read/write code. Requires backend support.<br />
|-<br />
| builtin.d || Identify and evaluate built-in functions (e.g. '''std.math.sin''')<br />
|-<br />
| dcast.d || Implicit cast, implicit conversion, and explicit cast ('''cast(T)'''), combining type in binary expression, integer promotion, and value range propagation.<br />
|-<br />
| dclass.d || Class declaration<br />
|-<br />
| clone.d || Define the implicit '''opEquals''', '''opAssign''', post blit and destructor for struct if needed, and also define the copy constructor for struct.<br />
|-<br />
| cond.d || Evaluate compile-time conditionals, i.e. '''debug''', '''version''', and '''static if'''.<br />
|-<br />
| constfold.d || Constant folding<br />
|-<br />
| cppmangle.d || Mangle D types according to [http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling Intel's Itanium C++ ABI].<br />
|-<br />
| declaration.d || Miscellaneous declarations, including '''typedef''', '''alias''', variable declarations including the implicit '''this''' declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.<br />
|-<br />
| delegatize.d || Convert an expression ''expr'' to a delegate ''{ return expr; }'' (e.g. in '''lazy''' parameter). <br />
|-<br />
| doc.d || [http://digitalmars.com/d/ddoc.html Ddoc] documentation generator ([http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.announce&article_id=1558 NG:digitalmars.D.announce/1558])<br />
|-<br />
| dsymbol.d || D symbols (i.e. variables, functions, modules, ... anything that has a name).<br />
|-<br />
| dump.d || Defines the ''Expression::dump'' method to print the content of the expression to console. Mainly for debugging.<br />
|-<br />
| e2ir.d || Expression to Intermediate Representation; requires backend support<br />
|-<br />
| eh.d || Generate exception handling tables<br />
|-<br />
| entity.d || Defines the named entities to support the ''"\&Entity;"'' escape sequence.<br />
|-<br />
| denum.d || Enum declaration<br />
|-<br />
| expression.h || Defines the bulk of the classes which represent the AST at the expression level.<br />
|-<br />
| func.d || Function declaration, also includes function/delegate literals, function alias, (static/shared) constructor/destructor/post-blit, '''invariant''', '''unittest''' and [http://digitalmars.com/d/2.0/class.html#allocators allocator/deallocator].<br />
|-<br />
| glue.d || Generate the object file for function declarations and critical sections; convert between backend types and frontend types<br />
|-<br />
| hdrgen.d || Generate headers (*.di files)<br />
|-<br />
| iasm.d || Inline assembler<br />
|-<br />
| identifier.d || Identifier (just the name).<br />
|-<br />
| idgen.d || Make id.h and id.c for defining built-in Identifier instances. Compile and run this before compiling the rest of the source. ([http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=17157 NG:digitalmars.D/17157])<br />
|-<br />
| impcvngen.d || Make impcnvtab.c for the implicit conversion table. Compile and run this before compiling the rest of the source. <br />
|-<br />
| imphint.d || Import hint, e.g. prompting to import ''std.stdio'' when using ''writeln''.<br />
|-<br />
| dimport.d || Import.<br />
|-<br />
| inifile.d || Read .ini file<br />
|-<br />
| init.d || [http://digitalmars.com/d/2.0/declaration.html#Initializer Initializers] (e.g. the ''3'' in ''int x = 3'').<br />
|-<br />
| inline.d || Compute the cost and perform inlining.<br />
|-<br />
| interpret.d || All the code which evaluates CTFE<br />
|-<br />
| irstate.d || Intermediate Representation state; requires backend support<br />
|-<br />
| json.d || Generate JSON output<br />
|-<br />
| lexer.d || Lexically analyzes the source (such as separate keywords from identifiers)<br />
|-<br />
| libelf.d || ELF object format functions<br />
|-<br />
| libmach.d || Mach-O object format functions<br />
|-<br />
| libomf.d || OMF object format functions<br />
|-<br />
| link.d || Call the linker<br />
|-<br />
| dmacro.d || Expand DDoc macros<br />
|-<br />
| mangle.d || Mangle D types and declarations<br />
|-<br />
| mars.d || Analyzes the command line arguments (also display command-line help)<br />
|-<br />
| dmodule.d || ead modules.<br />
|-<br />
| msc.d || ?<br />
|-<br />
| mtype.d || All D types.<br />
|-<br />
| opover.d || Apply operator overloading<br />
|-<br />
| optimize.d || Optimize the AST<br />
|-<br />
| parse.d || Parse tokens into AST<br />
|-<br />
| ph.d || Custom allocator to replace malloc/free<br />
|-<br />
| root/aav.d || Associative array<br />
|-<br />
| root/array.d || Dynamic array<br />
|-<br />
| root/async.d || Asynchronous input<br />
|-<br />
| root/dchar.d || Convert UTF-32 character to UTF-8 sequence<br />
|-<br />
| root/gnuc.d || Implements functions missing from GCC, specifically ''stricmp'' and ''memicmp''.<br />
|-<br />
| root/lstring.d || Length-prefixed UTF-32 string.<br />
|-<br />
| root/man.d || Start the internet browser.<br />
|-<br />
| root/port.d || Portable wrapper around compiler/system specific things. The idea is to minimize #ifdef's in the app code.<br />
|-<br />
| root/response.d || ead the [http://digitalmars.com/d/2.0/dmd-windows.html#switches response file].<br />
|-<br />
| root/rmem.d || Implementation of the storage allocator uses the standard C allocation package.<br />
|-<br />
| root/root.d || Basic functions (deal mostly with strings, files, and bits)<br />
|-<br />
| root/speller.d || Spellchecker<br />
|-<br />
| root/stringtable.d || String table<br />
|-<br />
| s2ir.d || Statement to Intermediate Representation; requires backend support<br />
|-<br />
| dscope.d || Scope<br />
|-<br />
| statement.d || Handles '''while''', '''do''', '''for''', '''foreach''', '''if''', '''pragma''', '''staticassert''', '''switch''', '''case''', '''default''' , '''break''', '''return''', '''continue''', '''synchronized''', '''try'''/'''catch'''/'''finally''', '''throw''', '''volatile''', '''goto''', and '''label'''<br />
|-<br />
| staticassert.d || '''static assert'''.<br />
|-<br />
| dstruct.d || Aggregate ('''struct''' and '''union''') declaration.<br />
|-<br />
| dtemplate.d || Everything related to '''template'''.<br />
|-<br />
| tk/ || ?<br />
|-<br />
| tocsym.d || o C symbol<br />
|-<br />
| toctype.d || Convert D type to C type for debug symbol<br />
|-<br />
| tocvdebug.d || [http://stackoverflow.com/questions/1418660/microsofts-codeview-format-specs CodeView4 debug format].<br />
|-<br />
| todt.d || ?; requires backend support<br />
|-<br />
| toelfdebug.d || Emit symbolic debug info in Dwarf2 format. Currently empty.<br />
|-<br />
| toir.d || o Intermediate Representation; requires backend support<br />
|-<br />
| toobj.d || Generate the object file for Dsymbol and declarations except functions.<br />
|-<br />
| traits.d || '''__traits'''.<br />
|-<br />
| typinf.d || Get TypeInfo from a type.<br />
|-<br />
| unialpha.d || Check if a character is a Unicode alphabet.<br />
|-<br />
| unittests.d || un functions related to unit test.<br />
|-<br />
| utf.d || UTF-8.<br />
|-<br />
| version.d || Handles '''version'''<br />
|}<br />
<br />
=== Back end ===<br />
{| class="wikitable" |<br />
! File || Function<br />
|-<br />
| html.c || Extracts D source code from .html files<br />
|}<br />
<br />
=== A few observations ===<br />
* idgen.c is not part of the compiler source at all. It is the source to a code generator which creates id.h and id.c, which defines a whole lot of Identifier instances. (presumably, these are used to represent various 'builtin' symbols that the language defines)<br />
* impcvngen.c follows the same pattern as idgen.c. It creates impcnvtab.c, which appears to describe casting rules between primitive types.<br />
* Unspurprisingly, the code is highly D-like in methodology. For instance, root.h defines an Object class which serves as a base class for most, if not all of the other classes used. Class instances are always passed by pointer and allocated on the heap.<br />
* root.h also defines String, Array, and File classes, as opposed to using STL. Curious. (a relic from the days when templates weren't as reliable as they are now?)<br />
* lots of files with .c suffixes contain C++ code. Very confusing.<br />
<br />
== Abbreviations ==<br />
<br />
You may find these abbreviations throughout the DMD source code (in identifiers and comments).<br />
<br />
==== Front-end ====<br />
; STC<br />
: STorage Class<br />
; ILS<br />
: InLine State<br />
; IR<br />
: Intermediate Representation<br />
<br />
==== Back-end ====<br />
; AE<br />
: Available Expressions <br />
; CP<br />
: Copy Propagation info.<br />
; CSE<br />
: Common Subexpression Elimination <br />
; VBE<br />
: Very Busy Expression (http://web.cs.wpi.edu/~kal/PLT/PLT9.6.html)<br />
<br />
See also: [[Commonly-Used Acronyms]]<br />
<br />
==Class hierarchy==<br />
<br />
Have a look at [[Media:dmd_ast.png]].<br />
<br />
* RootObject<br />
** Dsymbol<br />
*** AliasThis<br />
*** AttribDeclaration<br />
**** StorageClassDeclaration<br />
***** DeprecatedDeclaration<br />
**** LinkDeclaration<br />
**** ProtDeclaration<br />
**** AlignDeclaration<br />
**** AnonDeclaration<br />
**** PragmaDeclaration<br />
**** ConditionalDeclaration<br />
***** StaticIfDeclaration<br />
**** CompileDeclaration<br />
**** UserAttributeDeclaration<br />
*** Declaration<br />
**** TupleDeclaration<br />
**** AliasDeclaration<br />
**** VarDeclaration<br />
***** TypeInfoDeclaration<br />
****** TypeInfoStructDeclaration<br />
****** TypeInfoClassDeclaration<br />
****** TypeInfoInterfaceDeclaration<br />
****** TypeInfoPointerDeclaration<br />
****** TypeInfoArrayDeclaration<br />
****** TypeInfoStaticArrayDeclaration<br />
****** TypeInfoAssociativeArrayDeclaration<br />
****** TypeInfoEnumDeclaration<br />
****** TypeInfoFunctionDeclaration<br />
****** TypeInfoDelegateDeclaration<br />
****** TypeInfoTupleDeclaration<br />
****** TypeInfoConstDeclaration<br />
****** TypeInfoInvariantDeclaration<br />
****** TypeInfoSharedDeclaration<br />
****** TypeInfoWildDeclaration<br />
****** TypeInfoVectorDeclaration<br />
***** ThisDeclaration<br />
**** SymbolDeclaration<br />
**** FuncDeclaration<br />
***** FuncAliasDeclaration<br />
***** FuncLiteralDeclaration<br />
***** CtorDeclaration<br />
***** PostBlitDeclaration<br />
***** DtorDeclaration<br />
***** StaticCtorDeclaration<br />
****** SharedStaticCtorDeclaration<br />
***** StaticDtorDeclaration<br />
****** SharedStaticDtorDeclaration<br />
***** InvariantDeclaration<br />
***** UnitTestDeclaration<br />
***** NewDeclaration<br />
***** DeleteDeclaration<br />
*** ScopeDsymbol<br />
**** AggregateDeclaration<br />
***** StructDeclaration<br />
****** UnionDeclaration<br />
***** ClassDeclaration<br />
****** InterfaceDeclaration<br />
**** WithScopeSymbol<br />
**** ArrayScopeSymbol<br />
**** EnumDeclaration<br />
**** Package<br />
***** Module<br />
**** TemplateDeclaration<br />
**** TemplateInstance<br />
***** TemplateMixin<br />
*** OverloadSet<br />
*** EnumMember<br />
*** Import<br />
*** LabelDsymbol<br />
*** StaticAssert<br />
*** DebugSymbol<br />
*** VersionSymbol<br />
** Expression<br />
*** ClassReferenceExp<br />
*** VoidInitExp<br />
*** ThrownExceptionExp<br />
*** IntegerExp<br />
*** ErrorExp<br />
*** RealExp<br />
*** ComplexExp<br />
*** IdentifierExp<br />
**** DollarExp<br />
*** DsymbolExp<br />
*** ThisExp<br />
**** SuperExp<br />
*** NullExp<br />
*** StringExp<br />
*** TupleExp<br />
*** ArrayLiteralExp<br />
*** AssocArrayLiteralExp<br />
*** StructLiteralExp<br />
*** TypeExp<br />
*** ScopeExp<br />
*** TemplateExp<br />
*** NewExp<br />
*** NewAnonClassExp<br />
*** SymbolExp<br />
**** SymOffExp<br />
**** VarExp<br />
*** OverExp<br />
*** FuncExp<br />
*** DeclarationExp<br />
*** TypeidExp<br />
*** TraitsExp<br />
*** HaltExp<br />
*** IsExp<br />
*** UnaExp<br />
**** CompileExp<br />
**** AssertExp<br />
**** DotIdExp<br />
**** DotTemplateExp<br />
**** DotVarExp<br />
**** DotTemplateInstanceExp<br />
**** DelegateExp<br />
**** DotTypeExp<br />
**** CallExp<br />
**** AddrExp<br />
**** PtrExp<br />
**** NegExp<br />
**** UAddExp<br />
**** ComExp<br />
**** NotExp<br />
**** DeleteExp<br />
**** CastExp<br />
**** VectorExp<br />
**** SliceExp<br />
**** ArrayLengthExp<br />
**** ArrayExp<br />
**** PreExp<br />
*** BinExp<br />
**** BinAssignExp<br />
***** AddAssignExp<br />
***** MinAssignExp<br />
***** MulAssignExp<br />
***** DivAssignExp<br />
***** ModAssignExp<br />
***** AndAssignExp<br />
***** OrAssignExp<br />
***** XorAssignExp<br />
***** PowAssignExp<br />
***** ShlAssignExp<br />
***** ShrAssignExp<br />
***** UshrAssignExp<br />
***** CatAssignExp<br />
**** DotExp<br />
**** CommaExp<br />
**** IndexExp<br />
**** PostExp<br />
**** AssignExp<br />
***** ConstructExp<br />
**** AddExp<br />
**** MinExp<br />
**** CatExp<br />
**** MulExp<br />
**** DivExp<br />
**** ModExp<br />
**** PowExp<br />
**** ShlExp<br />
**** ShrExp<br />
**** UshrExp<br />
**** AndExp<br />
**** OrExp<br />
**** XorExp<br />
**** OrOrExp<br />
**** AndAndExp<br />
**** CmpExp<br />
**** InExp<br />
**** RemoveExp<br />
**** EqualExp<br />
**** IdentityExp<br />
**** CondExp<br />
*** DefaultInitExp<br />
**** FileInitExp<br />
**** LineInitExp<br />
**** ModuleInitExp<br />
**** FuncInitExp<br />
**** PrettyFuncInitExp<br />
** Identifier<br />
** Initializer<br />
*** VoidInitializer<br />
*** ErrorInitializer<br />
*** StructInitializer<br />
*** ArrayInitializer<br />
*** ExpInitializer<br />
** Type<br />
*** TypeError<br />
*** TypeNext<br />
**** TypeArray<br />
***** TypeSArray<br />
***** TypeDArray<br />
***** TypeAArray<br />
**** TypePointer<br />
**** TypeReference<br />
**** TypeFunction<br />
**** TypeDelegate<br />
**** TypeSlice<br />
*** TypeBasic<br />
*** TypeVector<br />
*** TypeQualified<br />
**** TypeIdentifier<br />
**** TypeInstance<br />
**** TypeTypeof<br />
**** TypeReturn<br />
*** TypeStruct<br />
*** TypeEnum<br />
*** TypeClass<br />
*** TypeTuple<br />
*** TypeNull<br />
** Parameter<br />
** Statement<br />
*** ErrorStatement<br />
*** PeelStatement<br />
*** ExpStatement<br />
**** DtorExpStatement<br />
*** CompileStatement<br />
*** CompoundStatement<br />
**** CompoundDeclarationStatement<br />
*** UnrolledLoopStatement<br />
*** ScopeStatement<br />
*** WhileStatement<br />
*** DoStatement<br />
*** ForStatement<br />
*** ForeachStatement<br />
*** ForeachRangeStatement<br />
*** IfStatement<br />
*** ConditionalStatement<br />
*** PragmaStatement<br />
*** StaticAssertStatement<br />
*** SwitchStatement<br />
*** CaseStatement<br />
*** CaseRangeStatement<br />
*** DefaultStatement<br />
*** GotoDefaultStatement<br />
*** GotoCaseStatement<br />
*** SwitchErrorStatement<br />
*** ReturnStatement<br />
*** BreakStatement<br />
*** ContinueStatement<br />
*** SynchronizedStatement<br />
*** WithStatement<br />
*** TryCatchStatement<br />
*** TryFinallyStatement<br />
*** OnScopeStatement<br />
*** ThrowStatement<br />
*** DebugStatement<br />
*** GotoStatement<br />
*** LabelStatement<br />
*** AsmStatement<br />
*** ImportStatement<br />
** Catch<br />
** Tuple<br />
** DsymbolTable<br />
** Condition<br />
*** DVCondition<br />
**** DebugCondition<br />
**** VersionCondition<br />
*** StaticIfCondition<br />
* Visitor<br />
** StoppableVisitor<br />
* Lexer<br />
** Parser<br />
* Library<br />
<br />
== DMD Hacking Tips & Tricks ==<br />
<br />
=== Use printf-style debugging without too much visual noise ===<br />
<br />
There are many commented-out '''printf''' statements in the DMD front-end. You can uncomment them<br />
during debugging, but often you may only want to enable them for a specific symbol. One simple<br />
workaround is to enable printing when the name of the symbol matches the symbol you're debugging,<br />
for example:<br />
<br />
<syntaxhighlight lang="d"><br />
void semantic(Scope* sc)<br />
{<br />
// only do printouts if this is our target symbol<br />
if (!strcmp(toChars, "test_struct"));<br />
printf("this=%p, %s '%s', sizeok = %d\n", this, parent.toChars, toChars, sizeok);<br />
}<br />
</syntaxhighlight><br />
<br />
=== Find which module instantiated a specific template instance ===<br />
<br />
Templates have a '''instantiatingModule''' field which you can inspect. Here's an example from '''glue.d''':<br />
<br />
<syntaxhighlight lang="d"><br />
/* Skip generating code if this part of a TemplateInstance that is instantiated<br />
* only by non-root modules (i.e. modules not listed on the command line).<br />
*/<br />
TemplateInstance* ti = inTemplateInstance();<br />
if (!global.params.useUnitTests &&<br />
ti && ti.instantiatingModule && !ti.instantiatingModule.root)<br />
{<br />
//printf("instantiated by %s %s\n", ti.instantiatingModule.toChars(), ti.toChars());<br />
return;<br />
}<br />
</syntaxhighlight><br />
<br />
=== View lowerings, emitted templates instances and string/mixins ===<br />
<br />
The <tt>-vcg-ast</tt> switch will generate a .cg-file next to the compiled code source-code<br />
Which will contain the source representation of the AST just before code-generation<br />
(That means the last stage of compilation)<br />
This helps to debug templates as well spot issues with the inliner<br />
NOTE: for this to work the code has to reach the codegen stage i.e is has to compile without error<br />
<br />
<syntaxhighlight lang="d"><br />
void main() {<br />
foreach (i; 0 .. 10) {<br />
mixin("auto a = i;");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="bash"><br />
dmd -vcg-ast test.d<br />
</syntaxhighlight><br />
<br />
Which will generated a file <tt>test.d.cg</tt>:<br />
<br />
<syntaxhighlight lang="d"><br />
import object;<br />
void main()<br />
{<br />
{<br />
int __key2 = 0;<br />
int __limit3 = 10;<br />
for (; __key2 < __limit3; __key2 += 1)<br />
{<br />
int i = __key2;<br />
int a = i;<br />
}<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Determine if a DMD 'Type' is an actual type, expression, or a symbol ===<br />
<br />
You can use the '''resolve''' virtual function to determine this:<br />
<br />
<syntaxhighlight lang="d"><br />
RootObject* o = ...;<br />
Type* srcType = isType(o);<br />
<br />
if (srcType)<br />
{<br />
Type* t;<br />
Expression* e;<br />
Dsymbol* s;<br />
srcType.resolve(loc, sc, &e, &t, &s);<br />
<br />
if (t) { } // it's a type<br />
else if (e) { } // it's an expression<br />
else if (s) { } // it's a symbol<br />
}<br />
</syntaxhighlight><br />
<br />
You can see examples of this technique being used in the '''traits.d''' file.<br />
<br />
=== Get the string representation of a DSymbol ===<br />
<br />
A '''DSymbol''' has the two functions '''toChars()''' and '''toPrettyChars()''',<br />
which are useful for debugging. The former prints out the name of the symbol,<br />
while the latter may print out the fully-scoped name of the symbol. For example:<br />
<br />
<syntaxhighlight lang="d"><br />
StructDeclaration* sd = ...; // assuming struct named "Bar" inside module named "Foo"<br />
printf("name: %s\n", sd.toChars()); // prints out "Bar"<br />
printf("fully qualified name: %s\n", sd.toPrettyChars()); // prints out "Foo.Bar"<br />
</syntaxhighlight><br />
<br />
=== Get the string representation of the kind of a DSymbol ===<br />
<br />
All '''DSymbol'''-inherited classes implement the '''kind''' virtual method,<br />
which enable you to use printf-style debugging, e.g.:<br />
<br />
<syntaxhighlight lang="d"><br />
EnumDeclaration* ed = ...;<br />
DSymbol* s = ed;<br />
printf("%s\n", s.kind()); // prints "enum". See 'EnumDeclaration.kind'.<br />
</syntaxhighlight><br />
<br />
=== Get the string representation of the dynamic type of an ast-node ===<br />
There is a helper module called '''asttypename''' which allows you to print the dynamic type of an ast-node<br />
This is useful when implementing your own visitors. <br />
<br />
<syntaxhighlight lang="d"><br />
import dmd.asttypename;<br />
Expression ex = new AndAndExp(...);<br />
writeln(ex.astTypeName); // prints "AndAndExp".<br />
</syntaxhighlight><br />
<br />
=== Get the string representation of an operator or token ===<br />
<br />
'''Expression''' objects hold an '''op''' field, which is a '''TOK''' type (a token).<br />
To print out the string representation of the token, index into the static array '''Token.toChars''':<br />
<br />
<syntaxhighlight lang="d"><br />
Expression* e = ...;<br />
printf("Expression op: %s ", Token.toChars(e.op));<br />
</syntaxhighlight><br />
<br />
=== Print the value of a floating-point literal ===<br />
<br />
To print the value of an expression which is a floating-point literal (a value known at compile-time),<br />
use the '''toReal()''' member function:<br />
<br />
<syntaxhighlight lang="d"><br />
if (exp.op == TOKfloat32 || exp.op == TOKfloat64 || exp.op == TOKfloat80)<br />
printf("%Lf", exp.toReal());<br />
</syntaxhighlight><br />
<br />
=== Check whether an expression is a compile-time known literal ===<br />
<br />
Use the '''isConst()''' method to check if an '''Expression''' is a compile-time known literal.<br />
The name '''isConst()''' is a misnomer, but this name predates D2 and was more relevant to D1.<br />
Please note that '''isConst()''' is also a method of '''Type''', but is unrelated to the<br />
equally named function in the '''Expression''' class.<br />
<br />
=== Note the difference between two mixin types: compile declarations and compile statements ===<br />
<br />
Take this example D code:<br />
<br />
<syntaxhighlight lang="D"><br />
mixin("int x;");<br />
<br />
void main()<br />
{<br />
mixin("int y;");<br />
}<br />
</syntaxhighlight><br />
<br />
The first mixin is a '''CompileDeclaration''', while the second is a '''CompileStatement'''.<br />
These are separate classes in the DMD front-end.<br />
<br />
<br />
[[Category:DMD Compiler]]</div>NickTreleavenhttps://wiki.dlang.org/?title=DMD_Source_Guide&diff=10145DMD Source Guide2023-02-01T21:18:44Z<p>NickTreleaven: /* Front end */ Add link to dmd/README.md; fix keyword filenames</p>
<hr />
<div>== Overview ==<br />
<br />
=== Major components ===<br />
<br />
All D compilers are divided into two parts: the front-end and the back-end.<br />
<br />
The front-end (DMD-FE) implements all things D-specific: lexing and parsing D syntax, instantiating templates, producing error messages, etc. The same front-end code is used by [[DMD]], [[GDC]] and [[LDC]].<br />
<br />
The back-end is what emits machine code. It contains code generation, optimization, object file writing, etc. The back-end is specific to each D compiler: DMD uses a D-specific Boost-licensed (as of April 2017) back-end, LDC uses [[LLVM]], and GDC uses [[GCC]] for their respective back-end processing.<br />
<br />
There is also a glue layer, which is the interface between the front-end and back-end. This component is custom for each D compiler.<br />
<br />
=== Compilation cycle ===<br />
<br />
D source code goes through the following stages when compiled:<br />
<br />
* First, the file is loaded into memory as-is, and converted to UTF-8 when necessary.<br />
* The lexer transforms the file into an array of tokens. There is no structure yet at this point - just a flat list of tokens. (lexer.c)<br />
* The parser then builds a simple AST out of the token stream. (parser.c)<br />
* The AST is then semantically processed. This is done in three stages (called semantic, semantic2 and semantic3). This is done in a loop in mars.c. Each pass transforms the AST to be closer to the final representation: types are resolved, templates are instantiated, etc.<br />
:1. The "semantic" phase will analyze the full signature of all declarations. For example:<br />
::* members of aggregate type<br />
::* function parameter types and return type<br />
::* variable types<br />
::* evaluation of pragma(msg)<br />
:<br />
:2. The "semantic2" phase will analyze some additional part of the declarations, For example:<br />
::* initializer of variable declarations<br />
::* evaluation of static assert condition<br />
:<br />
:3. The "semantic3" phase will analyze the body of function declarations.<br />
::If a function is declared in the module which is not directly compiled (== not listed in the command line), semantic3 pass won't analyze its body.<br />
:<br />
:4. During each phases, some declarations will partially invoke the subsequent phases due to resolve forward reference, For example:<br />
<br />
immutable string x = "hello";<br />
static if (x == "hello") { ... }<br />
// The static if condition will invoke semantic2 of the variable 'x'<br />
<br />
auto foo() { ... }<br />
typeof(&foo) fp;<br />
// "semantic" phase of the variable 'fp' will run "semantic3" of 'foo'<br />
// to demand the full signature of the function (== infer the return type)<br />
<br />
string foo() { ... }<br />
mixin(foo());<br />
// For CTFE, the mixin declaration will invoke the semantic3 of 'foo'<br />
* Finally, the AST is handed over to the glue layer, which feeds it into the back-end, which in turn produces machine code and object files.<br />
<br />
=== Runtime interoperability ===<br />
<br />
Non-trivial operations (e.g. memory allocation, array operations) are implemented in the D runtime. The compiler integrates with the runtime using a number of so-called hook functions (which by convention have the <tt>_d_</tt> name prefix).<br />
<br />
A list can be found here: [[Runtime_Hooks]]<br />
<br />
=== Details ===<br />
<br />
''Note: This section may be considerably outdated. Please bring it up to date where you can.''<br />
<br />
There are a number of types that are stored in various nodes that are never actually used in the front end. They are merely stored and passed around as pointers. <br />
<br />
* Symbol - Appears to have something to do with the names used by the linker. Appears to be used by Dsymbol and its subclasses.<br />
* dt_t - "Data to be added to the data segment of the output object file" ''source: todt.c''<br />
* elem - A node in the internal representation.<br />
<br />
The code generator is split among the various AST nodes. Certain methods of almost every AST node are part of the code generator.<br />
<br />
(it's an interesting solution to the problem. It would have never occurred to a Java programmer)<br />
<br />
Most notably:<br />
* all Statement subclasses must define a toIR method<br />
* All Expression subclasses must define a toElem method<br />
* Initializers and certain Expression subclasses must define toDt<br />
* Declarations must define toObjFile<br />
* Dsymbol subclasses must define toSymbol<br />
<br />
==== Other things ====<br />
Floating point libraries seem to be atrociously incompatible between compilers. Replacing strtold with strtod may be necessary, for instance. (this does "break" the compiler, however: it will lose precision on literals of type 'real')<br />
-- AndyFriesen<br />
<br />
==== Intermediate Representation ====<br />
<br />
'''From [http://www.digitalmars.com/webnews/newsgroups.php?art_group=D.gnu&article_id=762 NG:D.gnu/762]'''<br />
<br />
I've been looking at trying to hook the DMD frontend up to LLVM (www.llvm.org), but I've been having some trouble. The LLVM IR (Intermediate Representation) is very well documented, but I'm having a rough time figuring out how DMD holds its IR. Since at least three people (David, Ben, and Walter) seem to have understand, I thought I'd ask for guidance.<br />
<br />
What's the best way to traverse the DMD IR once I've run the three semantic phases? As far as I can tell it's all held in the SymbolTable as a bunch of Symbols. Is there a good way to traverse that and reconstruct it into another IR?<br />
<br />
----<br />
<br />
'''From [http://www.digitalmars.com/webnews/newsgroups.php?art_group=D.gnu&article_id=764 NG:D.gnu/764]'''<br />
<br />
There isn't a generic visitor interface. Instead, there are several methods with are responsible for emiting code/data and then calling that method for child objects. Start by implementing Module::genobjfile and loop over the 'members' array, calling each Dsymbol object's toObjFile method. From there, you will need to implement these methods:<br />
<br />
Dsymbol (and descendents) ::toObjFile -- Emits code and data for objects that have generally have a symbol name and storage in memory. Containers like ClassDeclaration also have a 'members' array with child Dsymbols. Most of these are descendents of the Declaration class.<br />
<br />
Statement (and descendents) ::toIR -- Emits instructions. Usually, you just call toObjFile, toIR, toElem, etc. on the statement's fields and string the results together in the IR.<br />
<br />
Expression (and descendents) ::toElem -- Returns a back end representation of numeric constants, variable references, and operations that expression trees are composed of. This was very simple for GCC because the back end already had the code to convert expression trees to ordered instructions. If LLVM doesn't do this, I think you could generate the instructions here since LLVM has SSA.<br />
<br />
Type (and descendents) ::toCtype -- Returns the back end representation of the type. Note that a lot of classes don't override this -- you just need to do a switch on the 'ty' field in Type::toCtype.<br />
<br />
Dsymbol (and descendents) ::toSymbol -- returns the back end reference to the object. For example, FuncDeclaration::toSymbol could return a llvm::Function. These are already implemented in tocsym.c, but you will probably rewrite them to create LLVM objects. <br />
<br />
----<br />
<br />
(Thread: http://digitalmars.com/d/archives/D/gnu/762.html)<br />
<br />
==== Inliner ====<br />
<br />
DMD's inliner is part of the frontend, existing entirely in the file '''inline.c'''.<br />
<br />
This inliner is conceptually quite simple: It traverses the AST looking for function calls. Each function found is analysed for cost by adding up the number of expression nodes in its body. Anything non-inlinable counts as "maximum cost". If the total cost is below the maximum, the function call is inlined.<br />
<br />
In DMD's AST, certain statements cannot currently be represented as expressions (such as non-unrolled loops and throwing). Because of this, the inliner makes a distinction between two main types of inlining:<br />
<br />
* Converting a function call to an inline expression: This must be used whenever the function's return value is actually used. Ex: "x = foo();" or "2 + foo()".<br />
* Converting a function call to an inline statement: Used when a function's return value is ignored, or when calling a void function.<br />
<br />
Those two scenarios are inlined by mostly separate codepaths. Cost analysis is mostly the same codepath, but "inlinable as a statement" and "inlinable as an expression" are separate decisions (again, due to certain statements not being representable as expressions).<br />
<br />
The inliner is divided into four main parts:<br />
<br />
* Main entry point: '''inlineScan''' (which utilizes class '''InlineScanVisitor''' and function '''expandInline''')<br />
* Cost analysis (to determine inlinability): '''canInline''' and class '''InlineCostVisitor'''<br />
* Inlining a function call as a statement: '''inlineAsStatement''' and its embedded class '''InlineAsStatement'''<br />
* Inlining a function call as an expression: '''doInline''' and its embedded class '''InlineStatement'''<br />
<br />
===== Inliner: Main Entry Point =====<br />
<br />
The whole inliner is driven by the '''inlineScan''' function and '''InlineScanVisitor''' class, but the bulk of the real work is performed by '''expandInline''' (described in this section) and the other three main parts of the inliner (described in the following sections).<br />
<br />
The global function '''inlineScan''' is the inliner's main entry point. This uses class '''InlineScanVisitor''' to traverse the AST looking for function calls to inline, and inlining them as they're found. Whenever '''InlineScanVisitor''' finds an inlinable function call (determined by the cost analyzer), it calls '''expandInline''' to start the inlining process.<br />
<br />
'''InlineScanVisitor''' also decides whether to inline as a statement or an expression based on the type of AST node found:<br />
<br />
* '''ExpStatement''': Implies the function either has no return value, or the return value is unused. Therefore, inline as a statement (if permitted by cost analysis).<br />
* '''CallExp''': Implies the function returns a value which is used. Therefore, inline as an expression (if permitted by cost analysis).<br />
<br />
Called by '''InlineScanVisitor''', '''expandInline''' drives the actual inlining for both "as statement" and "as expression" cases. It converts the function call scaffolding, parameters and return value (if any) into the appropriate inline statement or expression. To inline the function's body, '''expandInline''' hands over to either '''inlineAsStatement''' (if inlining the call as a statement) or '''doInline''' (if inlining the call as an expression).<br />
<br />
===== Inliner: Cost Analysis =====<br />
<br />
The function '''canInline''', unsurprisingly, determines if a function can be inlined. To decide this, it uses class '''InlineCostVisitor''', which traverses the AST calculating a sum of all costs involved.<br />
<br />
'''InlineCostVisitor''' is a '''Visitor''' class which works just like any other AST visitor class in DMD, or any other usage of the [http://en.wikipedia.org/wiki/Visitor_pattern visitor pattern]: It contains a '''visit''' function for each AST node type supported by the inliner. Each '''visit''' function traverses its children nodes (if any) by calling the child node's '''accept''' function, passing the visitor class itself as an argument. Then the node's '''accept''' automatically calls its corresponding '''visit''' function.<br />
<br />
Any type of node not supported by '''InlineCostVisitor''' automatically calls a default function '''InlineCostVisitor::visit(Statement *s)''', which flags the function being analyzed as non-inlinable.<br />
<br />
The actual '''cost''' variable is slightly complicated since it's really two packed values:<br />
<br />
The low 12-bits of '''cost''' are the actual accumulated cost. A value of 1 is added for every inlinable expression node in the function's body (ex: "a+b*c" has a cost of 2: One for the multiplication and one for the addition). Anything that can't be inlined, or that the cost analyzer knows nothing about, adds a cost of '''COST_MAX'''. If this total cost, in the low 12-bits, is at least '''COST_MAX''' (determined by the helper function '''tooCostly'''), the function is considered non-inlinable.<br />
<br />
The upper bits of '''cost''' (bits 13 and up) are separate from the actual cost and keep track of whether the function can be inlined as an expression. Whenever a statement is found which can be inlined ''only'' as a statement (and cannot be converted to an expression), this is flagged by adding '''STATEMENT_COST''' to '''cost'''.<br />
<br />
Note: It looks as if at one point in time there had been a limit (or perhaps plans to eventually limit) the number of statements allowed in inlined functions, just as there's currently a limit to the number of expression nodes. But this does not currently appear to be enforced, so '''STATEMENT_COST''' is essentially used as a "this can only be inlined as a statement" flag.<br />
<br />
Sometimes expressions are evaluated for cost by simply visiting the the expression node, via the node's '''accept''' function. Other times, the helper function '''InlineCostVisitor::expressionInlineCost''' is used instead. The benefit of '''expressionInlineCost''' is it automatically halts analysis of an expression as soon as it reaches '''COST_MAX'''.<br />
<br />
The '''canInline''' function caches its results in two members of '''FuncDeclaration''': In '''ILS inlineStatusStmt''' (for inlinability as a statement) and '''ILS inlineStatusExp''' (for inlinability as an expression). '''ILS''' is an enum defined in '''declaration.h''' supporting three states: '''ILSuninitialized''' (not yet cached), '''ILSno''' (not inlinable) and '''ILSyes''' (inlinable).<br />
<br />
===== Inliner: Inlining as a Statement =====<br />
<br />
Any functions DMD is capable of inlining, can be inlined as a statement. As explained above, this is performed whenever a function call ignores the return value, or has no return value. In this case, the function's body is inlined via '''inlineAsStatement'''. Internally, '''inlineAsStatement''' works using its embedded visitor class '''InlineAsStatement'''.<br />
<br />
To paraphrase a comment in '''inline.c''', this inlining is done by converting to a statement, copying the trees of the function to be inlined, and renaming the variables. Most of this is fairly straightforward: Much like the cost analyzer's '''InlineCostVisitor''' class, the '''InlineAsStatement''' class has a '''visit''' function for each supported type of statement and expression. Each of these visitors copies the node, makes any adjustments if necessary, and then visits all subnodes by calling their '''accept''' functions.<br />
<br />
There's also a default catch-all function which asserts, indicating the cost analyzer failed to disallow something which has no corresponding visitor in '''InlineAsStatement'''.<br />
<br />
===== Inliner: Inlining as an Expression =====<br />
<br />
''Some'', but not all, inlinable functions can be inlined as an expression. This must be done whenever a function call uses the return value (Ex: "x = foo();" or "2 + foo()"). In this case, inlining the function's body as an expression works very much like inlining it as a statement (see the section above), but with a separate code path and a few differences:<br />
<br />
* The function body is inlined by '''doInline''' instead of '''inlineAsStatement'''.<br />
* There are two overloads of '''doInline''': One to inline expressions ''as'' expressions, and one to convert statements ''to'' inline expressions.<br />
* As discussed in the sections above, not all statements can be converted to expressions. Because of this, these statements' corresponding '''visit''' functions are omitted from '''doInline''', since the cost analyzer should have already prevented the inliner from attempting to inline any offending functions.<br />
<br />
===== Inliner: How to Add More Support =====<br />
<br />
If a particular statement is unsupported by the inliner (thereby preventing any function using it from being inlined), support can be added like this:<br />
<br />
* Add an overload of '''InlineCostVisitor::visit''' for the type of AST node you wish to support. Following the example of the other visit functions:<br />
:* Increase '''cost''' however is appropriate.<br />
:* Add '''STATEMENT_COST''' to '''cost''' if the statement cannot be converted to an expression (ex: '''ForStatement''' and '''ThrowStatement'''). This allows you to omit a corresponding overload of '''doInline's''' '''InlineStatement::visit'''.<br />
:* Add '''COST_MAX''' to '''cost''' for any situations that are not inlinable.<br />
:* Call '''accept''' on all subnodes. If the subnode is an expression, it may be better to use '''expressionInlineCost''' instead since this will automatically halt analysis as soon as the expression's cost reaches the maximum.<br />
* In '''inlineAsStatement''', add an overload of '''InlineAsStatement::visit''' for the appropriate AST node type. Following the example of the other visit overloads: Copy the node, make any adjustments if necessary, and traverse to all subnodes.<br />
* If the statement can be converted to an expression (ex: '''IfStatement'''), then inside the '''Statement''' overload of '''doInline''', add an overload of '''InlineStatement::visit''' for the appropriate AST node type. Following the other examples, convert the node to an expression, make any adjustments if necessary, and traverse to all subnodes.<br />
<br />
==== The Back End ====<br />
<br />
DMD's internal representation uses expression trees with 'elem' nodes (defined in el.h). The "Rosetta Stone" for understanding the backend is enum OPER in oper.h. This lists all the types of nodes which can be in an expression tree.<br />
<br />
If you compile dmd with debug on, and compile with:<br />
<br />
-O --c<br />
<br />
you'll get reports of the various optimizations done.<br />
<br />
Other useful undocumented flags:<br />
<br />
--b show block optimisation<br />
--f full output<br />
--r show register allocation<br />
--x suppress predefined C++ stuff<br />
--y show output to Intermediate Language (IL) buffer<br />
<br />
Others which are present in the back-end but not exposed as DMD flags are:<br />
debuge show exception handling info<br />
debugs show common subexpression eliminator<br />
<br />
<br />
The most important entry point from the front-end to the backend is writefunc() in out.c, which optimises a function, and then generates code for it.<br />
<br />
* writefunc() sets up the parameters, then calls codgen() to generate the code inside the function.<br />
* it generates code for each block. Then puts vars in registers.<br />
* generates function start code, does pinhole optimisation. (cod3.pinholeopt()).<br />
* does jump optimisation<br />
* emit the generated code in codout().<br />
* writes switch tables<br />
* writes exception tables (nteh_gentables() or except_gentables()<br />
<br />
In cgcod.c, blcodgen() generates code for a basic block. Deals with the way the block ends (return, switch,<br />
if, etc).<br />
<br />
cod1.gencodelem() does the codegen inside the block. It just calls codelem().<br />
<br />
cgcod.codelem() generates code for an elem. This distributes code generation depending on elem type.<br />
<br />
Most x86 integer code generation happens in cod1,cod2, cod3, cod4, and cod5.c<br />
Floating-point code generation happens in cg87. Compared to the integer code generation, the x87 code generator is extremely simple. Most importantly, it cannot cope with common subexpressions. This is the primary reason why it is less efficient than compilers from many other vendors.<br />
<br />
===== Optimiser =====<br />
The main optimiser is in go.c, optfunc().<br />
This calls:<br />
* blockopt.c blockopt(iter) -- branch optimisation on basic blocks, iter = 0 or 1.<br />
* gother.c constprop() -- constant propagation<br />
* gother.c copyprop() -- copy propagation<br />
* gother.c rmdeadass() -- remove dead assignments<br />
* gother.c verybusyexp() -- very busy expressions<br />
* gother.c deadvar() -- eliminate dead variables<br />
<br />
* gloop.c loopopt() -- remove loop invariants and induction vars. Do loop rotation<br />
<br />
* gdag.c boolopt() -- optimize booleans.<br />
* gdag.c builddags() -- common subexpressions<br />
<br />
* el.c el_convert() -- Put float and string literals into the data segment<br />
* el.c el_combine() -- merges two expressions (uses a comma-expression to join them).<br />
* glocal.c localize() -- improve expression locality<br />
<br />
<br />
* cod3.c pinholeopt() -- Performs peephole optimisation. Doesn't do much, could do a lot more.<br />
<br />
===== Code generation =====<br />
The code generation for each function is done individually. Each function is placed into its own COMDAT segment in the obj file.<br />
The function is divided into blocks, which are linear sections of code ending with a jump or other control instruction (http://en.wikipedia.org/wiki/Basic_block).<br />
<br />
===== Scheduler (cgsched.c) =====<br />
<br />
Pentium only<br />
<br />
== Source files ==<br />
<br />
''Note: This section may be considerably outdated. If it's wrong, please correct it. If it's not here, please add it.''<br />
<br />
=== Front end ===<br />
See the [https://github.com/dlang/dmd/blob/master/compiler/src/dmd/README.md official docs].<br />
<br />
{| class="wikitable" |<br />
! File || Function<br />
|-<br />
| access.d || Access check ('''private''', '''public''', '''package''' ...)<br />
|-<br />
| aliasthis.d || Implements the '''[http://digitalmars.com/d/2.0/class.html#AliasThis alias this]''' D symbol.<br />
|-<br />
| argtypes.d || Convert types for argument passing (e.g. '''char''' are passed as '''ubyte''').<br />
|-<br />
| arrayop.d || [http://digitalmars.com/d/2.0/arrays.html#array-operations Array operations] (e.g. ''a[] = b[] + c[]'').<br />
|-<br />
| attrib.d || [http://digitalmars.com/d/2.0/attribute.html Attributes] i.e. storage class ('''const''', '''@safe''' ...), linkage ('''extern(C)''' ...), protection ('''private''' ...), alignment ('''align(1)''' ...), anonymous aggregate, '''pragma''', '''static if''' and '''mixin'''.<br />
|-<br />
| bit.d || Generate bit-level read/write code. Requires backend support.<br />
|-<br />
| builtin.d || Identify and evaluate built-in functions (e.g. '''std.math.sin''')<br />
|-<br />
| dcast.d || Implicit cast, implicit conversion, and explicit cast ('''cast(T)'''), combining type in binary expression, integer promotion, and value range propagation.<br />
|-<br />
| dclass.d || Class declaration<br />
|-<br />
| clone.d || Define the implicit '''opEquals''', '''opAssign''', post blit and destructor for struct if needed, and also define the copy constructor for struct.<br />
|-<br />
| cond.d || Evaluate compile-time conditionals, i.e. '''debug''', '''version''', and '''static if'''.<br />
|-<br />
| constfold.d || Constant folding<br />
|-<br />
| cppmangle.d || Mangle D types according to [http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling Intel's Itanium C++ ABI].<br />
|-<br />
| declaration.d || Miscellaneous declarations, including '''typedef''', '''alias''', variable declarations including the implicit '''this''' declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.<br />
|-<br />
| delegatize.d || Convert an expression ''expr'' to a delegate ''{ return expr; }'' (e.g. in '''lazy''' parameter). <br />
|-<br />
| doc.d || [http://digitalmars.com/d/ddoc.html Ddoc] documentation generator ([http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.announce&article_id=1558 NG:digitalmars.D.announce/1558])<br />
|-<br />
| dsymbol.d || D symbols (i.e. variables, functions, modules, ... anything that has a name).<br />
|-<br />
| dump.d || Defines the ''Expression::dump'' method to print the content of the expression to console. Mainly for debugging.<br />
|-<br />
| e2ir.d || Expression to Intermediate Representation; requires backend support<br />
|-<br />
| eh.d || Generate exception handling tables<br />
|-<br />
| entity.d || Defines the named entities to support the ''"\&Entity;"'' escape sequence.<br />
|-<br />
| denum.d || Enum declaration<br />
|-<br />
| expression.h || Defines the bulk of the classes which represent the AST at the expression level.<br />
|-<br />
| func.d || Function declaration, also includes function/delegate literals, function alias, (static/shared) constructor/destructor/post-blit, '''invariant''', '''unittest''' and [http://digitalmars.com/d/2.0/class.html#allocators allocator/deallocator].<br />
|-<br />
| glue.d || Generate the object file for function declarations and critical sections; convert between backend types and frontend types<br />
|-<br />
| hdrgen.d || Generate headers (*.di files)<br />
|-<br />
| iasm.d || Inline assembler<br />
|-<br />
| identifier.d || Identifier (just the name).<br />
|-<br />
| idgen.d || Make id.h and id.c for defining built-in Identifier instances. Compile and run this before compiling the rest of the source. ([http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=17157 NG:digitalmars.D/17157])<br />
|-<br />
| impcvngen.d || Make impcnvtab.c for the implicit conversion table. Compile and run this before compiling the rest of the source. <br />
|-<br />
| imphint.d || Import hint, e.g. prompting to import ''std.stdio'' when using ''writeln''.<br />
|-<br />
| dimport.d || Import.<br />
|-<br />
| inifile.d || Read .ini file<br />
|-<br />
| init.d || [http://digitalmars.com/d/2.0/declaration.html#Initializer Initializers] (e.g. the ''3'' in ''int x = 3'').<br />
|-<br />
| inline.d || Compute the cost and perform inlining.<br />
|-<br />
| interpret.d || All the code which evaluates CTFE<br />
|-<br />
| irstate.d || Intermediate Representation state; requires backend support<br />
|-<br />
| json.d || Generate JSON output<br />
|-<br />
| lexer.d || Lexically analyzes the source (such as separate keywords from identifiers)<br />
|-<br />
| libelf.d || ELF object format functions<br />
|-<br />
| libmach.d || Mach-O object format functions<br />
|-<br />
| libomf.d || OMF object format functions<br />
|-<br />
| link.d || Call the linker<br />
|-<br />
| dmacro.d || Expand DDoc macros<br />
|-<br />
| mangle.d || Mangle D types and declarations<br />
|-<br />
| mars.d || Analyzes the command line arguments (also display command-line help)<br />
|-<br />
| dmodule.d || ead modules.<br />
|-<br />
| msc.d || ?<br />
|-<br />
| mtype.d || All D types.<br />
|-<br />
| opover.d || Apply operator overloading<br />
|-<br />
| optimize.d || Optimize the AST<br />
|-<br />
| parse.d || Parse tokens into AST<br />
|-<br />
| ph.d || Custom allocator to replace malloc/free<br />
|-<br />
| root/aav.d || Associative array<br />
|-<br />
| root/array.d || Dynamic array<br />
|-<br />
| root/async.d || Asynchronous input<br />
|-<br />
| root/dchar.d || Convert UTF-32 character to UTF-8 sequence<br />
|-<br />
| root/gnuc.d || Implements functions missing from GCC, specifically ''stricmp'' and ''memicmp''.<br />
|-<br />
| root/lstring.d || Length-prefixed UTF-32 string.<br />
|-<br />
| root/man.d || Start the internet browser.<br />
|-<br />
| root/port.d || Portable wrapper around compiler/system specific things. The idea is to minimize #ifdef's in the app code.<br />
|-<br />
| root/response.d || ead the [http://digitalmars.com/d/2.0/dmd-windows.html#switches response file].<br />
|-<br />
| root/rmem.d || Implementation of the storage allocator uses the standard C allocation package.<br />
|-<br />
| root/root.d || Basic functions (deal mostly with strings, files, and bits)<br />
|-<br />
| root/speller.d || Spellchecker<br />
|-<br />
| root/stringtable.d || String table<br />
|-<br />
| s2ir.d || Statement to Intermediate Representation; requires backend support<br />
|-<br />
| dscope.d || Scope<br />
|-<br />
| statement.d || Handles '''while''', '''do''', '''for''', '''foreach''', '''if''', '''pragma''', '''staticassert''', '''switch''', '''case''', '''default''' , '''break''', '''return''', '''continue''', '''synchronized''', '''try'''/'''catch'''/'''finally''', '''throw''', '''volatile''', '''goto''', and '''label'''<br />
|-<br />
| staticassert.d || '''static assert'''.<br />
|-<br />
| dstruct.d || Aggregate ('''struct''' and '''union''') declaration.<br />
|-<br />
| dtemplate.d || Everything related to '''template'''.<br />
|-<br />
| tk/ || ?<br />
|-<br />
| tocsym.d || o C symbol<br />
|-<br />
| toctype.d || Convert D type to C type for debug symbol<br />
|-<br />
| tocvdebug.d || [http://stackoverflow.com/questions/1418660/microsofts-codeview-format-specs CodeView4 debug format].<br />
|-<br />
| todt.d || ?; requires backend support<br />
|-<br />
| toelfdebug.d || Emit symbolic debug info in Dwarf2 format. Currently empty.<br />
|-<br />
| toir.d || o Intermediate Representation; requires backend support<br />
|-<br />
| toobj.d || Generate the object file for Dsymbol and declarations except functions.<br />
|-<br />
| traits.d || '''__traits'''.<br />
|-<br />
| typinf.d || Get TypeInfo from a type.<br />
|-<br />
| unialpha.d || Check if a character is a Unicode alphabet.<br />
|-<br />
| unittests.d || un functions related to unit test.<br />
|-<br />
| utf.d || UTF-8.<br />
|-<br />
| version.d || Handles '''version'''<br />
|}<br />
<br />
=== Back end ===<br />
{| class="wikitable" |<br />
! File || Function<br />
|-<br />
| html.c || Extracts D source code from .html files<br />
|}<br />
<br />
=== A few observations ===<br />
* idgen.c is not part of the compiler source at all. It is the source to a code generator which creates id.h and id.c, which defines a whole lot of Identifier instances. (presumably, these are used to represent various 'builtin' symbols that the language defines)<br />
* impcvngen.c follows the same pattern as idgen.c. It creates impcnvtab.c, which appears to describe casting rules between primitive types.<br />
* Unspurprisingly, the code is highly D-like in methodology. For instance, root.h defines an Object class which serves as a base class for most, if not all of the other classes used. Class instances are always passed by pointer and allocated on the heap.<br />
* root.h also defines String, Array, and File classes, as opposed to using STL. Curious. (a relic from the days when templates weren't as reliable as they are now?)<br />
* lots of files with .c suffixes contain C++ code. Very confusing.<br />
<br />
== Abbreviations ==<br />
<br />
You may find these abbreviations throughout the DMD source code (in identifiers and comments).<br />
<br />
==== Front-end ====<br />
; STC<br />
: STorage Class<br />
; ILS<br />
: InLine State<br />
; IR<br />
: Intermediate Representation<br />
<br />
==== Back-end ====<br />
; AE<br />
: Available Expressions <br />
; CP<br />
: Copy Propagation info.<br />
; CSE<br />
: Common Subexpression Elimination <br />
; VBE<br />
: Very Busy Expression (http://web.cs.wpi.edu/~kal/PLT/PLT9.6.html)<br />
<br />
See also: [[Commonly-Used Acronyms]]<br />
<br />
==Class hierarchy==<br />
<br />
Have a look at [[Media:dmd_ast.png]].<br />
<br />
* RootObject<br />
** Dsymbol<br />
*** AliasThis<br />
*** AttribDeclaration<br />
**** StorageClassDeclaration<br />
***** DeprecatedDeclaration<br />
**** LinkDeclaration<br />
**** ProtDeclaration<br />
**** AlignDeclaration<br />
**** AnonDeclaration<br />
**** PragmaDeclaration<br />
**** ConditionalDeclaration<br />
***** StaticIfDeclaration<br />
**** CompileDeclaration<br />
**** UserAttributeDeclaration<br />
*** Declaration<br />
**** TupleDeclaration<br />
**** AliasDeclaration<br />
**** VarDeclaration<br />
***** TypeInfoDeclaration<br />
****** TypeInfoStructDeclaration<br />
****** TypeInfoClassDeclaration<br />
****** TypeInfoInterfaceDeclaration<br />
****** TypeInfoPointerDeclaration<br />
****** TypeInfoArrayDeclaration<br />
****** TypeInfoStaticArrayDeclaration<br />
****** TypeInfoAssociativeArrayDeclaration<br />
****** TypeInfoEnumDeclaration<br />
****** TypeInfoFunctionDeclaration<br />
****** TypeInfoDelegateDeclaration<br />
****** TypeInfoTupleDeclaration<br />
****** TypeInfoConstDeclaration<br />
****** TypeInfoInvariantDeclaration<br />
****** TypeInfoSharedDeclaration<br />
****** TypeInfoWildDeclaration<br />
****** TypeInfoVectorDeclaration<br />
***** ThisDeclaration<br />
**** SymbolDeclaration<br />
**** FuncDeclaration<br />
***** FuncAliasDeclaration<br />
***** FuncLiteralDeclaration<br />
***** CtorDeclaration<br />
***** PostBlitDeclaration<br />
***** DtorDeclaration<br />
***** StaticCtorDeclaration<br />
****** SharedStaticCtorDeclaration<br />
***** StaticDtorDeclaration<br />
****** SharedStaticDtorDeclaration<br />
***** InvariantDeclaration<br />
***** UnitTestDeclaration<br />
***** NewDeclaration<br />
***** DeleteDeclaration<br />
*** ScopeDsymbol<br />
**** AggregateDeclaration<br />
***** StructDeclaration<br />
****** UnionDeclaration<br />
***** ClassDeclaration<br />
****** InterfaceDeclaration<br />
**** WithScopeSymbol<br />
**** ArrayScopeSymbol<br />
**** EnumDeclaration<br />
**** Package<br />
***** Module<br />
**** TemplateDeclaration<br />
**** TemplateInstance<br />
***** TemplateMixin<br />
*** OverloadSet<br />
*** EnumMember<br />
*** Import<br />
*** LabelDsymbol<br />
*** StaticAssert<br />
*** DebugSymbol<br />
*** VersionSymbol<br />
** Expression<br />
*** ClassReferenceExp<br />
*** VoidInitExp<br />
*** ThrownExceptionExp<br />
*** IntegerExp<br />
*** ErrorExp<br />
*** RealExp<br />
*** ComplexExp<br />
*** IdentifierExp<br />
**** DollarExp<br />
*** DsymbolExp<br />
*** ThisExp<br />
**** SuperExp<br />
*** NullExp<br />
*** StringExp<br />
*** TupleExp<br />
*** ArrayLiteralExp<br />
*** AssocArrayLiteralExp<br />
*** StructLiteralExp<br />
*** TypeExp<br />
*** ScopeExp<br />
*** TemplateExp<br />
*** NewExp<br />
*** NewAnonClassExp<br />
*** SymbolExp<br />
**** SymOffExp<br />
**** VarExp<br />
*** OverExp<br />
*** FuncExp<br />
*** DeclarationExp<br />
*** TypeidExp<br />
*** TraitsExp<br />
*** HaltExp<br />
*** IsExp<br />
*** UnaExp<br />
**** CompileExp<br />
**** AssertExp<br />
**** DotIdExp<br />
**** DotTemplateExp<br />
**** DotVarExp<br />
**** DotTemplateInstanceExp<br />
**** DelegateExp<br />
**** DotTypeExp<br />
**** CallExp<br />
**** AddrExp<br />
**** PtrExp<br />
**** NegExp<br />
**** UAddExp<br />
**** ComExp<br />
**** NotExp<br />
**** DeleteExp<br />
**** CastExp<br />
**** VectorExp<br />
**** SliceExp<br />
**** ArrayLengthExp<br />
**** ArrayExp<br />
**** PreExp<br />
*** BinExp<br />
**** BinAssignExp<br />
***** AddAssignExp<br />
***** MinAssignExp<br />
***** MulAssignExp<br />
***** DivAssignExp<br />
***** ModAssignExp<br />
***** AndAssignExp<br />
***** OrAssignExp<br />
***** XorAssignExp<br />
***** PowAssignExp<br />
***** ShlAssignExp<br />
***** ShrAssignExp<br />
***** UshrAssignExp<br />
***** CatAssignExp<br />
**** DotExp<br />
**** CommaExp<br />
**** IndexExp<br />
**** PostExp<br />
**** AssignExp<br />
***** ConstructExp<br />
**** AddExp<br />
**** MinExp<br />
**** CatExp<br />
**** MulExp<br />
**** DivExp<br />
**** ModExp<br />
**** PowExp<br />
**** ShlExp<br />
**** ShrExp<br />
**** UshrExp<br />
**** AndExp<br />
**** OrExp<br />
**** XorExp<br />
**** OrOrExp<br />
**** AndAndExp<br />
**** CmpExp<br />
**** InExp<br />
**** RemoveExp<br />
**** EqualExp<br />
**** IdentityExp<br />
**** CondExp<br />
*** DefaultInitExp<br />
**** FileInitExp<br />
**** LineInitExp<br />
**** ModuleInitExp<br />
**** FuncInitExp<br />
**** PrettyFuncInitExp<br />
** Identifier<br />
** Initializer<br />
*** VoidInitializer<br />
*** ErrorInitializer<br />
*** StructInitializer<br />
*** ArrayInitializer<br />
*** ExpInitializer<br />
** Type<br />
*** TypeError<br />
*** TypeNext<br />
**** TypeArray<br />
***** TypeSArray<br />
***** TypeDArray<br />
***** TypeAArray<br />
**** TypePointer<br />
**** TypeReference<br />
**** TypeFunction<br />
**** TypeDelegate<br />
**** TypeSlice<br />
*** TypeBasic<br />
*** TypeVector<br />
*** TypeQualified<br />
**** TypeIdentifier<br />
**** TypeInstance<br />
**** TypeTypeof<br />
**** TypeReturn<br />
*** TypeStruct<br />
*** TypeEnum<br />
*** TypeClass<br />
*** TypeTuple<br />
*** TypeNull<br />
** Parameter<br />
** Statement<br />
*** ErrorStatement<br />
*** PeelStatement<br />
*** ExpStatement<br />
**** DtorExpStatement<br />
*** CompileStatement<br />
*** CompoundStatement<br />
**** CompoundDeclarationStatement<br />
*** UnrolledLoopStatement<br />
*** ScopeStatement<br />
*** WhileStatement<br />
*** DoStatement<br />
*** ForStatement<br />
*** ForeachStatement<br />
*** ForeachRangeStatement<br />
*** IfStatement<br />
*** ConditionalStatement<br />
*** PragmaStatement<br />
*** StaticAssertStatement<br />
*** SwitchStatement<br />
*** CaseStatement<br />
*** CaseRangeStatement<br />
*** DefaultStatement<br />
*** GotoDefaultStatement<br />
*** GotoCaseStatement<br />
*** SwitchErrorStatement<br />
*** ReturnStatement<br />
*** BreakStatement<br />
*** ContinueStatement<br />
*** SynchronizedStatement<br />
*** WithStatement<br />
*** TryCatchStatement<br />
*** TryFinallyStatement<br />
*** OnScopeStatement<br />
*** ThrowStatement<br />
*** DebugStatement<br />
*** GotoStatement<br />
*** LabelStatement<br />
*** AsmStatement<br />
*** ImportStatement<br />
** Catch<br />
** Tuple<br />
** DsymbolTable<br />
** Condition<br />
*** DVCondition<br />
**** DebugCondition<br />
**** VersionCondition<br />
*** StaticIfCondition<br />
* Visitor<br />
** StoppableVisitor<br />
* Lexer<br />
** Parser<br />
* Library<br />
<br />
== DMD Hacking Tips & Tricks ==<br />
<br />
=== Use printf-style debugging without too much visual noise ===<br />
<br />
There are many commented-out '''printf''' statements in the DMD front-end. You can uncomment them<br />
during debugging, but often you may only want to enable them for a specific symbol. One simple<br />
workaround is to enable printing when the name of the symbol matches the symbol you're debugging,<br />
for example:<br />
<br />
<syntaxhighlight lang="d"><br />
void semantic(Scope* sc)<br />
{<br />
// only do printouts if this is our target symbol<br />
if (!strcmp(toChars, "test_struct"));<br />
printf("this=%p, %s '%s', sizeok = %d\n", this, parent.toChars, toChars, sizeok);<br />
}<br />
</syntaxhighlight><br />
<br />
=== Find which module instantiated a specific template instance ===<br />
<br />
Templates have a '''instantiatingModule''' field which you can inspect. Here's an example from '''glue.d''':<br />
<br />
<syntaxhighlight lang="d"><br />
/* Skip generating code if this part of a TemplateInstance that is instantiated<br />
* only by non-root modules (i.e. modules not listed on the command line).<br />
*/<br />
TemplateInstance* ti = inTemplateInstance();<br />
if (!global.params.useUnitTests &&<br />
ti && ti.instantiatingModule && !ti.instantiatingModule.root)<br />
{<br />
//printf("instantiated by %s %s\n", ti.instantiatingModule.toChars(), ti.toChars());<br />
return;<br />
}<br />
</syntaxhighlight><br />
<br />
=== View emitted templates instances and string/mixins ===<br />
<br />
The <tt>-vcg-ast</tt> switch will generate a .cg-file next to the compiled code source-code<br />
Which will contain the source representation of the AST just before code-generation<br />
(That means the last stage of compilation)<br />
This helps to debug templates as well spot issues with the inliner<br />
NOTE: for this to work the code has to reach the codegen stage i.e is has to compile without error<br />
<br />
<syntaxhighlight lang="d"><br />
void main() {<br />
foreach (i; 0 .. 10) {<br />
mixin("auto a = i;");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang="bash"><br />
dmd -vcg-ast test.d<br />
</syntaxhighlight><br />
<br />
Which will generated a file <tt>test.d.cg</tt>:<br />
<br />
<syntaxhighlight lang="d"><br />
import object;<br />
void main()<br />
{<br />
{<br />
int __key2 = 0;<br />
int __limit3 = 10;<br />
for (; __key2 < __limit3; __key2 += 1)<br />
{<br />
int i = __key2;<br />
int a = i;<br />
}<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Determine if a DMD 'Type' is an actual type, expression, or a symbol ===<br />
<br />
You can use the '''resolve''' virtual function to determine this:<br />
<br />
<syntaxhighlight lang="d"><br />
RootObject* o = ...;<br />
Type* srcType = isType(o);<br />
<br />
if (srcType)<br />
{<br />
Type* t;<br />
Expression* e;<br />
Dsymbol* s;<br />
srcType.resolve(loc, sc, &e, &t, &s);<br />
<br />
if (t) { } // it's a type<br />
else if (e) { } // it's an expression<br />
else if (s) { } // it's a symbol<br />
}<br />
</syntaxhighlight><br />
<br />
You can see examples of this technique being used in the '''traits.d''' file.<br />
<br />
=== Get the string representation of a DSymbol ===<br />
<br />
A '''DSymbol''' has the two functions '''toChars()''' and '''toPrettyChars()''',<br />
which are useful for debugging. The former prints out the name of the symbol,<br />
while the latter may print out the fully-scoped name of the symbol. For example:<br />
<br />
<syntaxhighlight lang="d"><br />
StructDeclaration* sd = ...; // assuming struct named "Bar" inside module named "Foo"<br />
printf("name: %s\n", sd.toChars()); // prints out "Bar"<br />
printf("fully qualified name: %s\n", sd.toPrettyChars()); // prints out "Foo.Bar"<br />
</syntaxhighlight><br />
<br />
=== Get the string representation of the kind of a DSymbol ===<br />
<br />
All '''DSymbol'''-inherited classes implement the '''kind''' virtual method,<br />
which enable you to use printf-style debugging, e.g.:<br />
<br />
<syntaxhighlight lang="d"><br />
EnumDeclaration* ed = ...;<br />
DSymbol* s = ed;<br />
printf("%s\n", s.kind()); // prints "enum". See 'EnumDeclaration.kind'.<br />
</syntaxhighlight><br />
<br />
=== Get the string representation of the dynamic type of an ast-node ===<br />
There is a helper module called '''asttypename''' which allows you to print the dynamic type of an ast-node<br />
This is useful when implementing your own visitors. <br />
<br />
<syntaxhighlight lang="d"><br />
import dmd.asttypename;<br />
Expression ex = new AndAndExp(...);<br />
writeln(ex.astTypeName); // prints "AndAndExp".<br />
</syntaxhighlight><br />
<br />
=== Get the string representation of an operator or token ===<br />
<br />
'''Expression''' objects hold an '''op''' field, which is a '''TOK''' type (a token).<br />
To print out the string representation of the token, index into the static array '''Token.toChars''':<br />
<br />
<syntaxhighlight lang="d"><br />
Expression* e = ...;<br />
printf("Expression op: %s ", Token.toChars(e.op));<br />
</syntaxhighlight><br />
<br />
=== Print the value of a floating-point literal ===<br />
<br />
To print the value of an expression which is a floating-point literal (a value known at compile-time),<br />
use the '''toReal()''' member function:<br />
<br />
<syntaxhighlight lang="d"><br />
if (exp.op == TOKfloat32 || exp.op == TOKfloat64 || exp.op == TOKfloat80)<br />
printf("%Lf", exp.toReal());<br />
</syntaxhighlight><br />
<br />
=== Check whether an expression is a compile-time known literal ===<br />
<br />
Use the '''isConst()''' method to check if an '''Expression''' is a compile-time known literal.<br />
The name '''isConst()''' is a misnomer, but this name predates D2 and was more relevant to D1.<br />
Please note that '''isConst()''' is also a method of '''Type''', but is unrelated to the<br />
equally named function in the '''Expression''' class.<br />
<br />
=== Note the difference between two mixin types: compile declarations and compile statements ===<br />
<br />
Take this example D code:<br />
<br />
<syntaxhighlight lang="D"><br />
mixin("int x;");<br />
<br />
void main()<br />
{<br />
mixin("int y;");<br />
}<br />
</syntaxhighlight><br />
<br />
The first mixin is a '''CompileDeclaration''', while the second is a '''CompileStatement'''.<br />
These are separate classes in the DMD front-end.<br />
<br />
<br />
[[Category:DMD Compiler]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Building_under_Windows&diff=10141Building under Windows2023-01-23T18:14:08Z<p>NickTreleaven: /* Missing sppn.exe or cl.exe */ Recommend reinstalling dmc or merging bup.zip to fix problems</p>
<hr />
<div>== Automation ==<br />
<br />
[https://github.com/CyberShadow/Digger Digger] can checkout and build any D version automatically for you. Only a D compiler is required. Digger will download all required dependencies by itself.<br />
<br />
<syntaxhighlight lang=bash><br />
dub fetch digger<br />
dub run digger<br />
</syntaxhighlight><br />
<br />
Among many other features, Digger can build older compiler versions or versions with a specific pull request added:<br />
<br />
<syntaxhighlight lang=bash><br />
# build a specific D version<br />
$ dub run digger -- build v2.064.2<br />
<br />
# build for x86-64<br />
$ dub run digger -- build --model=64 v2.064.2<br />
<br />
# build commit from a point in time<br />
$ dub run digger -- build "@ 3 weeks ago"<br />
<br />
# build specified branch from a point in time<br />
$ dub run digger -- build "2.065 @ 3 weeks ago"<br />
<br />
# build with an added pull request<br />
$ dub run digger -- build "master + dmd#123"<br />
</syntaxhighlight><br />
<br />
== Use Digital Mars make ==<br />
This page needs DigitalMars {{code|make}} (not to confuse with GNUMake). DigitalMars is part of the DMD Windows distribution and should be part of your {{code|PATH}}.<br />
<br />
If you have GNUMake installed on your system too, use the full path to DigitalMars make: {{code|C:\D\dmd2\windows\bin\make}}.<br />
<br />
== Building with Visual Studio ==<br />
<br />
=== Prerequisites ===<br />
<br />
* [https://visualstudio.microsoft.com/ Visual Studio]<br />
* [https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Window SDK]<br />
* [https://dlang.org/download.html DMD Windows Installer]<br />
* [https://rainers.github.io/visuald/visuald/StartPage.html VisualD]<br />
<br />
=== Instructions ===<br />
<br />
* Run the DMD Windows Installer and make sure that the binaries get added to the PATH (check "Add to Path")<br />
* Install VisualD (can be done via the DMD installer with the "Download VisualD" checkbox)<br />
* Make sure that dmd gets installed to {{code|C:\D\dmd2}} (the default)<br />
<br />
=== Clone repositories ===<br />
<br />
Next step is to clone the 3 necessary source repos, dmd, phobos, and tools.<br />
<br />
<syntaxhighlight lang=dos><br />
mkdir C:\Source\D<br />
cd C:\Source\D<br />
git clone https://github.com/dlang/dmd<br />
git clone https://github.com/dlang/phobos<br />
git clone https://github.com/dlang/tools<br />
</syntaxhighlight><br />
<br />
Make sure to pick a folder without white spaces or special characters to avoid any potential problems.<br />
<br />
=== Building DMD ===<br />
<br />
You should be able to build DMD using the visual studio solution found in: {{code|dmd\src\vcbuild}}<br />
A typical choice is to build the 64-bit debug version (the VisualD options are named 'Release' and 'x64').<br />
<br />
A 'dmd.exe' should have been built and placed in {{code|C:\Source\D\dmd\generated\Windows\Debug\x64}}.<br />
<br />
If you want the 32-bit counterparts, you will have to adjust accordingly.<br />
Most notably, using win32.mak Makefiles instead of the win64.mak files.<br />
<br />
=== Building DRuntime ===<br />
<br />
Make sure that Visual Studio tools are part of your PATH. One common way is to run 'vcvarsall.bat'.<br />
With Visual Studio 2017 this call is:<br />
<br />
<syntaxhighlight lang=dos><br />
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64<br />
</syntaxhighlight ><br />
<br />
Now, go into druntime:<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\dmd\druntime<br />
</syntaxhighlight><br />
<br />
Then compile with DigitalMars make (not to confuse with GNUMake).<br />
<br />
<syntaxhighlight lang=dos><br />
set VCDIR="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC"<br />
make -f win64.mak -j4 "VCDIR=%VCDIR%" target<br />
</syntaxhighlight><br />
<br />
For building on 32-bit with the Visual Studio Runtime, use {{code|MODEL=32mscoff}}.<br />
<br />
=== Building Phobos ===<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\phobos<br />
make -f win64.mak -j4 target<br />
</syntaxhighlight><br />
<br />
== Building D ==<br />
<br />
These instructions use the dmc tool chain.<br />
<br />
=== Prerequisites ===<br />
<br />
On Windows, you will need [http://dlang.org/download.html#dmd D compiler], [http://ftp.digitalmars.com/dmc.zip the DigitalMars C++ compiler], and, for 64-bit or 32-bit COFF builds, the [https://www.microsoft.com/en-us/download/details.aspx?id=8279 Microsoft Windows SDK].<br />
<br />
Assuming that {{code|make}}, {{code|dmc}} and {{code|dmd}} from digital mars are in your path and your sources are in {{code|C:\D\dmd2\src}} which has the following structure:<br />
<syntaxhighlight lang=dos><br />
C:\D\dmd2\src\dmd<br />
C:\D\dmd2\src\phobos<br />
C:\D\dmd2\src\tools<br />
</syntaxhighlight><br />
<br />
Note: tools is optional. <br />
<br />
Alternatively, you may wish to clone the git repositories for each of the above using [https://git-scm.com/ Git for Windows].<br />
<br />
==== git Configuration ====<br />
<br />
When cloning from the GitHub repositories you may encounter problems if your git configuration on Windows replaces line endings with the Windows variant (i.e. {{code|\r\n}}) instead of leaving it as {{code|\n}}, which is what D repositories require.<br />
<br />
To check your settings, run {{code|git config core.autocrlf}}. If it prints {{code|true}}, set it to {{code|false}} with {{code|git config --global core.autocrlf false}}.<br />
<br />
=== Before you start ===<br />
<br />
The following instructions work for win32. May or may not work with win64. This scheme is a suggestion. These instructions should work when building from a clean repository, however, this repository contains autogenerated code that may be left behind after switching branches so running a git clean after switching branches is a good idea:<br />
<br />
<syntaxhighlight lang=dos><br />
git clean -xfd<br />
</syntaxhighlight><br />
<br />
=== Building DMD ===<br />
<br />
To build DMD compiler you should run the following commands ({{code|win32.mak}} file expects that {{code|HOST_DC}} variable is set to {{code|dmd}}):<br />
<syntaxhighlight lang=dos><br />
set DM_HOME=C:\D<br />
cd %DM_HOME%\dmd2\src\dmd\src<br />
set HOST_DC=dmd<br />
make -fwin32.mak release<br />
</syntaxhighlight><br />
<br />
From there, it is suggested to move the built binaries into your {{code|%DM_HOME%\windows\bin}} directory, and add that to your path:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\bin<br />
copy *.exe %DM_HOME%\dmd2\windows\bin<br />
set path=%DM_HOME%\dmd2\windows\bin;%path%<br />
</syntaxhighlight><br />
<br />
From there, you have to create a {{code|sc.ini}} in your {{code|%DM_HOME%\dmd2\windows\bin}} directory (where {{code|dmd.exe}} is). It is suggested to just copy paste the one provided in the packaged {{Latest DMD Version Raw}}, instead of writing your own, like:<br />
<syntaxhighlight lang=dos><br />
copy "C:\Program Files\D\dmd2\windows\bin\sc.ini" %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Building D runtime ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest druntime code.<br />
<br />
To build D runtime you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\druntime<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
==== Missing sppn.exe or cl.exe ====<br />
<br />
* For 32-bit if you don't have sppn.exe then probably dmc is not correctly installed. Download dmc.zip and replace your {{code|dm}} directory.<br />
* If you are using win64.mak, you may need to download bup.zip and merge the {{code|dm}} folders.<br />
Both zip files can be found here:<br />
http://ftp.digitalmars.com/<br />
<br />
=== Building Phobos ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest phobos code.<br />
<br />
To build Phobos you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
You should copy phobos lib into your {{code|%DM_HOME%\windows\lib}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy phobos.lib %DM_HOME%\dmd2\windows\lib<br />
</syntaxhighlight><br />
<br />
=== Building rdmd ===<br />
<br />
Optionally, you can build rdmd from source if you have checked out {{code|tools}} in your sources. Some additional libs might be required for build and can simply be copy pasted from the {{Latest DMD Version Raw}} package without overwriting your {{code|phobos.lib}}.<br />
<br />
To build rdmd you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\tools<br />
make -fwin32.mak rdmd<br />
</syntaxhighlight><br />
<br />
You should copy rdmd into your {{code|%DM_HOME%\windows\bin}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy generated\windows\32\*.exe %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Thirdparty libraries ===<br />
<br />
The last step is getting the additional libs. curl for D2 can be found at the bottom of the download section of dlang.org: [[http://dlang.org/download.html download]].<br />
<br />
Additional libs that are necessary can simply be copy pasted from the {{Latest DMD Version Raw}} package (without overwriting your {{code|phobos.lib}}).<br />
<br />
=== Verifying ===<br />
<br />
The very last step is to verify that everything works by unittesting phobos:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak unittest<br />
</syntaxhighlight><br />
<br />
== Common Windows issues ==<br />
<br />
=== Missing MASM386===<br />
<br />
If when building druntime you get errors about missing MASM386, it's due to a required assembling of a file called '''minit.asm'''. However the druntime repository includes a prebuilt minit.obj file so you shouldn't need to assemble it again. As a workaround for the make error create an empty '''masm386.bat''' file and put it in a directory that's in your '''PATH'''.<br />
<br />
=== Command prompt ===<br />
<br />
It's also recommended that you use the cmd.exe terminal. Others, like PowerShell, are known to experience issues with legacy tools.<br />
<br />
=== Intermediate files lead to several errors ===<br />
<br />
The three main components (dmd, druntime, phobos) should always be built together with matching versions. The intermediate files generated by a previous build can lead to a failure so it's advisable to run<br />
<br />
<syntaxhighlight lang=dos><br />
make -fwin32.mak clean<br />
</syntaxhighlight><br />
<br />
on each component before starting the process.<br />
<br />
=== Using DigitalMars <code>make</code> for running the test suite ===<br />
<br />
DMD's testsuite can't be run with DigitalMars <code>make</code> - use GNUMake.<br />
Refer to the instructions in [[DMD_development#Running_the_testsuite_on_Windows | Running the test suite on Windows]].<br />
<br />
== Where to go from here ==<br />
<br />
If you want to contribute to a D project, please continue with the [[Starting_as_a_Contributor| starting as a contributor]] guide.<br />
If you want to contribute to Phobos, you may also read the [[Contributing to Phobos|contributing to Phobos guide]].<br />
<br />
[[Category:Windows]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Building_under_Windows&diff=10140Building under Windows2023-01-23T18:01:22Z<p>NickTreleaven: /* Common Windows issues */ Add command prompt subheading</p>
<hr />
<div>== Automation ==<br />
<br />
[https://github.com/CyberShadow/Digger Digger] can checkout and build any D version automatically for you. Only a D compiler is required. Digger will download all required dependencies by itself.<br />
<br />
<syntaxhighlight lang=bash><br />
dub fetch digger<br />
dub run digger<br />
</syntaxhighlight><br />
<br />
Among many other features, Digger can build older compiler versions or versions with a specific pull request added:<br />
<br />
<syntaxhighlight lang=bash><br />
# build a specific D version<br />
$ dub run digger -- build v2.064.2<br />
<br />
# build for x86-64<br />
$ dub run digger -- build --model=64 v2.064.2<br />
<br />
# build commit from a point in time<br />
$ dub run digger -- build "@ 3 weeks ago"<br />
<br />
# build specified branch from a point in time<br />
$ dub run digger -- build "2.065 @ 3 weeks ago"<br />
<br />
# build with an added pull request<br />
$ dub run digger -- build "master + dmd#123"<br />
</syntaxhighlight><br />
<br />
== Use Digital Mars make ==<br />
This page needs DigitalMars {{code|make}} (not to confuse with GNUMake). DigitalMars is part of the DMD Windows distribution and should be part of your {{code|PATH}}.<br />
<br />
If you have GNUMake installed on your system too, use the full path to DigitalMars make: {{code|C:\D\dmd2\windows\bin\make}}.<br />
<br />
== Building with Visual Studio ==<br />
<br />
=== Prerequisites ===<br />
<br />
* [https://visualstudio.microsoft.com/ Visual Studio]<br />
* [https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Window SDK]<br />
* [https://dlang.org/download.html DMD Windows Installer]<br />
* [https://rainers.github.io/visuald/visuald/StartPage.html VisualD]<br />
<br />
=== Instructions ===<br />
<br />
* Run the DMD Windows Installer and make sure that the binaries get added to the PATH (check "Add to Path")<br />
* Install VisualD (can be done via the DMD installer with the "Download VisualD" checkbox)<br />
* Make sure that dmd gets installed to {{code|C:\D\dmd2}} (the default)<br />
<br />
=== Clone repositories ===<br />
<br />
Next step is to clone the 3 necessary source repos, dmd, phobos, and tools.<br />
<br />
<syntaxhighlight lang=dos><br />
mkdir C:\Source\D<br />
cd C:\Source\D<br />
git clone https://github.com/dlang/dmd<br />
git clone https://github.com/dlang/phobos<br />
git clone https://github.com/dlang/tools<br />
</syntaxhighlight><br />
<br />
Make sure to pick a folder without white spaces or special characters to avoid any potential problems.<br />
<br />
=== Building DMD ===<br />
<br />
You should be able to build DMD using the visual studio solution found in: {{code|dmd\src\vcbuild}}<br />
A typical choice is to build the 64-bit debug version (the VisualD options are named 'Release' and 'x64').<br />
<br />
A 'dmd.exe' should have been built and placed in {{code|C:\Source\D\dmd\generated\Windows\Debug\x64}}.<br />
<br />
If you want the 32-bit counterparts, you will have to adjust accordingly.<br />
Most notably, using win32.mak Makefiles instead of the win64.mak files.<br />
<br />
=== Building DRuntime ===<br />
<br />
Make sure that Visual Studio tools are part of your PATH. One common way is to run 'vcvarsall.bat'.<br />
With Visual Studio 2017 this call is:<br />
<br />
<syntaxhighlight lang=dos><br />
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64<br />
</syntaxhighlight ><br />
<br />
Now, go into druntime:<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\dmd\druntime<br />
</syntaxhighlight><br />
<br />
Then compile with DigitalMars make (not to confuse with GNUMake).<br />
<br />
<syntaxhighlight lang=dos><br />
set VCDIR="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC"<br />
make -f win64.mak -j4 "VCDIR=%VCDIR%" target<br />
</syntaxhighlight><br />
<br />
For building on 32-bit with the Visual Studio Runtime, use {{code|MODEL=32mscoff}}.<br />
<br />
=== Building Phobos ===<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\phobos<br />
make -f win64.mak -j4 target<br />
</syntaxhighlight><br />
<br />
== Building D ==<br />
<br />
These instructions use the dmc tool chain.<br />
<br />
=== Prerequisites ===<br />
<br />
On Windows, you will need [http://dlang.org/download.html#dmd D compiler], [http://ftp.digitalmars.com/dmc.zip the DigitalMars C++ compiler], and, for 64-bit or 32-bit COFF builds, the [https://www.microsoft.com/en-us/download/details.aspx?id=8279 Microsoft Windows SDK].<br />
<br />
Assuming that {{code|make}}, {{code|dmc}} and {{code|dmd}} from digital mars are in your path and your sources are in {{code|C:\D\dmd2\src}} which has the following structure:<br />
<syntaxhighlight lang=dos><br />
C:\D\dmd2\src\dmd<br />
C:\D\dmd2\src\phobos<br />
C:\D\dmd2\src\tools<br />
</syntaxhighlight><br />
<br />
Note: tools is optional. <br />
<br />
Alternatively, you may wish to clone the git repositories for each of the above using [https://git-scm.com/ Git for Windows].<br />
<br />
==== git Configuration ====<br />
<br />
When cloning from the GitHub repositories you may encounter problems if your git configuration on Windows replaces line endings with the Windows variant (i.e. {{code|\r\n}}) instead of leaving it as {{code|\n}}, which is what D repositories require.<br />
<br />
To check your settings, run {{code|git config core.autocrlf}}. If it prints {{code|true}}, set it to {{code|false}} with {{code|git config --global core.autocrlf false}}.<br />
<br />
=== Before you start ===<br />
<br />
The following instructions work for win32. May or may not work with win64. This scheme is a suggestion. These instructions should work when building from a clean repository, however, this repository contains autogenerated code that may be left behind after switching branches so running a git clean after switching branches is a good idea:<br />
<br />
<syntaxhighlight lang=dos><br />
git clean -xfd<br />
</syntaxhighlight><br />
<br />
=== Building DMD ===<br />
<br />
To build DMD compiler you should run the following commands ({{code|win32.mak}} file expects that {{code|HOST_DC}} variable is set to {{code|dmd}}):<br />
<syntaxhighlight lang=dos><br />
set DM_HOME=C:\D<br />
cd %DM_HOME%\dmd2\src\dmd\src<br />
set HOST_DC=dmd<br />
make -fwin32.mak release<br />
</syntaxhighlight><br />
<br />
From there, it is suggested to move the built binaries into your {{code|%DM_HOME%\windows\bin}} directory, and add that to your path:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\bin<br />
copy *.exe %DM_HOME%\dmd2\windows\bin<br />
set path=%DM_HOME%\dmd2\windows\bin;%path%<br />
</syntaxhighlight><br />
<br />
From there, you have to create a {{code|sc.ini}} in your {{code|%DM_HOME%\dmd2\windows\bin}} directory (where {{code|dmd.exe}} is). It is suggested to just copy paste the one provided in the packaged {{Latest DMD Version Raw}}, instead of writing your own, like:<br />
<syntaxhighlight lang=dos><br />
copy "C:\Program Files\D\dmd2\windows\bin\sc.ini" %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Building D runtime ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest druntime code.<br />
<br />
To build D runtime you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\druntime<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
==== Missing sppn.exe or cl.exe ====<br />
<br />
* For 32-bit you may need to download and extract sppn.zip next to your dmc.exe.<br />
* If you are using win64.mak, you may need to download cl.exe.<br />
Both can be found here:<br />
http://ftp.digitalmars.com/<br />
<br />
=== Building Phobos ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest phobos code.<br />
<br />
To build Phobos you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
You should copy phobos lib into your {{code|%DM_HOME%\windows\lib}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy phobos.lib %DM_HOME%\dmd2\windows\lib<br />
</syntaxhighlight><br />
<br />
=== Building rdmd ===<br />
<br />
Optionally, you can build rdmd from source if you have checked out {{code|tools}} in your sources. Some additional libs might be required for build and can simply be copy pasted from the {{Latest DMD Version Raw}} package without overwriting your {{code|phobos.lib}}.<br />
<br />
To build rdmd you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\tools<br />
make -fwin32.mak rdmd<br />
</syntaxhighlight><br />
<br />
You should copy rdmd into your {{code|%DM_HOME%\windows\bin}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy generated\windows\32\*.exe %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Thirdparty libraries ===<br />
<br />
The last step is getting the additional libs. curl for D2 can be found at the bottom of the download section of dlang.org: [[http://dlang.org/download.html download]].<br />
<br />
Additional libs that are necessary can simply be copy pasted from the {{Latest DMD Version Raw}} package (without overwriting your {{code|phobos.lib}}).<br />
<br />
=== Verifying ===<br />
<br />
The very last step is to verify that everything works by unittesting phobos:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak unittest<br />
</syntaxhighlight><br />
<br />
== Common Windows issues ==<br />
<br />
=== Missing MASM386===<br />
<br />
If when building druntime you get errors about missing MASM386, it's due to a required assembling of a file called '''minit.asm'''. However the druntime repository includes a prebuilt minit.obj file so you shouldn't need to assemble it again. As a workaround for the make error create an empty '''masm386.bat''' file and put it in a directory that's in your '''PATH'''.<br />
<br />
=== Command prompt ===<br />
<br />
It's also recommended that you use the cmd.exe terminal. Others, like PowerShell, are known to experience issues with legacy tools.<br />
<br />
=== Intermediate files lead to several errors ===<br />
<br />
The three main components (dmd, druntime, phobos) should always be built together with matching versions. The intermediate files generated by a previous build can lead to a failure so it's advisable to run<br />
<br />
<syntaxhighlight lang=dos><br />
make -fwin32.mak clean<br />
</syntaxhighlight><br />
<br />
on each component before starting the process.<br />
<br />
=== Using DigitalMars <code>make</code> for running the test suite ===<br />
<br />
DMD's testsuite can't be run with DigitalMars <code>make</code> - use GNUMake.<br />
Refer to the instructions in [[DMD_development#Running_the_testsuite_on_Windows | Running the test suite on Windows]].<br />
<br />
== Where to go from here ==<br />
<br />
If you want to contribute to a D project, please continue with the [[Starting_as_a_Contributor| starting as a contributor]] guide.<br />
If you want to contribute to Phobos, you may also read the [[Contributing to Phobos|contributing to Phobos guide]].<br />
<br />
[[Category:Windows]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Building_under_Windows&diff=10139Building under Windows2023-01-23T17:55:06Z<p>NickTreleaven: /* Prerequisites */ Remove make link to 'running the test suite', confusing and we now mention DM make above this</p>
<hr />
<div>== Automation ==<br />
<br />
[https://github.com/CyberShadow/Digger Digger] can checkout and build any D version automatically for you. Only a D compiler is required. Digger will download all required dependencies by itself.<br />
<br />
<syntaxhighlight lang=bash><br />
dub fetch digger<br />
dub run digger<br />
</syntaxhighlight><br />
<br />
Among many other features, Digger can build older compiler versions or versions with a specific pull request added:<br />
<br />
<syntaxhighlight lang=bash><br />
# build a specific D version<br />
$ dub run digger -- build v2.064.2<br />
<br />
# build for x86-64<br />
$ dub run digger -- build --model=64 v2.064.2<br />
<br />
# build commit from a point in time<br />
$ dub run digger -- build "@ 3 weeks ago"<br />
<br />
# build specified branch from a point in time<br />
$ dub run digger -- build "2.065 @ 3 weeks ago"<br />
<br />
# build with an added pull request<br />
$ dub run digger -- build "master + dmd#123"<br />
</syntaxhighlight><br />
<br />
== Use Digital Mars make ==<br />
This page needs DigitalMars {{code|make}} (not to confuse with GNUMake). DigitalMars is part of the DMD Windows distribution and should be part of your {{code|PATH}}.<br />
<br />
If you have GNUMake installed on your system too, use the full path to DigitalMars make: {{code|C:\D\dmd2\windows\bin\make}}.<br />
<br />
== Building with Visual Studio ==<br />
<br />
=== Prerequisites ===<br />
<br />
* [https://visualstudio.microsoft.com/ Visual Studio]<br />
* [https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Window SDK]<br />
* [https://dlang.org/download.html DMD Windows Installer]<br />
* [https://rainers.github.io/visuald/visuald/StartPage.html VisualD]<br />
<br />
=== Instructions ===<br />
<br />
* Run the DMD Windows Installer and make sure that the binaries get added to the PATH (check "Add to Path")<br />
* Install VisualD (can be done via the DMD installer with the "Download VisualD" checkbox)<br />
* Make sure that dmd gets installed to {{code|C:\D\dmd2}} (the default)<br />
<br />
=== Clone repositories ===<br />
<br />
Next step is to clone the 3 necessary source repos, dmd, phobos, and tools.<br />
<br />
<syntaxhighlight lang=dos><br />
mkdir C:\Source\D<br />
cd C:\Source\D<br />
git clone https://github.com/dlang/dmd<br />
git clone https://github.com/dlang/phobos<br />
git clone https://github.com/dlang/tools<br />
</syntaxhighlight><br />
<br />
Make sure to pick a folder without white spaces or special characters to avoid any potential problems.<br />
<br />
=== Building DMD ===<br />
<br />
You should be able to build DMD using the visual studio solution found in: {{code|dmd\src\vcbuild}}<br />
A typical choice is to build the 64-bit debug version (the VisualD options are named 'Release' and 'x64').<br />
<br />
A 'dmd.exe' should have been built and placed in {{code|C:\Source\D\dmd\generated\Windows\Debug\x64}}.<br />
<br />
If you want the 32-bit counterparts, you will have to adjust accordingly.<br />
Most notably, using win32.mak Makefiles instead of the win64.mak files.<br />
<br />
=== Building DRuntime ===<br />
<br />
Make sure that Visual Studio tools are part of your PATH. One common way is to run 'vcvarsall.bat'.<br />
With Visual Studio 2017 this call is:<br />
<br />
<syntaxhighlight lang=dos><br />
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64<br />
</syntaxhighlight ><br />
<br />
Now, go into druntime:<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\dmd\druntime<br />
</syntaxhighlight><br />
<br />
Then compile with DigitalMars make (not to confuse with GNUMake).<br />
<br />
<syntaxhighlight lang=dos><br />
set VCDIR="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC"<br />
make -f win64.mak -j4 "VCDIR=%VCDIR%" target<br />
</syntaxhighlight><br />
<br />
For building on 32-bit with the Visual Studio Runtime, use {{code|MODEL=32mscoff}}.<br />
<br />
=== Building Phobos ===<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\phobos<br />
make -f win64.mak -j4 target<br />
</syntaxhighlight><br />
<br />
== Building D ==<br />
<br />
These instructions use the dmc tool chain.<br />
<br />
=== Prerequisites ===<br />
<br />
On Windows, you will need [http://dlang.org/download.html#dmd D compiler], [http://ftp.digitalmars.com/dmc.zip the DigitalMars C++ compiler], and, for 64-bit or 32-bit COFF builds, the [https://www.microsoft.com/en-us/download/details.aspx?id=8279 Microsoft Windows SDK].<br />
<br />
Assuming that {{code|make}}, {{code|dmc}} and {{code|dmd}} from digital mars are in your path and your sources are in {{code|C:\D\dmd2\src}} which has the following structure:<br />
<syntaxhighlight lang=dos><br />
C:\D\dmd2\src\dmd<br />
C:\D\dmd2\src\phobos<br />
C:\D\dmd2\src\tools<br />
</syntaxhighlight><br />
<br />
Note: tools is optional. <br />
<br />
Alternatively, you may wish to clone the git repositories for each of the above using [https://git-scm.com/ Git for Windows].<br />
<br />
==== git Configuration ====<br />
<br />
When cloning from the GitHub repositories you may encounter problems if your git configuration on Windows replaces line endings with the Windows variant (i.e. {{code|\r\n}}) instead of leaving it as {{code|\n}}, which is what D repositories require.<br />
<br />
To check your settings, run {{code|git config core.autocrlf}}. If it prints {{code|true}}, set it to {{code|false}} with {{code|git config --global core.autocrlf false}}.<br />
<br />
=== Before you start ===<br />
<br />
The following instructions work for win32. May or may not work with win64. This scheme is a suggestion. These instructions should work when building from a clean repository, however, this repository contains autogenerated code that may be left behind after switching branches so running a git clean after switching branches is a good idea:<br />
<br />
<syntaxhighlight lang=dos><br />
git clean -xfd<br />
</syntaxhighlight><br />
<br />
=== Building DMD ===<br />
<br />
To build DMD compiler you should run the following commands ({{code|win32.mak}} file expects that {{code|HOST_DC}} variable is set to {{code|dmd}}):<br />
<syntaxhighlight lang=dos><br />
set DM_HOME=C:\D<br />
cd %DM_HOME%\dmd2\src\dmd\src<br />
set HOST_DC=dmd<br />
make -fwin32.mak release<br />
</syntaxhighlight><br />
<br />
From there, it is suggested to move the built binaries into your {{code|%DM_HOME%\windows\bin}} directory, and add that to your path:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\bin<br />
copy *.exe %DM_HOME%\dmd2\windows\bin<br />
set path=%DM_HOME%\dmd2\windows\bin;%path%<br />
</syntaxhighlight><br />
<br />
From there, you have to create a {{code|sc.ini}} in your {{code|%DM_HOME%\dmd2\windows\bin}} directory (where {{code|dmd.exe}} is). It is suggested to just copy paste the one provided in the packaged {{Latest DMD Version Raw}}, instead of writing your own, like:<br />
<syntaxhighlight lang=dos><br />
copy "C:\Program Files\D\dmd2\windows\bin\sc.ini" %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Building D runtime ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest druntime code.<br />
<br />
To build D runtime you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\druntime<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
==== Missing sppn.exe or cl.exe ====<br />
<br />
* For 32-bit you may need to download and extract sppn.zip next to your dmc.exe.<br />
* If you are using win64.mak, you may need to download cl.exe.<br />
Both can be found here:<br />
http://ftp.digitalmars.com/<br />
<br />
=== Building Phobos ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest phobos code.<br />
<br />
To build Phobos you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
You should copy phobos lib into your {{code|%DM_HOME%\windows\lib}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy phobos.lib %DM_HOME%\dmd2\windows\lib<br />
</syntaxhighlight><br />
<br />
=== Building rdmd ===<br />
<br />
Optionally, you can build rdmd from source if you have checked out {{code|tools}} in your sources. Some additional libs might be required for build and can simply be copy pasted from the {{Latest DMD Version Raw}} package without overwriting your {{code|phobos.lib}}.<br />
<br />
To build rdmd you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\tools<br />
make -fwin32.mak rdmd<br />
</syntaxhighlight><br />
<br />
You should copy rdmd into your {{code|%DM_HOME%\windows\bin}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy generated\windows\32\*.exe %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Thirdparty libraries ===<br />
<br />
The last step is getting the additional libs. curl for D2 can be found at the bottom of the download section of dlang.org: [[http://dlang.org/download.html download]].<br />
<br />
Additional libs that are necessary can simply be copy pasted from the {{Latest DMD Version Raw}} package (without overwriting your {{code|phobos.lib}}).<br />
<br />
=== Verifying ===<br />
<br />
The very last step is to verify that everything works by unittesting phobos:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak unittest<br />
</syntaxhighlight><br />
<br />
== Common Windows issues ==<br />
<br />
=== Missing MASM386===<br />
<br />
If when building druntime you get errors about missing MASM386, it's due to a required assembling of a file called '''minit.asm'''. However the druntime repository includes a prebuilt minit.obj file so you shouldn't need to assemble it again. As a workaround for the make error create an empty '''masm386.bat''' file and put it in a directory that's in your '''PATH'''.<br />
<br />
It's also recommended that you use the cmd.exe terminal. Others, like PowerShell, are known to experience issues with legacy tools.<br />
<br />
=== Intermediate files lead to several errors ===<br />
<br />
The three main components (dmd, druntime, phobos) should always be built together with matching versions. The intermediate files generated by a previous build can lead to a failure so it's advisable to run<br />
<br />
<syntaxhighlight lang=dos><br />
make -fwin32.mak clean<br />
</syntaxhighlight><br />
<br />
on each component before starting the process.<br />
<br />
=== Using DigitalMars <code>make</code> for running the test suite ===<br />
<br />
DMD's testsuite can't be run with DigitalMars <code>make</code> - use GNUMake.<br />
Refer to the instructions in [[DMD_development#Running_the_testsuite_on_Windows | Running the test suite on Windows]].<br />
<br />
== Where to go from here ==<br />
<br />
If you want to contribute to a D project, please continue with the [[Starting_as_a_Contributor| starting as a contributor]] guide.<br />
If you want to contribute to Phobos, you may also read the [[Contributing to Phobos|contributing to Phobos guide]].<br />
<br />
[[Category:Windows]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Building_under_Windows&diff=10138Building under Windows2023-01-23T17:50:16Z<p>NickTreleaven: git is actually optional with the dmc tool chain instructions</p>
<hr />
<div>== Automation ==<br />
<br />
[https://github.com/CyberShadow/Digger Digger] can checkout and build any D version automatically for you. Only a D compiler is required. Digger will download all required dependencies by itself.<br />
<br />
<syntaxhighlight lang=bash><br />
dub fetch digger<br />
dub run digger<br />
</syntaxhighlight><br />
<br />
Among many other features, Digger can build older compiler versions or versions with a specific pull request added:<br />
<br />
<syntaxhighlight lang=bash><br />
# build a specific D version<br />
$ dub run digger -- build v2.064.2<br />
<br />
# build for x86-64<br />
$ dub run digger -- build --model=64 v2.064.2<br />
<br />
# build commit from a point in time<br />
$ dub run digger -- build "@ 3 weeks ago"<br />
<br />
# build specified branch from a point in time<br />
$ dub run digger -- build "2.065 @ 3 weeks ago"<br />
<br />
# build with an added pull request<br />
$ dub run digger -- build "master + dmd#123"<br />
</syntaxhighlight><br />
<br />
== Use Digital Mars make ==<br />
This page needs DigitalMars {{code|make}} (not to confuse with GNUMake). DigitalMars is part of the DMD Windows distribution and should be part of your {{code|PATH}}.<br />
<br />
If you have GNUMake installed on your system too, use the full path to DigitalMars make: {{code|C:\D\dmd2\windows\bin\make}}.<br />
<br />
== Building with Visual Studio ==<br />
<br />
=== Prerequisites ===<br />
<br />
* [https://visualstudio.microsoft.com/ Visual Studio]<br />
* [https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Window SDK]<br />
* [https://dlang.org/download.html DMD Windows Installer]<br />
* [https://rainers.github.io/visuald/visuald/StartPage.html VisualD]<br />
* [https://wiki.dlang.org/DMD_development#Running_the_testsuite_on_Windows make]<br />
<br />
=== Instructions ===<br />
<br />
* Run the DMD Windows Installer and make sure that the binaries get added to the PATH (check "Add to Path")<br />
* Install VisualD (can be done via the DMD installer with the "Download VisualD" checkbox)<br />
* Make sure that dmd gets installed to {{code|C:\D\dmd2}} (the default)<br />
<br />
=== Clone repositories ===<br />
<br />
Next step is to clone the 3 necessary source repos, dmd, phobos, and tools.<br />
<br />
<syntaxhighlight lang=dos><br />
mkdir C:\Source\D<br />
cd C:\Source\D<br />
git clone https://github.com/dlang/dmd<br />
git clone https://github.com/dlang/phobos<br />
git clone https://github.com/dlang/tools<br />
</syntaxhighlight><br />
<br />
Make sure to pick a folder without white spaces or special characters to avoid any potential problems.<br />
<br />
=== Building DMD ===<br />
<br />
You should be able to build DMD using the visual studio solution found in: {{code|dmd\src\vcbuild}}<br />
A typical choice is to build the 64-bit debug version (the VisualD options are named 'Release' and 'x64').<br />
<br />
A 'dmd.exe' should have been built and placed in {{code|C:\Source\D\dmd\generated\Windows\Debug\x64}}.<br />
<br />
If you want the 32-bit counterparts, you will have to adjust accordingly.<br />
Most notably, using win32.mak Makefiles instead of the win64.mak files.<br />
<br />
=== Building DRuntime ===<br />
<br />
Make sure that Visual Studio tools are part of your PATH. One common way is to run 'vcvarsall.bat'.<br />
With Visual Studio 2017 this call is:<br />
<br />
<syntaxhighlight lang=dos><br />
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64<br />
</syntaxhighlight ><br />
<br />
Now, go into druntime:<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\dmd\druntime<br />
</syntaxhighlight><br />
<br />
Then compile with DigitalMars make (not to confuse with GNUMake).<br />
<br />
<syntaxhighlight lang=dos><br />
set VCDIR="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC"<br />
make -f win64.mak -j4 "VCDIR=%VCDIR%" target<br />
</syntaxhighlight><br />
<br />
For building on 32-bit with the Visual Studio Runtime, use {{code|MODEL=32mscoff}}.<br />
<br />
=== Building Phobos ===<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\phobos<br />
make -f win64.mak -j4 target<br />
</syntaxhighlight><br />
<br />
== Building D ==<br />
<br />
These instructions use the dmc tool chain.<br />
<br />
=== Prerequisites ===<br />
<br />
On Windows, you will need [http://dlang.org/download.html#dmd D compiler], [http://ftp.digitalmars.com/dmc.zip the DigitalMars C++ compiler], and, for 64-bit or 32-bit COFF builds, the [https://www.microsoft.com/en-us/download/details.aspx?id=8279 Microsoft Windows SDK].<br />
<br />
Assuming that {{code|make}}, {{code|dmc}} and {{code|dmd}} from digital mars are in your path and your sources are in {{code|C:\D\dmd2\src}} which has the following structure:<br />
<syntaxhighlight lang=dos><br />
C:\D\dmd2\src\dmd<br />
C:\D\dmd2\src\phobos<br />
C:\D\dmd2\src\tools<br />
</syntaxhighlight><br />
<br />
Note: tools is optional. <br />
<br />
Alternatively, you may wish to clone the git repositories for each of the above using [https://git-scm.com/ Git for Windows].<br />
<br />
==== git Configuration ====<br />
<br />
When cloning from the GitHub repositories you may encounter problems if your git configuration on Windows replaces line endings with the Windows variant (i.e. {{code|\r\n}}) instead of leaving it as {{code|\n}}, which is what D repositories require.<br />
<br />
To check your settings, run {{code|git config core.autocrlf}}. If it prints {{code|true}}, set it to {{code|false}} with {{code|git config --global core.autocrlf false}}.<br />
<br />
=== Before you start ===<br />
<br />
The following instructions work for win32. May or may not work with win64. This scheme is a suggestion. These instructions should work when building from a clean repository, however, this repository contains autogenerated code that may be left behind after switching branches so running a git clean after switching branches is a good idea:<br />
<br />
<syntaxhighlight lang=dos><br />
git clean -xfd<br />
</syntaxhighlight><br />
<br />
=== Building DMD ===<br />
<br />
To build DMD compiler you should run the following commands ({{code|win32.mak}} file expects that {{code|HOST_DC}} variable is set to {{code|dmd}}):<br />
<syntaxhighlight lang=dos><br />
set DM_HOME=C:\D<br />
cd %DM_HOME%\dmd2\src\dmd\src<br />
set HOST_DC=dmd<br />
make -fwin32.mak release<br />
</syntaxhighlight><br />
<br />
From there, it is suggested to move the built binaries into your {{code|%DM_HOME%\windows\bin}} directory, and add that to your path:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\bin<br />
copy *.exe %DM_HOME%\dmd2\windows\bin<br />
set path=%DM_HOME%\dmd2\windows\bin;%path%<br />
</syntaxhighlight><br />
<br />
From there, you have to create a {{code|sc.ini}} in your {{code|%DM_HOME%\dmd2\windows\bin}} directory (where {{code|dmd.exe}} is). It is suggested to just copy paste the one provided in the packaged {{Latest DMD Version Raw}}, instead of writing your own, like:<br />
<syntaxhighlight lang=dos><br />
copy "C:\Program Files\D\dmd2\windows\bin\sc.ini" %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Building D runtime ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest druntime code.<br />
<br />
To build D runtime you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\druntime<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
==== Missing sppn.exe or cl.exe ====<br />
<br />
* For 32-bit you may need to download and extract sppn.zip next to your dmc.exe.<br />
* If you are using win64.mak, you may need to download cl.exe.<br />
Both can be found here:<br />
http://ftp.digitalmars.com/<br />
<br />
=== Building Phobos ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest phobos code.<br />
<br />
To build Phobos you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
You should copy phobos lib into your {{code|%DM_HOME%\windows\lib}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy phobos.lib %DM_HOME%\dmd2\windows\lib<br />
</syntaxhighlight><br />
<br />
=== Building rdmd ===<br />
<br />
Optionally, you can build rdmd from source if you have checked out {{code|tools}} in your sources. Some additional libs might be required for build and can simply be copy pasted from the {{Latest DMD Version Raw}} package without overwriting your {{code|phobos.lib}}.<br />
<br />
To build rdmd you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\tools<br />
make -fwin32.mak rdmd<br />
</syntaxhighlight><br />
<br />
You should copy rdmd into your {{code|%DM_HOME%\windows\bin}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy generated\windows\32\*.exe %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Thirdparty libraries ===<br />
<br />
The last step is getting the additional libs. curl for D2 can be found at the bottom of the download section of dlang.org: [[http://dlang.org/download.html download]].<br />
<br />
Additional libs that are necessary can simply be copy pasted from the {{Latest DMD Version Raw}} package (without overwriting your {{code|phobos.lib}}).<br />
<br />
=== Verifying ===<br />
<br />
The very last step is to verify that everything works by unittesting phobos:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak unittest<br />
</syntaxhighlight><br />
<br />
== Common Windows issues ==<br />
<br />
=== Missing MASM386===<br />
<br />
If when building druntime you get errors about missing MASM386, it's due to a required assembling of a file called '''minit.asm'''. However the druntime repository includes a prebuilt minit.obj file so you shouldn't need to assemble it again. As a workaround for the make error create an empty '''masm386.bat''' file and put it in a directory that's in your '''PATH'''.<br />
<br />
It's also recommended that you use the cmd.exe terminal. Others, like PowerShell, are known to experience issues with legacy tools.<br />
<br />
=== Intermediate files lead to several errors ===<br />
<br />
The three main components (dmd, druntime, phobos) should always be built together with matching versions. The intermediate files generated by a previous build can lead to a failure so it's advisable to run<br />
<br />
<syntaxhighlight lang=dos><br />
make -fwin32.mak clean<br />
</syntaxhighlight><br />
<br />
on each component before starting the process.<br />
<br />
=== Using DigitalMars <code>make</code> for running the test suite ===<br />
<br />
DMD's testsuite can't be run with DigitalMars <code>make</code> - use GNUMake.<br />
Refer to the instructions in [[DMD_development#Running_the_testsuite_on_Windows | Running the test suite on Windows]].<br />
<br />
== Where to go from here ==<br />
<br />
If you want to contribute to a D project, please continue with the [[Starting_as_a_Contributor| starting as a contributor]] guide.<br />
If you want to contribute to Phobos, you may also read the [[Contributing to Phobos|contributing to Phobos guide]].<br />
<br />
[[Category:Windows]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Building_under_Windows&diff=10137Building under Windows2023-01-23T17:39:02Z<p>NickTreleaven: Use dos highlighting not bash (affects paths)</p>
<hr />
<div>== Automation ==<br />
<br />
[https://github.com/CyberShadow/Digger Digger] can checkout and build any D version automatically for you. Only a D compiler is required. Digger will download all required dependencies by itself.<br />
<br />
<syntaxhighlight lang=bash><br />
dub fetch digger<br />
dub run digger<br />
</syntaxhighlight><br />
<br />
Among many other features, Digger can build older compiler versions or versions with a specific pull request added:<br />
<br />
<syntaxhighlight lang=bash><br />
# build a specific D version<br />
$ dub run digger -- build v2.064.2<br />
<br />
# build for x86-64<br />
$ dub run digger -- build --model=64 v2.064.2<br />
<br />
# build commit from a point in time<br />
$ dub run digger -- build "@ 3 weeks ago"<br />
<br />
# build specified branch from a point in time<br />
$ dub run digger -- build "2.065 @ 3 weeks ago"<br />
<br />
# build with an added pull request<br />
$ dub run digger -- build "master + dmd#123"<br />
</syntaxhighlight><br />
<br />
== Use Digital Mars make ==<br />
This page needs DigitalMars {{code|make}} (not to confuse with GNUMake). DigitalMars is part of the DMD Windows distribution and should be part of your {{code|PATH}}.<br />
<br />
If you have GNUMake installed on your system too, use the full path to DigitalMars make: {{code|C:\D\dmd2\windows\bin\make}}.<br />
<br />
== Building with Visual Studio ==<br />
<br />
=== Prerequisites ===<br />
<br />
* [https://visualstudio.microsoft.com/ Visual Studio]<br />
* [https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Window SDK]<br />
* [https://dlang.org/download.html DMD Windows Installer]<br />
* [https://rainers.github.io/visuald/visuald/StartPage.html VisualD]<br />
* [https://wiki.dlang.org/DMD_development#Running_the_testsuite_on_Windows make]<br />
<br />
=== Instructions ===<br />
<br />
* Run the DMD Windows Installer and make sure that the binaries get added to the PATH (check "Add to Path")<br />
* Install VisualD (can be done via the DMD installer with the "Download VisualD" checkbox)<br />
* Make sure that dmd gets installed to {{code|C:\D\dmd2}} (the default)<br />
<br />
=== Clone repositories ===<br />
<br />
Next step is to clone the 3 necessary source repos, dmd, phobos, and tools.<br />
<br />
<syntaxhighlight lang=dos><br />
mkdir C:\Source\D<br />
cd C:\Source\D<br />
git clone https://github.com/dlang/dmd<br />
git clone https://github.com/dlang/phobos<br />
git clone https://github.com/dlang/tools<br />
</syntaxhighlight><br />
<br />
Make sure to pick a folder without white spaces or special characters to avoid any potential problems.<br />
<br />
=== Building DMD ===<br />
<br />
You should be able to build DMD using the visual studio solution found in: {{code|dmd\src\vcbuild}}<br />
A typical choice is to build the 64-bit debug version (the VisualD options are named 'Release' and 'x64').<br />
<br />
A 'dmd.exe' should have been built and placed in {{code|C:\Source\D\dmd\generated\Windows\Debug\x64}}.<br />
<br />
If you want the 32-bit counterparts, you will have to adjust accordingly.<br />
Most notably, using win32.mak Makefiles instead of the win64.mak files.<br />
<br />
=== Building DRuntime ===<br />
<br />
Make sure that Visual Studio tools are part of your PATH. One common way is to run 'vcvarsall.bat'.<br />
With Visual Studio 2017 this call is:<br />
<br />
<syntaxhighlight lang=dos><br />
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64<br />
</syntaxhighlight ><br />
<br />
Now, go into druntime:<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\dmd\druntime<br />
</syntaxhighlight><br />
<br />
Then compile with DigitalMars make (not to confuse with GNUMake).<br />
<br />
<syntaxhighlight lang=dos><br />
set VCDIR="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC"<br />
make -f win64.mak -j4 "VCDIR=%VCDIR%" target<br />
</syntaxhighlight><br />
<br />
For building on 32-bit with the Visual Studio Runtime, use {{code|MODEL=32mscoff}}.<br />
<br />
=== Building Phobos ===<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\phobos<br />
make -f win64.mak -j4 target<br />
</syntaxhighlight><br />
<br />
== Building D ==<br />
<br />
These instructions use the dmc tool chain.<br />
<br />
=== Prerequisites ===<br />
<br />
On Windows, you will need [https://git-scm.com/ Git for Windows], [http://dlang.org/download.html#dmd D compiler], [http://ftp.digitalmars.com/dmc.zip the DigitalMars C++ compiler], and, for 64-bit or 32-bit COFF builds, the [https://www.microsoft.com/en-us/download/details.aspx?id=8279 Microsoft Windows SDK].<br />
<br />
Assuming that {{code|make}}, {{code|dmc}} and {{code|dmd}} from digital mars are in your path and your sources are checked out into {{code|C:\D\dmd2\src}} which has the following structure:<br />
<syntaxhighlight lang=dos><br />
C:\D\dmd2\src\dmd<br />
C:\D\dmd2\src\phobos<br />
C:\D\dmd2\src\tools<br />
</syntaxhighlight><br />
<br />
==== git Configuration ====<br />
<br />
When cloning from the GitHub repositories you may encounter problems if your git configuration on Windows replaces line endings with the Windows variant (i.e. {{code|\r\n}}) instead of leaving it as {{code|\n}}, which is what D repositories require.<br />
<br />
To check your settings, run {{code|git config core.autocrlf}}. If it prints {{code|true}}, set it to {{code|false}} with {{code|git config --global core.autocrlf false}}.<br />
<br />
=== Before you start ===<br />
<br />
The following instructions work for win32. May or may not work with win64. This scheme is a suggestion. These instructions should work when building from a clean repository, however, this repository contains autogenerated code that may be left behind after switching branches so running a git clean after switching branches is a good idea:<br />
<br />
<syntaxhighlight lang=dos><br />
git clean -xfd<br />
</syntaxhighlight><br />
<br />
=== Building DMD ===<br />
<br />
To build DMD compiler you should run the following commands ({{code|win32.mak}} file expects that {{code|HOST_DC}} variable is set to {{code|dmd}}):<br />
<syntaxhighlight lang=dos><br />
set DM_HOME=C:\D<br />
cd %DM_HOME%\dmd2\src\dmd\src<br />
set HOST_DC=dmd<br />
make -fwin32.mak release<br />
</syntaxhighlight><br />
<br />
From there, it is suggested to move the built binaries into your {{code|%DM_HOME%\windows\bin}} directory, and add that to your path:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\bin<br />
copy *.exe %DM_HOME%\dmd2\windows\bin<br />
set path=%DM_HOME%\dmd2\windows\bin;%path%<br />
</syntaxhighlight><br />
<br />
From there, you have to create a {{code|sc.ini}} in your {{code|%DM_HOME%\dmd2\windows\bin}} directory (where {{code|dmd.exe}} is). It is suggested to just copy paste the one provided in the packaged {{Latest DMD Version Raw}}, instead of writing your own, like:<br />
<syntaxhighlight lang=dos><br />
copy "C:\Program Files\D\dmd2\windows\bin\sc.ini" %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Building D runtime ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest druntime code.<br />
<br />
To build D runtime you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\druntime<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
==== Missing sppn.exe or cl.exe ====<br />
<br />
* For 32-bit you may need to download and extract sppn.zip next to your dmc.exe.<br />
* If you are using win64.mak, you may need to download cl.exe.<br />
Both can be found here:<br />
http://ftp.digitalmars.com/<br />
<br />
=== Building Phobos ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest phobos code.<br />
<br />
To build Phobos you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
You should copy phobos lib into your {{code|%DM_HOME%\windows\lib}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy phobos.lib %DM_HOME%\dmd2\windows\lib<br />
</syntaxhighlight><br />
<br />
=== Building rdmd ===<br />
<br />
Optionally, you can build rdmd from source if you have checked out {{code|tools}} in your sources. Some additional libs might be required for build and can simply be copy pasted from the {{Latest DMD Version Raw}} package without overwriting your {{code|phobos.lib}}.<br />
<br />
To build rdmd you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\tools<br />
make -fwin32.mak rdmd<br />
</syntaxhighlight><br />
<br />
You should copy rdmd into your {{code|%DM_HOME%\windows\bin}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy generated\windows\32\*.exe %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Thirdparty libraries ===<br />
<br />
The last step is getting the additional libs. curl for D2 can be found at the bottom of the download section of dlang.org: [[http://dlang.org/download.html download]].<br />
<br />
Additional libs that are necessary can simply be copy pasted from the {{Latest DMD Version Raw}} package (without overwriting your {{code|phobos.lib}}).<br />
<br />
=== Verifying ===<br />
<br />
The very last step is to verify that everything works by unittesting phobos:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak unittest<br />
</syntaxhighlight><br />
<br />
== Common Windows issues ==<br />
<br />
=== Missing MASM386===<br />
<br />
If when building druntime you get errors about missing MASM386, it's due to a required assembling of a file called '''minit.asm'''. However the druntime repository includes a prebuilt minit.obj file so you shouldn't need to assemble it again. As a workaround for the make error create an empty '''masm386.bat''' file and put it in a directory that's in your '''PATH'''.<br />
<br />
It's also recommended that you use the cmd.exe terminal. Others, like PowerShell, are known to experience issues with legacy tools.<br />
<br />
=== Intermediate files lead to several errors ===<br />
<br />
The three main components (dmd, druntime, phobos) should always be built together with matching versions. The intermediate files generated by a previous build can lead to a failure so it's advisable to run<br />
<br />
<syntaxhighlight lang=dos><br />
make -fwin32.mak clean<br />
</syntaxhighlight><br />
<br />
on each component before starting the process.<br />
<br />
=== Using DigitalMars <code>make</code> for running the test suite ===<br />
<br />
DMD's testsuite can't be run with DigitalMars <code>make</code> - use GNUMake.<br />
Refer to the instructions in [[DMD_development#Running_the_testsuite_on_Windows | Running the test suite on Windows]].<br />
<br />
== Where to go from here ==<br />
<br />
If you want to contribute to a D project, please continue with the [[Starting_as_a_Contributor| starting as a contributor]] guide.<br />
If you want to contribute to Phobos, you may also read the [[Contributing to Phobos|contributing to Phobos guide]].<br />
<br />
[[Category:Windows]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Building_under_Windows&diff=10136Building under Windows2023-01-23T17:32:40Z<p>NickTreleaven: Reparent Prerequisites under 'Building D' heading</p>
<hr />
<div>== Automation ==<br />
<br />
[https://github.com/CyberShadow/Digger Digger] can checkout and build any D version automatically for you. Only a D compiler is required. Digger will download all required dependencies by itself.<br />
<br />
<syntaxhighlight lang=bash><br />
dub fetch digger<br />
dub run digger<br />
</syntaxhighlight><br />
<br />
Among many other features, Digger can build older compiler versions or versions with a specific pull request added:<br />
<br />
<syntaxhighlight lang=bash><br />
# build a specific D version<br />
$ dub run digger -- build v2.064.2<br />
<br />
# build for x86-64<br />
$ dub run digger -- build --model=64 v2.064.2<br />
<br />
# build commit from a point in time<br />
$ dub run digger -- build "@ 3 weeks ago"<br />
<br />
# build specified branch from a point in time<br />
$ dub run digger -- build "2.065 @ 3 weeks ago"<br />
<br />
# build with an added pull request<br />
$ dub run digger -- build "master + dmd#123"<br />
</syntaxhighlight><br />
<br />
== Use Digital Mars make ==<br />
This page needs DigitalMars {{code|make}} (not to confuse with GNUMake). DigitalMars is part of the DMD Windows distribution and should be part of your {{code|PATH}}.<br />
<br />
If you have GNUMake installed on your system too, use the full path to DigitalMars make: {{code|C:\D\dmd2\windows\bin\make}}.<br />
<br />
== Building with Visual Studio ==<br />
<br />
=== Prerequisites ===<br />
<br />
* [https://visualstudio.microsoft.com/ Visual Studio]<br />
* [https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Window SDK]<br />
* [https://dlang.org/download.html DMD Windows Installer]<br />
* [https://rainers.github.io/visuald/visuald/StartPage.html VisualD]<br />
* [https://wiki.dlang.org/DMD_development#Running_the_testsuite_on_Windows make]<br />
<br />
=== Instructions ===<br />
<br />
* Run the DMD Windows Installer and make sure that the binaries get added to the PATH (check "Add to Path")<br />
* Install VisualD (can be done via the DMD installer with the "Download VisualD" checkbox)<br />
* Make sure that dmd gets installed to {{code|C:\D\dmd2}} (the default)<br />
<br />
=== Clone repositories ===<br />
<br />
Next step is to clone the 3 necessary source repos, dmd, phobos, and tools.<br />
<br />
<syntaxhighlight lang=bash><br />
mkdir C:\Source\D<br />
cd C:\Source\D<br />
git clone https://github.com/dlang/dmd<br />
git clone https://github.com/dlang/phobos<br />
git clone https://github.com/dlang/tools<br />
</syntaxhighlight><br />
<br />
Make sure to pick a folder without white spaces or special characters to avoid any potential problems.<br />
<br />
=== Building DMD ===<br />
<br />
You should be able to build DMD using the visual studio solution found in: {{code|dmd\src\vcbuild}}<br />
A typical choice is to build the 64-bit debug version (the VisualD options are named 'Release' and 'x64').<br />
<br />
A 'dmd.exe' should have been built and placed in {{code|C:\Source\D\dmd\generated\Windows\Debug\x64}}.<br />
<br />
If you want the 32-bit counterparts, you will have to adjust accordingly.<br />
Most notably, using win32.mak Makefiles instead of the win64.mak files.<br />
<br />
=== Building DRuntime ===<br />
<br />
Make sure that Visual Studio tools are part of your PATH. One common way is to run 'vcvarsall.bat'.<br />
With Visual Studio 2017 this call is:<br />
<br />
<syntaxhighlight lang=dos><br />
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64<br />
</syntaxhighlight ><br />
<br />
Now, go into druntime:<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\dmd\druntime<br />
</syntaxhighlight><br />
<br />
Then compile with DigitalMars make (not to confuse with GNUMake).<br />
<br />
<syntaxhighlight lang=dos><br />
set VCDIR="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC"<br />
make -f win64.mak -j4 "VCDIR=%VCDIR%" target<br />
</syntaxhighlight><br />
<br />
For building on 32-bit with the Visual Studio Runtime, use {{code|MODEL=32mscoff}}.<br />
<br />
=== Building Phobos ===<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\phobos<br />
make -f win64.mak -j4 target<br />
</syntaxhighlight><br />
<br />
== Building D ==<br />
<br />
These instructions use the dmc tool chain.<br />
<br />
=== Prerequisites ===<br />
<br />
On Windows, you will need [https://git-scm.com/ Git for Windows], [http://dlang.org/download.html#dmd D compiler], [http://ftp.digitalmars.com/dmc.zip the DigitalMars C++ compiler], and, for 64-bit or 32-bit COFF builds, the [https://www.microsoft.com/en-us/download/details.aspx?id=8279 Microsoft Windows SDK].<br />
<br />
Assuming that {{code|make}}, {{code|dmc}} and {{code|dmd}} from digital mars are in your path and your sources are checked out into {{code|C:\D\dmd2\src}} which has the following structure:<br />
<syntaxhighlight lang=dos><br />
C:\D\dmd2\src\dmd<br />
C:\D\dmd2\src\phobos<br />
C:\D\dmd2\src\tools<br />
</syntaxhighlight><br />
<br />
==== git Configuration ====<br />
<br />
When cloning from the GitHub repositories you may encounter problems if your git configuration on Windows replaces line endings with the Windows variant (i.e. {{code|\r\n}}) instead of leaving it as {{code|\n}}, which is what D repositories require.<br />
<br />
To check your settings, run {{code|git config core.autocrlf}}. If it prints {{code|true}}, set it to {{code|false}} with {{code|git config --global core.autocrlf false}}.<br />
<br />
=== Before you start ===<br />
<br />
The following instructions work for win32. May or may not work with win64. This scheme is a suggestion. These instructions should work when building from a clean repository, however, this repository contains autogenerated code that may be left behind after switching branches so running a git clean after switching branches is a good idea:<br />
<br />
<syntaxhighlight lang=dos><br />
git clean -xfd<br />
</syntaxhighlight><br />
<br />
=== Building DMD ===<br />
<br />
To build DMD compiler you should run the following commands ({{code|win32.mak}} file expects that {{code|HOST_DC}} variable is set to {{code|dmd}}):<br />
<syntaxhighlight lang=dos><br />
set DM_HOME=C:\D<br />
cd %DM_HOME%\dmd2\src\dmd\src<br />
set HOST_DC=dmd<br />
make -fwin32.mak release<br />
</syntaxhighlight><br />
<br />
From there, it is suggested to move the built binaries into your {{code|%DM_HOME%\windows\bin}} directory, and add that to your path:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\bin<br />
copy *.exe %DM_HOME%\dmd2\windows\bin<br />
set path=%DM_HOME%\dmd2\windows\bin;%path%<br />
</syntaxhighlight><br />
<br />
From there, you have to create a {{code|sc.ini}} in your {{code|%DM_HOME%\dmd2\windows\bin}} directory (where {{code|dmd.exe}} is). It is suggested to just copy paste the one provided in the packaged {{Latest DMD Version Raw}}, instead of writing your own, like:<br />
<syntaxhighlight lang=dos><br />
copy "C:\Program Files\D\dmd2\windows\bin\sc.ini" %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Building D runtime ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest druntime code.<br />
<br />
To build D runtime you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\druntime<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
==== Missing sppn.exe or cl.exe ====<br />
<br />
* For 32-bit you may need to download and extract sppn.zip next to your dmc.exe.<br />
* If you are using win64.mak, you may need to download cl.exe.<br />
Both can be found here:<br />
http://ftp.digitalmars.com/<br />
<br />
=== Building Phobos ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest phobos code.<br />
<br />
To build Phobos you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
You should copy phobos lib into your {{code|%DM_HOME%\windows\lib}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy phobos.lib %DM_HOME%\dmd2\windows\lib<br />
</syntaxhighlight><br />
<br />
=== Building rdmd ===<br />
<br />
Optionally, you can build rdmd from source if you have checked out {{code|tools}} in your sources. Some additional libs might be required for build and can simply be copy pasted from the {{Latest DMD Version Raw}} package without overwriting your {{code|phobos.lib}}.<br />
<br />
To build rdmd you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\tools<br />
make -fwin32.mak rdmd<br />
</syntaxhighlight><br />
<br />
You should copy rdmd into your {{code|%DM_HOME%\windows\bin}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy generated\windows\32\*.exe %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Thirdparty libraries ===<br />
<br />
The last step is getting the additional libs. curl for D2 can be found at the bottom of the download section of dlang.org: [[http://dlang.org/download.html download]].<br />
<br />
Additional libs that are necessary can simply be copy pasted from the {{Latest DMD Version Raw}} package (without overwriting your {{code|phobos.lib}}).<br />
<br />
=== Verifying ===<br />
<br />
The very last step is to verify that everything works by unittesting phobos:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak unittest<br />
</syntaxhighlight><br />
<br />
== Common Windows issues ==<br />
<br />
=== Missing MASM386===<br />
<br />
If when building druntime you get errors about missing MASM386, it's due to a required assembling of a file called '''minit.asm'''. However the druntime repository includes a prebuilt minit.obj file so you shouldn't need to assemble it again. As a workaround for the make error create an empty '''masm386.bat''' file and put it in a directory that's in your '''PATH'''.<br />
<br />
It's also recommended that you use the cmd.exe terminal. Others, like PowerShell, are known to experience issues with legacy tools.<br />
<br />
=== Intermediate files lead to several errors ===<br />
<br />
The three main components (dmd, druntime, phobos) should always be built together with matching versions. The intermediate files generated by a previous build can lead to a failure so it's advisable to run<br />
<br />
<syntaxhighlight lang=dos><br />
make -fwin32.mak clean<br />
</syntaxhighlight><br />
<br />
on each component before starting the process.<br />
<br />
=== Using DigitalMars <code>make</code> for running the test suite ===<br />
<br />
DMD's testsuite can't be run with DigitalMars <code>make</code> - use GNUMake.<br />
Refer to the instructions in [[DMD_development#Running_the_testsuite_on_Windows | Running the test suite on Windows]].<br />
<br />
== Where to go from here ==<br />
<br />
If you want to contribute to a D project, please continue with the [[Starting_as_a_Contributor| starting as a contributor]] guide.<br />
If you want to contribute to Phobos, you may also read the [[Contributing to Phobos|contributing to Phobos guide]].<br />
<br />
[[Category:Windows]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Building_under_Windows&diff=10135Building under Windows2023-01-23T17:11:59Z<p>NickTreleaven: Add druntime note: Missing sppn.exe or cl.exe</p>
<hr />
<div>== Automation ==<br />
<br />
[https://github.com/CyberShadow/Digger Digger] can checkout and build any D version automatically for you. Only a D compiler is required. Digger will download all required dependencies by itself.<br />
<br />
<syntaxhighlight lang=bash><br />
dub fetch digger<br />
dub run digger<br />
</syntaxhighlight><br />
<br />
Among many other features, Digger can build older compiler versions or versions with a specific pull request added:<br />
<br />
<syntaxhighlight lang=bash><br />
# build a specific D version<br />
$ dub run digger -- build v2.064.2<br />
<br />
# build for x86-64<br />
$ dub run digger -- build --model=64 v2.064.2<br />
<br />
# build commit from a point in time<br />
$ dub run digger -- build "@ 3 weeks ago"<br />
<br />
# build specified branch from a point in time<br />
$ dub run digger -- build "2.065 @ 3 weeks ago"<br />
<br />
# build with an added pull request<br />
$ dub run digger -- build "master + dmd#123"<br />
</syntaxhighlight><br />
<br />
== Use Digital Mars make ==<br />
This page needs DigitalMars {{code|make}} (not to confuse with GNUMake). DigitalMars is part of the DMD Windows distribution and should be part of your {{code|PATH}}.<br />
<br />
If you have GNUMake installed on your system too, use the full path to DigitalMars make: {{code|C:\D\dmd2\windows\bin\make}}.<br />
<br />
== Building with Visual Studio ==<br />
<br />
=== Prerequisites ===<br />
<br />
* [https://visualstudio.microsoft.com/ Visual Studio]<br />
* [https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Window SDK]<br />
* [https://dlang.org/download.html DMD Windows Installer]<br />
* [https://rainers.github.io/visuald/visuald/StartPage.html VisualD]<br />
* [https://wiki.dlang.org/DMD_development#Running_the_testsuite_on_Windows make]<br />
<br />
=== Instructions ===<br />
<br />
* Run the DMD Windows Installer and make sure that the binaries get added to the PATH (check "Add to Path")<br />
* Install VisualD (can be done via the DMD installer with the "Download VisualD" checkbox)<br />
* Make sure that dmd gets installed to {{code|C:\D\dmd2}} (the default)<br />
<br />
=== Clone repositories ===<br />
<br />
Next step is to clone the 3 necessary source repos, dmd, phobos, and tools.<br />
<br />
<syntaxhighlight lang=bash><br />
mkdir C:\Source\D<br />
cd C:\Source\D<br />
git clone https://github.com/dlang/dmd<br />
git clone https://github.com/dlang/phobos<br />
git clone https://github.com/dlang/tools<br />
</syntaxhighlight><br />
<br />
Make sure to pick a folder without white spaces or special characters to avoid any potential problems.<br />
<br />
=== Building DMD ===<br />
<br />
You should be able to build DMD using the visual studio solution found in: {{code|dmd\src\vcbuild}}<br />
A typical choice is to build the 64-bit debug version (the VisualD options are named 'Release' and 'x64').<br />
<br />
A 'dmd.exe' should have been built and placed in {{code|C:\Source\D\dmd\generated\Windows\Debug\x64}}.<br />
<br />
If you want the 32-bit counterparts, you will have to adjust accordingly.<br />
Most notably, using win32.mak Makefiles instead of the win64.mak files.<br />
<br />
=== Building DRuntime ===<br />
<br />
Make sure that Visual Studio tools are part of your PATH. One common way is to run 'vcvarsall.bat'.<br />
With Visual Studio 2017 this call is:<br />
<br />
<syntaxhighlight lang=dos><br />
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64<br />
</syntaxhighlight ><br />
<br />
Now, go into druntime:<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\dmd\druntime<br />
</syntaxhighlight><br />
<br />
Then compile with DigitalMars make (not to confuse with GNUMake).<br />
<br />
<syntaxhighlight lang=dos><br />
set VCDIR="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC"<br />
make -f win64.mak -j4 "VCDIR=%VCDIR%" target<br />
</syntaxhighlight><br />
<br />
For building on 32-bit with the Visual Studio Runtime, use {{code|MODEL=32mscoff}}.<br />
<br />
=== Building Phobos ===<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\phobos<br />
make -f win64.mak -j4 target<br />
</syntaxhighlight><br />
<br />
== Prerequisites ==<br />
<br />
On Windows, you will need [https://git-scm.com/ Git for Windows], [http://dlang.org/download.html#dmd D compiler], [http://ftp.digitalmars.com/dmc.zip the DigitalMars C++ compiler], and, for 64-bit or 32-bit COFF builds, the [https://www.microsoft.com/en-us/download/details.aspx?id=8279 Microsoft Windows SDK].<br />
<br />
Assuming that {{code|make}}, {{code|dmc}} and {{code|dmd}} from digital mars are in your path and your sources are checked out into {{code|C:\D\dmd2\src}} which has the following structure:<br />
<syntaxhighlight lang=dos><br />
C:\D\dmd2\src\dmd<br />
C:\D\dmd2\src\phobos<br />
C:\D\dmd2\src\tools<br />
</syntaxhighlight><br />
<br />
=== git Configuration ===<br />
<br />
When cloning from the GitHub repositories you may encounter problems if your git configuration on Windows replaces line endings with the Windows variant (i.e. {{code|\r\n}}) instead of leaving it as {{code|\n}}, which is what D repositories require.<br />
<br />
To check your settings, run {{code|git config core.autocrlf}}. If it prints {{code|true}}, set it to {{code|false}} with {{code|git config --global core.autocrlf false}}.<br />
<br />
== Building D ==<br />
<br />
The following instructions work for win32. May or may not work with win64. This scheme is a suggestion. These instructions should work when building from a clean repository, however, this repository contains autogenerated code that may be left behind after switching branches so running a git clean after switching branches is a good idea:<br />
<br />
<syntaxhighlight lang=dos><br />
git clean -xfd<br />
</syntaxhighlight><br />
<br />
=== Building DMD ===<br />
<br />
To build DMD compiler you should run the following commands ({{code|win32.mak}} file expects that {{code|HOST_DC}} variable is set to {{code|dmd}}):<br />
<syntaxhighlight lang=dos><br />
set DM_HOME=C:\D<br />
cd %DM_HOME%\dmd2\src\dmd\src<br />
set HOST_DC=dmd<br />
make -fwin32.mak release<br />
</syntaxhighlight><br />
<br />
From there, it is suggested to move the built binaries into your {{code|%DM_HOME%\windows\bin}} directory, and add that to your path:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\bin<br />
copy *.exe %DM_HOME%\dmd2\windows\bin<br />
set path=%DM_HOME%\dmd2\windows\bin;%path%<br />
</syntaxhighlight><br />
<br />
From there, you have to create a {{code|sc.ini}} in your {{code|%DM_HOME%\dmd2\windows\bin}} directory (where {{code|dmd.exe}} is). It is suggested to just copy paste the one provided in the packaged {{Latest DMD Version Raw}}, instead of writing your own, like:<br />
<syntaxhighlight lang=dos><br />
copy "C:\Program Files\D\dmd2\windows\bin\sc.ini" %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Building D runtime ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest druntime code.<br />
<br />
To build D runtime you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\druntime<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
==== Missing sppn.exe or cl.exe ====<br />
<br />
* For 32-bit you may need to download and extract sppn.zip next to your dmc.exe.<br />
* If you are using win64.mak, you may need to download cl.exe.<br />
Both can be found here:<br />
http://ftp.digitalmars.com/<br />
<br />
=== Building Phobos ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest phobos code.<br />
<br />
To build Phobos you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
You should copy phobos lib into your {{code|%DM_HOME%\windows\lib}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy phobos.lib %DM_HOME%\dmd2\windows\lib<br />
</syntaxhighlight><br />
<br />
=== Building rdmd ===<br />
<br />
Optionally, you can build rdmd from source if you have checked out {{code|tools}} in your sources. Some additional libs might be required for build and can simply be copy pasted from the {{Latest DMD Version Raw}} package without overwriting your {{code|phobos.lib}}.<br />
<br />
To build rdmd you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\tools<br />
make -fwin32.mak rdmd<br />
</syntaxhighlight><br />
<br />
You should copy rdmd into your {{code|%DM_HOME%\windows\bin}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy generated\windows\32\*.exe %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Thirdparty libraries ===<br />
<br />
The last step is getting the additional libs. curl for D2 can be found at the bottom of the download section of dlang.org: [[http://dlang.org/download.html download]].<br />
<br />
Additional libs that are necessary can simply be copy pasted from the {{Latest DMD Version Raw}} package (without overwriting your {{code|phobos.lib}}).<br />
<br />
=== Verifying ===<br />
<br />
The very last step is to verify that everything works by unittesting phobos:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak unittest<br />
</syntaxhighlight><br />
<br />
== Common Windows issues ==<br />
<br />
=== Missing MASM386===<br />
<br />
If when building druntime you get errors about missing MASM386, it's due to a required assembling of a file called '''minit.asm'''. However the druntime repository includes a prebuilt minit.obj file so you shouldn't need to assemble it again. As a workaround for the make error create an empty '''masm386.bat''' file and put it in a directory that's in your '''PATH'''.<br />
<br />
It's also recommended that you use the cmd.exe terminal. Others, like PowerShell, are known to experience issues with legacy tools.<br />
<br />
=== Intermediate files lead to several errors ===<br />
<br />
The three main components (dmd, druntime, phobos) should always be built together with matching versions. The intermediate files generated by a previous build can lead to a failure so it's advisable to run<br />
<br />
<syntaxhighlight lang=dos><br />
make -fwin32.mak clean<br />
</syntaxhighlight><br />
<br />
on each component before starting the process.<br />
<br />
=== Using DigitalMars <code>make</code> for running the test suite ===<br />
<br />
DMD's testsuite can't be run with DigitalMars <code>make</code> - use GNUMake.<br />
Refer to the instructions in [[DMD_development#Running_the_testsuite_on_Windows | Running the test suite on Windows]].<br />
<br />
== Where to go from here ==<br />
<br />
If you want to contribute to a D project, please continue with the [[Starting_as_a_Contributor| starting as a contributor]] guide.<br />
If you want to contribute to Phobos, you may also read the [[Contributing to Phobos|contributing to Phobos guide]].<br />
<br />
[[Category:Windows]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Building_under_Windows&diff=10133Building under Windows2023-01-22T12:25:49Z<p>NickTreleaven: Move DM `make` note above VS section as it applies to all</p>
<hr />
<div>== Automation ==<br />
<br />
[https://github.com/CyberShadow/Digger Digger] can checkout and build any D version automatically for you. Only a D compiler is required. Digger will download all required dependencies by itself.<br />
<br />
<syntaxhighlight lang=bash><br />
dub fetch digger<br />
dub run digger<br />
</syntaxhighlight><br />
<br />
Among many other features, Digger can build older compiler versions or versions with a specific pull request added:<br />
<br />
<syntaxhighlight lang=bash><br />
# build a specific D version<br />
$ dub run digger -- build v2.064.2<br />
<br />
# build for x86-64<br />
$ dub run digger -- build --model=64 v2.064.2<br />
<br />
# build commit from a point in time<br />
$ dub run digger -- build "@ 3 weeks ago"<br />
<br />
# build specified branch from a point in time<br />
$ dub run digger -- build "2.065 @ 3 weeks ago"<br />
<br />
# build with an added pull request<br />
$ dub run digger -- build "master + dmd#123"<br />
</syntaxhighlight><br />
<br />
== Use Digital Mars make ==<br />
This page needs DigitalMars {{code|make}} (not to confuse with GNUMake). DigitalMars is part of the DMD Windows distribution and should be part of your {{code|PATH}}.<br />
<br />
If you have GNUMake installed on your system too, use the full path to DigitalMars make: {{code|C:\D\dmd2\windows\bin\make}}.<br />
<br />
== Building with Visual Studio ==<br />
<br />
=== Prerequisites ===<br />
<br />
* [https://visualstudio.microsoft.com/ Visual Studio]<br />
* [https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Window SDK]<br />
* [https://dlang.org/download.html DMD Windows Installer]<br />
* [https://rainers.github.io/visuald/visuald/StartPage.html VisualD]<br />
* [https://wiki.dlang.org/DMD_development#Running_the_testsuite_on_Windows make]<br />
<br />
=== Instructions ===<br />
<br />
* Run the DMD Windows Installer and make sure that the binaries get added to the PATH (check "Add to Path")<br />
* Install VisualD (can be done via the DMD installer with the "Download VisualD" checkbox)<br />
* Make sure that dmd gets installed to {{code|C:\D\dmd2}} (the default)<br />
<br />
=== Clone repositories ===<br />
<br />
Next step is to clone the 3 necessary source repos, dmd, phobos, and tools.<br />
<br />
<syntaxhighlight lang=bash><br />
mkdir C:\Source\D<br />
cd C:\Source\D<br />
git clone https://github.com/dlang/dmd<br />
git clone https://github.com/dlang/phobos<br />
git clone https://github.com/dlang/tools<br />
</syntaxhighlight><br />
<br />
Make sure to pick a folder without white spaces or special characters to avoid any potential problems.<br />
<br />
=== Building DMD ===<br />
<br />
You should be able to build DMD using the visual studio solution found in: {{code|dmd\src\vcbuild}}<br />
A typical choice is to build the 64-bit debug version (the VisualD options are named 'Release' and 'x64').<br />
<br />
A 'dmd.exe' should have been built and placed in {{code|C:\Source\D\dmd\generated\Windows\Debug\x64}}.<br />
<br />
If you want the 32-bit counterparts, you will have to adjust accordingly.<br />
Most notably, using win32.mak Makefiles instead of the win64.mak files.<br />
<br />
=== Building DRuntime ===<br />
<br />
Make sure that Visual Studio tools are part of your PATH. One common way is to run 'vcvarsall.bat'.<br />
With Visual Studio 2017 this call is:<br />
<br />
<syntaxhighlight lang=dos><br />
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64<br />
</syntaxhighlight ><br />
<br />
Now, go into druntime:<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\dmd\druntime<br />
</syntaxhighlight><br />
<br />
Then compile with DigitalMars make (not to confuse with GNUMake).<br />
<br />
<syntaxhighlight lang=dos><br />
set VCDIR="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC"<br />
make -f win64.mak -j4 "VCDIR=%VCDIR%" target<br />
</syntaxhighlight><br />
<br />
For building on 32-bit with the Visual Studio Runtime, use {{code|MODEL=32mscoff}}.<br />
<br />
=== Building Phobos ===<br />
<br />
<syntaxhighlight lang=dos><br />
cd C:\source\D\phobos<br />
make -f win64.mak -j4 target<br />
</syntaxhighlight><br />
<br />
== Prerequisites ==<br />
<br />
On Windows, you will need [https://git-scm.com/ Git for Windows], [http://dlang.org/download.html#dmd D compiler], [http://ftp.digitalmars.com/dmc.zip the DigitalMars C++ compiler], and, for 64-bit or 32-bit COFF builds, the [https://www.microsoft.com/en-us/download/details.aspx?id=8279 Microsoft Windows SDK].<br />
<br />
Assuming that {{code|make}}, {{code|dmc}} and {{code|dmd}} from digital mars are in your path and your sources are checked out into {{code|C:\D\dmd2\src}} which has the following structure:<br />
<syntaxhighlight lang=dos><br />
C:\D\dmd2\src\dmd<br />
C:\D\dmd2\src\phobos<br />
C:\D\dmd2\src\tools<br />
</syntaxhighlight><br />
<br />
=== git Configuration ===<br />
<br />
When cloning from the GitHub repositories you may encounter problems if your git configuration on Windows replaces line endings with the Windows variant (i.e. {{code|\r\n}}) instead of leaving it as {{code|\n}}, which is what D repositories require.<br />
<br />
To check your settings, run {{code|git config core.autocrlf}}. If it prints {{code|true}}, set it to {{code|false}} with {{code|git config --global core.autocrlf false}}.<br />
<br />
== Building D ==<br />
<br />
The following instructions work for win32. May or may not work with win64. This scheme is a suggestion. These instructions should work when building from a clean repository, however, this repository contains autogenerated code that may be left behind after switching branches so running a git clean after switching branches is a good idea:<br />
<br />
<syntaxhighlight lang=dos><br />
git clean -xfd<br />
</syntaxhighlight><br />
<br />
=== Building DMD ===<br />
<br />
To build DMD compiler you should run the following commands ({{code|win32.mak}} file expects that {{code|HOST_DC}} variable is set to {{code|dmd}}):<br />
<syntaxhighlight lang=dos><br />
set DM_HOME=C:\D<br />
cd %DM_HOME%\dmd2\src\dmd\src<br />
set HOST_DC=dmd<br />
make -fwin32.mak release<br />
</syntaxhighlight><br />
<br />
From there, it is suggested to move the built binaries into your {{code|%DM_HOME%\windows\bin}} directory, and add that to your path:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\bin<br />
copy *.exe %DM_HOME%\dmd2\windows\bin<br />
set path=%DM_HOME%\dmd2\windows\bin;%path%<br />
</syntaxhighlight><br />
<br />
From there, you have to create a {{code|sc.ini}} in your {{code|%DM_HOME%\dmd2\windows\bin}} directory (where {{code|dmd.exe}} is). It is suggested to just copy paste the one provided in the packaged {{Latest DMD Version Raw}}, instead of writing your own, like:<br />
<syntaxhighlight lang=dos><br />
copy "C:\Program Files\D\dmd2\windows\bin\sc.ini" %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Building D runtime ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest druntime code.<br />
<br />
To build D runtime you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\druntime<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
=== Building Phobos ===<br />
<br />
Make sure that you are using {{code|dmd}} compiled in previous step because older compiler might not compile the latest phobos code.<br />
<br />
To build Phobos you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak<br />
</syntaxhighlight><br />
<br />
You should copy phobos lib into your {{code|%DM_HOME%\windows\lib}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy phobos.lib %DM_HOME%\dmd2\windows\lib<br />
</syntaxhighlight><br />
<br />
=== Building rdmd ===<br />
<br />
Optionally, you can build rdmd from source if you have checked out {{code|tools}} in your sources. Some additional libs might be required for build and can simply be copy pasted from the {{Latest DMD Version Raw}} package without overwriting your {{code|phobos.lib}}.<br />
<br />
To build rdmd you should run the following commands:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\tools<br />
make -fwin32.mak rdmd<br />
</syntaxhighlight><br />
<br />
You should copy rdmd into your {{code|%DM_HOME%\windows\bin}} folder:<br />
<syntaxhighlight lang=dos><br />
mkdir %DM_HOME%\dmd2\windows\lib<br />
copy generated\windows\32\*.exe %DM_HOME%\dmd2\windows\bin<br />
</syntaxhighlight><br />
<br />
=== Thirdparty libraries ===<br />
<br />
The last step is getting the additional libs. curl for D2 can be found at the bottom of the download section of dlang.org: [[http://dlang.org/download.html download]].<br />
<br />
Additional libs that are necessary can simply be copy pasted from the {{Latest DMD Version Raw}} package (without overwriting your {{code|phobos.lib}}).<br />
<br />
=== Verifying ===<br />
<br />
The very last step is to verify that everything works by unittesting phobos:<br />
<syntaxhighlight lang=dos><br />
cd %DM_HOME%\dmd2\src\phobos<br />
make -fwin32.mak unittest<br />
</syntaxhighlight><br />
<br />
== Common Windows issues ==<br />
<br />
=== Missing MASM386===<br />
<br />
If when building druntime you get errors about missing MASM386, it's due to a required assembling of a file called '''minit.asm'''. However the druntime repository includes a prebuilt minit.obj file so you shouldn't need to assemble it again. As a workaround for the make error create an empty '''masm386.bat''' file and put it in a directory that's in your '''PATH'''.<br />
<br />
It's also recommended that you use the cmd.exe terminal. Others, like PowerShell, are known to experience issues with legacy tools.<br />
<br />
=== Intermediate files lead to several errors ===<br />
<br />
The three main components (dmd, druntime, phobos) should always be built together with matching versions. The intermediate files generated by a previous build can lead to a failure so it's advisable to run<br />
<br />
<syntaxhighlight lang=dos><br />
make -fwin32.mak clean<br />
</syntaxhighlight><br />
<br />
on each component before starting the process.<br />
<br />
=== Using DigitalMars <code>make</code> for running the test suite ===<br />
<br />
DMD's testsuite can't be run with DigitalMars <code>make</code> - use GNUMake.<br />
Refer to the instructions in [[DMD_development#Running_the_testsuite_on_Windows | Running the test suite on Windows]].<br />
<br />
== Where to go from here ==<br />
<br />
If you want to contribute to a D project, please continue with the [[Starting_as_a_Contributor| starting as a contributor]] guide.<br />
If you want to contribute to Phobos, you may also read the [[Contributing to Phobos|contributing to Phobos guide]].<br />
<br />
[[Category:Windows]]</div>NickTreleavenhttps://wiki.dlang.org/?title=DMD_development&diff=10125DMD development2022-11-06T21:29:21Z<p>NickTreleaven: Update paths to dmd/compiler/</p>
<hr />
<div>Welcome to the D community and thanks for your interest in contributing!<br />
If you need help you can ask questions on <code>#d</code> IRC channel on freenode.org ([https://kiwiirc.com/client/irc.freenode.net/d web interface]) or on [http://forum.dlang.org/ our forum].<br />
<br />
This section explains commonly commands which are commonly used to test the [[DMD|dmd]] D Programming Language compiler.<br />
<br />
== Tests ==<br />
<br />
The testsuite is in <code>~/dlang/dmd/compiler/test</code>. Please go to this directory.<br />
<br />
<syntaxhighlight lang=bash><br />
cd ~/dlang/dmd/compiler/test<br />
</syntaxhighlight><br />
<br />
The testsuite will always print the exact command used to run a test, s.t. it's easy to single out and reproduce a failure.<br />
<br />
=== Running all tests ===<br />
<br />
<syntaxhighlight lang=bash><br />
./run.d<br />
</syntaxhighlight><br />
<br />
The testsuite runner will automatically use all available threads. You can use e.g. <code>-j1</code> to e.g. use one thread.<br />
<br />
=== Run a specific test category ===<br />
<br />
<syntaxhighlight lang=bash><br />
./run.d fail_compilation<br />
</syntaxhighlight><br />
<br />
=== Run a specific test ===<br />
<br />
<syntaxhighlight lang=bash><br />
./run.d fail_compilation/ice12673.d<br />
</syntaxhighlight><br />
<br />
=== Run a set of specific tests ===<br />
<br />
<syntaxhighlight lang=bash><br />
./run.d fail_compilation/ice*<br />
</syntaxhighlight><br />
<br />
=== Automatically update the OUTPUT text ===<br />
<br />
<syntaxhighlight lang=bash><br />
./run.d fail_compilation AUTO_UPDATE=1<br />
</syntaxhighlight><br />
<br />
A second run might be required.<br />
<br />
=== Remove test states ===<br />
<br />
<syntaxhighlight lang=bash><br />
./run.d clean<br />
</syntaxhighlight><br />
<br />
=== Run unittests within the compiler ===<br />
<br />
There are a few [[Unittest|unittest]] blocks within the compiler and there usage is increasing.<br />
They can be tested with:<br />
<br />
<syntaxhighlight lang=bash><br />
cd ~/dlang/dmd/compiler/src<br />
make -f posix.mak unittest<br />
</syntaxhighlight><br />
<br />
<br />
== Old Makefile targets ==<br />
<br />
The following section explains the Makefile rules of the <code>test/Makefile</code>. It has been replaced by <code>test/run.d</code> and is only listed here for users who experience problems during the transition to <pre>run.d</pre><br />
<br />
== DMD Test Suite - Windows Requirements ==<br />
<br />
==== Linux Core Utilities (bash/grep/diff/etc.) ====<br />
<br />
If you have git installed (https://gitforwindows.org) you probably already have the linux core utilities available. Simply add them to your <code>PATH</code> with:<br />
<br />
<syntaxhighlight lang=dos><br />
set PATH=C:\Program Files\Git\bin;C:\Program Files\Git\usr\bin;%PATH%<br />
</syntaxhighlight><br />
<br />
Alternatively, you can have digger automatically install them for you (https://github.com/CyberShadow/Digger) or follow these instructions: https://github.com/golang/go/wiki/WindowsBuild#install-mingwmsys<br />
<br />
==== GNU make (different than DigitalMars make) ====<br />
<br />
Option 1: use <code>mingw32-make.exe</code> from a MinGW binary<br />
<br />
Option 2: download binaries from sourceforce<br />
* You can download a prebuilt binary and its dependencies from here: http://gnuwin32.sourceforge.net/packages/make.htm<br />
* Download the "Binaries" Zip package and the "Dependencies" Zip package.<br />
* Extract them and copy "libiconv2.dll" and "libintl3.dll" to the "bin" directory in the unzipped "Binaries" archive.<br />
* Add the bin directory of the unzipped "Binaries" archive to your <code>PATH</code><br />
<br />
Option 3: try the pre-built binaries from this PR: https://github.com/dlang/installer/pull/311<br />
<br />
'''Important:''' you need to use GNU <code>make</code> to run the <code>Makefile</code> in <code>test</code> - not the DigitalMars <code>make</code> that is bundled with D's Windows binaries. Run `which make` to see which one is being used. If it's the DigitalMars' <code>make</code>, you'll need to change the directory order in your <code>PATH</code> by placing the path to GNU's make first.<br />
DigitalMars make is only required for <code>win32.mak</code> and <code>win64.mak</code>.<br />
<br />
<br />
<br />
If you are looking for an automated way to turn a VirtualBox in a Development Machine, follow [https://gist.github.com/MartinNowak/8270666 these instructions] to create a ssh-accessible Windows box.<br />
<br />
=== Run all tests which haven't been run before ===<br />
<br />
<syntaxhighlight lang=bash><br />
make all -j8<br />
</syntaxhighlight><br />
<br />
If you you now rerun this command, the testsuite won't execute anything:<br />
<br />
<syntaxhighlight lang=bash><br />
make all -j8<br />
</syntaxhighlight><br />
<br />
However, if you modified the compiler, it will only rerun the failing tests as these don't have an output stored.<br />
<br />
=== Remove test states ===<br />
<br />
The test suite stores the results of run tests to allow re-running only the failed tests.<br />
This state is stored in `~/dlang/dmd/compiler/test/test_results` and can be removed with:<br />
<br />
<syntaxhighlight lang=bash><br />
make clean<br />
</syntaxhighlight><br />
<br />
=== Always run all tests ===<br />
<br />
<syntaxhighlight lang=bash><br />
make run_tests -j8<br />
</syntaxhighlight><br />
<br />
== Run an individual test ==<br />
<br />
Sometimes it can be helpful to rerun only a single test which tests the fix or feature one is working on:<br />
<br />
<syntaxhighlight lang=bash><br />
make test_results/compilable/test10066.d.out<br />
</syntaxhighlight><br />
<br />
If you want to force re-evaluation of a single test, simply remove the respective file:<br />
<br />
<syntaxhighlight lang=bash><br />
rm test_results/compilable/test10066.d.out<br />
make test_results/compilable/test10066.d.out<br />
</syntaxhighlight><br />
<br />
=== Run quick test ===<br />
<br />
Often one makes a small change and wants to quickly know whether this change completely broke the compiler.<br />
For this, the target <tt>make quick</tt> exists:<br />
<br />
<syntaxhighlight lang=bash><br />
make quick<br />
</syntaxhighlight><br />
<br />
=== Run group of tests ===<br />
<br />
Sometimes it can be useful to run only a subset of tests. The testsuite groups the test in three groups: <tt>runnable</tt>, <tt>compilable</tt> and <tt>failed_compilation</tt>.<br />
They can be run individually:<br />
<br />
<syntaxhighlight lang=bash><br />
make run_runnable_tests: # run just the runnable tests<br />
make run_compilable_tests: # run just the compilable tests<br />
make run_fail_compilation_tests # run just the fail compilation tests<br />
</syntaxhighlight><br />
<br />
<br />
<br />
[[Category:Contribution Guidelines]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Language_issues&diff=10113Language issues2022-09-22T12:20:41Z<p>NickTreleaven: /* Attribute creep */ Mention inference and split out method type constructors as they DON'T apply to return type!</p>
<hr />
<div>Like any programming language, D is not perfect. This page lists some potential problems that have been brought up and debated throughout the language's history. Fixing these is not straight-forward or may not justify breaking backwards-compatibility. As of the moment of writing this, there are no plans for a major revision of D which would allow such breaking changes, but this list may also be useful for other programming languages which wish to learn from D's experience.<br />
<br />
See also: [[Language design discussions]]<br />
<br />
== Properties ==<br />
<br />
Design of properties has been an oft-discussed topic. This language feature has evolved throughout D's history (e.g. the addition and removal of the <tt>-property</tt> switch). There are numerous [[DIPs]] with proposals on improving the design:<br />
<br />
* [[DIP4]]<br />
* [[DIP5]]<br />
* [[DIP6]]<br />
* [[DIP21]]<br />
* [[DIP23]]<br />
* [[DIP24]]<br />
* [[DIP26]]<br />
* [[DIP28]]<br />
<br />
See also:<br />
<br />
* [[Property Discussion Wrap-up]]<br />
* [[Language design discussions#Properties]]<br />
<br />
== Unicode and ranges ==<br />
<br />
D's ranges currently treat strings in a special way: they present them as a range of code points, thus implicitly performing UTF decoding. Algorithms that do not require working with decoded code points, and which would gain a performance advantage by treating the input as a range of code units (or an array of code units), must incorporate D strings as a special case. This approach complicates the implementation by some degree, and only solves a certain subset of problems for a subset of written languages.<br />
<br />
Walter Bright has mentioned that auto-decoding is his #1 thing he currently dislikes about D [[http://www.reddit.com/r/programming/comments/2a20h5/wired_magazine_discovers_d/ciqqlg5 1]] [[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com 2]].<br />
<br />
See also:<br />
<br />
* [[Element type of string ranges]]<br />
* [http://forum.dlang.org/post/lfbbcn$2th7$1@digitalmars.com March 2014 discussion]<br />
* [https://github.com/D-Programming-Language/phobos/pull/2423 Related discussion in pull request "add range version of setExtension"]<br />
* [http://jackstouffer.com/blog/d_auto_decoding_and_you.html D's Auto Decoding and You]<br />
* [http://forum.dlang.org/post/nh2o9i$hr0$1@digitalmars.com The Case against Autodecode] - NG discussion in May 2016<br />
<br />
=== std2 ===<br />
<br />
Auto-decoding will be removed in Phobos V2:<br />
https://forum.dlang.org/thread/sl7l32$1umj$1@digitalmars.com<br />
<br />
Phobos 2 would allow importing certain modules from V2 whilst continuing to use other V1 modules.<br />
<br />
== Attribute creep ==<br />
<br />
In a 2014 forum thread titled "[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com What are the worst parts of D?]", a prevalent complaint was the number of attributes that functions can be decorated with.<br />
<br />
D currently allows the following attributes:<br />
<br />
* [http://dlang.org/function.html#virtual-functions <tt>override</tt> / <tt>final</tt>] / [http://dlang.org/attribute.html#abstract <tt>abstract</tt>]<br />
* [http://dlang.org/attribute.html#linkage <tt>extern</tt>]<br />
* [http://dlang.org/function.html#property-functions <tt>@property</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
* [http://dlang.org/function.html#safe-functions <tt>@safe</tt>] / [http://dlang.org/function.html#trusted-functions <tt>@trusted</tt>] / [http://dlang.org/function.html#system-functions <tt>@system</tt>]<br />
* [http://dlang.org/function.html#pure-functions <tt>pure</tt>]<br />
* [http://dlang.org/function.html#nothrow-functions <tt>nothrow</tt>]<br />
* [http://dlang.org/attribute.html#nogc <tt>@nogc</tt>]<br />
* [http://dlang.org/attribute.html#disable <tt>@disable</tt>]<br />
* [http://dlang.org/attribute.html#deprecated <tt>deprecated</tt>]<br />
* [[DIP25 | <tt>return</tt>]]<br />
<br />
Note that attributes such as @nogc, nothrow, pure, @safe and scope can be inferred for template functions, function literals and auto-return functions.<br />
<br />
Additionally, function return types can be or be annotated with the following storage classes:<br />
<br />
* [http://dlang.org/function.html#auto-functions <tt>auto</tt>]<br />
* [http://dlang.org/function.html#ref-functions <tt>ref</tt>]<br />
<br />
Methods can be annotated with the following type constructors:<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
<br />
== Signed/unsigned comparisons ==<br />
<br />
Currently, the following code fails:<br />
<br />
<syntaxhighlight lang="d"><br />
uint i = 1;<br />
assert(i > -2);<br />
</syntaxhighlight><br />
<br />
<tt>i > -2</tt> evaluates to <tt>false</tt> due to C compatibility (the same expression also evaluates to <tt>false</tt> in C, and one of D's goals is that if any C code compiles in D, then it should act like in C). One proposal is to make signed/unsigned comparisons generate a warning.<br />
<br />
See [https://d.puremagic.com/issues/show_bug.cgi?id=259 issue 259] for discussion.<br />
<br />
== Null References ==<br />
Null references have often been blamed as a common class of bugs, which could be prevented statically by the compiler (e.g. as a <tt>NotNull</tt> modifier, or explicitly marking variables possibly containing null values). This can be done by statically checking if all code paths (e.g. all class constructors) initialize a reference variable to a non-null value.<br />
<br />
See also:<br />
<br />
* [http://forum.dlang.org/post/vgntbohxwfnglyiyxgmi@forum.dlang.org February 2014 discussion]<br />
* [http://forum.dlang.org/post/vhtcmmnihixpmaqtakmg@forum.dlang.org September 2012 discussion]<br />
* [http://d.puremagic.com/issues/show_bug.cgi?id=4595 Issue 4595 - <nowiki>[tdpl]</nowiki> Accessing non-static member of a null reference compiles]<br />
<br />
== Arrays in boolean context ==<br />
Dynamic array variables in boolean context (e.g. when encountered in an <code>if</code> condition by themselves) are considered equivalent to their <code>.ptr</code> property. It has been argued they should instead use their <code>.length</code> property, so that empty (but not null) arrays evaluate as <code>false</code>. See [https://issues.dlang.org/show_bug.cgi?id=4733 Issue 4733 - Possible bugs caused by dynamic arrays in boolean evaluation context] and related pull requests.<br />
<br />
== Virtual by default ==<br />
<br />
In D, methods are virtual by default. Although this approach does have benefits from the point of view of extensibility, it has been criticized that this default incurs a considerable performance impact and harms forward compatibility in user code, unless explicitly disabled everywhere as appropriate using the <tt>final</tt> keyword.<br />
<br />
Although at one point Walter Bright [http://forum.dlang.org/post/lfqoan$5qq$1@digitalmars.com intended] to change the default (see [https://d.puremagic.com/issues/show_bug.cgi?id=11616 Issue 11616] and [[DIP51]]), ultimately this proposal [http://forum.dlang.org/post/lfrdst$oav$1@digitalmars.com has been rejected].<br />
<br />
== Default constructors ==<br />
<br />
D does not support custom default constructors for value types: attempting to declare a <tt>struct</tt> constructor without any arguments is an error. The rationale for this limitation is to allow any type to have a known constant default value (<tt>.init</tt> property). This is unlike C++, where structs and classes can have default constructors, which allow executing custom code at the point of a variable's declaration.<br />
<br />
D's restriction prevents implementing certain C++ patterns, and requires users to rely on conventions for factory functions.<br />
<br />
=== Advantages of <tt>.init</tt> ===<br />
<br />
[http://forum.dlang.org/post/m18aku$2q7e$1@digitalmars.com According to Walter Bright], some advantages of <tt>.init</tt> over default constructors are:<br />
<br />
# the default object is trivially constructable and cannot fail (for nested struct <code>.init</code> contains null context pointer, use default constructor instead)<br />
# an easy way for other constructors to not have overlooked field initializers, so they get garbage initialized like in C++<br />
# generic code can rely on the existence of trivial construction that cannot fail<br />
# dummy objects can be created, useful for "does this compile" semantics<br />
# an object can be "destroyed" by overwriting it with .init (overwriting with 0 is not the same thing)<br />
# when you see: <tt>T t;</tt> in code, you know it is trivially constructed and will succeed<br />
# objects can be created using <tt>TypeInfo</tt><br />
<br />
Notes:<br />
* (4) can be done with a function literal: <tt>(T v) { ... }</tt>. This works even when T has <tt>@disable this</tt>.<br />
* (5) can be done with <tt>obj.move;</tt>.<br />
<br />
<br />
=== Explicit syntax and <tt>@disable this</tt> ===<br />
<br />
In theory, explicit struct construction syntax <tt>S s = S();</tt> could allow calling a zero-argument constructor (vs. just <tt>S s;</tt> which is default construction). Forgetting to use the explicit syntax can be solved by disabling the default constructor (<tt>@disable this;</tt>).<br />
<br />
See also:<br />
* [http://forum.dlang.org/post/li3n8n$7ci$1@digitalmars.com April 2014 discussion]<br />
* [http://forum.dlang.org/post/k8ti2b$1iqj$1@digitalmars.com November 2012 discussion] (note we do now support <tt>int(2)</tt> syntax)<br />
<br />
== Memory management ==<br />
<br />
D is often criticized for its usage of garbage collection, and the quality of the current GC implementation.<br />
<br />
The default GC implementation is:<br />
<br />
* conservative (meaning, it can't guarantee whether any object actually has live references to it)<br />
* non-moving (the GC doesn't attempt to compact the heap to reduce fragmentation and working set size)<br />
* stop-the-world (all threads are stopped during a GC scan)<br />
<br />
Note: The GC only runs when a GC memory allocation is made.<br />
<br />
Built-in alternatives:<br />
<br />
* Precise GC is available as an option: https://dlang.org/spec/garbage.html#precise_gc.<br />
* A concurrent <tt>fork</tt>-based GC is available on *nix systems: https://dlang.org/blog/2019/07/22/symmetry-autumn-of-code-experience-report-porting-a-fork-based-gc/.<br />
<br />
Although GC collections can [https://dlang.org/phobos/core_memory.html#.GC.disable easily be disabled, re-enabled and run manually], using D completely without the GC may be challenging, as some features of D make GC allocations:<br />
<br />
* Many modules in Phobos, D's standard library, expect a GC to be present to clean up temporary allocations;<br />
* D language features such as dynamic arrays require careful use to avoid memory leaks;<br />
* D language features such as closures and heap exceptions cannot be used, as they do not provide a way to manually deallocate allocated memory.<br />
<br />
Note that <tt>@nogc</tt> can be used to statically check no GC allocations are made: https://dlang.org/spec/function.html#nogc-functions.<br />
<br />
Some alternative runtimes / standard libraries which do not rely on the GC are listed [[Libraries_and_Frameworks#Alternative_standard_libraries_.2F_runtimes|here]].</div>NickTreleavenhttps://wiki.dlang.org/?title=Language_issues&diff=10112Language issues2022-09-22T12:12:45Z<p>NickTreleaven: /* Memory management */</p>
<hr />
<div>Like any programming language, D is not perfect. This page lists some potential problems that have been brought up and debated throughout the language's history. Fixing these is not straight-forward or may not justify breaking backwards-compatibility. As of the moment of writing this, there are no plans for a major revision of D which would allow such breaking changes, but this list may also be useful for other programming languages which wish to learn from D's experience.<br />
<br />
See also: [[Language design discussions]]<br />
<br />
== Properties ==<br />
<br />
Design of properties has been an oft-discussed topic. This language feature has evolved throughout D's history (e.g. the addition and removal of the <tt>-property</tt> switch). There are numerous [[DIPs]] with proposals on improving the design:<br />
<br />
* [[DIP4]]<br />
* [[DIP5]]<br />
* [[DIP6]]<br />
* [[DIP21]]<br />
* [[DIP23]]<br />
* [[DIP24]]<br />
* [[DIP26]]<br />
* [[DIP28]]<br />
<br />
See also:<br />
<br />
* [[Property Discussion Wrap-up]]<br />
* [[Language design discussions#Properties]]<br />
<br />
== Unicode and ranges ==<br />
<br />
D's ranges currently treat strings in a special way: they present them as a range of code points, thus implicitly performing UTF decoding. Algorithms that do not require working with decoded code points, and which would gain a performance advantage by treating the input as a range of code units (or an array of code units), must incorporate D strings as a special case. This approach complicates the implementation by some degree, and only solves a certain subset of problems for a subset of written languages.<br />
<br />
Walter Bright has mentioned that auto-decoding is his #1 thing he currently dislikes about D [[http://www.reddit.com/r/programming/comments/2a20h5/wired_magazine_discovers_d/ciqqlg5 1]] [[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com 2]].<br />
<br />
See also:<br />
<br />
* [[Element type of string ranges]]<br />
* [http://forum.dlang.org/post/lfbbcn$2th7$1@digitalmars.com March 2014 discussion]<br />
* [https://github.com/D-Programming-Language/phobos/pull/2423 Related discussion in pull request "add range version of setExtension"]<br />
* [http://jackstouffer.com/blog/d_auto_decoding_and_you.html D's Auto Decoding and You]<br />
* [http://forum.dlang.org/post/nh2o9i$hr0$1@digitalmars.com The Case against Autodecode] - NG discussion in May 2016<br />
<br />
=== std2 ===<br />
<br />
Auto-decoding will be removed in Phobos V2:<br />
https://forum.dlang.org/thread/sl7l32$1umj$1@digitalmars.com<br />
<br />
Phobos 2 would allow importing certain modules from V2 whilst continuing to use other V1 modules.<br />
<br />
== Attribute creep ==<br />
<br />
In a 2014 forum thread titled "[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com What are the worst parts of D?]", a prevalent complaint was the number of attributes that functions can be decorated with.<br />
<br />
D currently allows the following attributes:<br />
<br />
* [http://dlang.org/function.html#virtual-functions <tt>override</tt> / <tt>final</tt>] / [http://dlang.org/attribute.html#abstract <tt>abstract</tt>]<br />
* [http://dlang.org/attribute.html#linkage <tt>extern</tt>]<br />
* [http://dlang.org/function.html#property-functions <tt>@property</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
* [http://dlang.org/function.html#safe-functions <tt>@safe</tt>] / [http://dlang.org/function.html#trusted-functions <tt>@trusted</tt>] / [http://dlang.org/function.html#system-functions <tt>@system</tt>]<br />
* [http://dlang.org/function.html#pure-functions <tt>pure</tt>]<br />
* [http://dlang.org/function.html#nothrow-functions <tt>nothrow</tt>]<br />
* [http://dlang.org/attribute.html#nogc <tt>@nogc</tt>]<br />
* [http://dlang.org/attribute.html#disable <tt>@disable</tt>]<br />
* [http://dlang.org/attribute.html#deprecated <tt>deprecated</tt>]<br />
* [[DIP25 | <tt>return</tt>]]<br />
<br />
Additionally, function return types can be or be annotated with the following keywords:<br />
<br />
* [http://dlang.org/function.html#auto-functions <tt>auto</tt>]<br />
* [http://dlang.org/function.html#ref-functions <tt>ref</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
<br />
== Signed/unsigned comparisons ==<br />
<br />
Currently, the following code fails:<br />
<br />
<syntaxhighlight lang="d"><br />
uint i = 1;<br />
assert(i > -2);<br />
</syntaxhighlight><br />
<br />
<tt>i > -2</tt> evaluates to <tt>false</tt> due to C compatibility (the same expression also evaluates to <tt>false</tt> in C, and one of D's goals is that if any C code compiles in D, then it should act like in C). One proposal is to make signed/unsigned comparisons generate a warning.<br />
<br />
See [https://d.puremagic.com/issues/show_bug.cgi?id=259 issue 259] for discussion.<br />
<br />
== Null References ==<br />
Null references have often been blamed as a common class of bugs, which could be prevented statically by the compiler (e.g. as a <tt>NotNull</tt> modifier, or explicitly marking variables possibly containing null values). This can be done by statically checking if all code paths (e.g. all class constructors) initialize a reference variable to a non-null value.<br />
<br />
See also:<br />
<br />
* [http://forum.dlang.org/post/vgntbohxwfnglyiyxgmi@forum.dlang.org February 2014 discussion]<br />
* [http://forum.dlang.org/post/vhtcmmnihixpmaqtakmg@forum.dlang.org September 2012 discussion]<br />
* [http://d.puremagic.com/issues/show_bug.cgi?id=4595 Issue 4595 - <nowiki>[tdpl]</nowiki> Accessing non-static member of a null reference compiles]<br />
<br />
== Arrays in boolean context ==<br />
Dynamic array variables in boolean context (e.g. when encountered in an <code>if</code> condition by themselves) are considered equivalent to their <code>.ptr</code> property. It has been argued they should instead use their <code>.length</code> property, so that empty (but not null) arrays evaluate as <code>false</code>. See [https://issues.dlang.org/show_bug.cgi?id=4733 Issue 4733 - Possible bugs caused by dynamic arrays in boolean evaluation context] and related pull requests.<br />
<br />
== Virtual by default ==<br />
<br />
In D, methods are virtual by default. Although this approach does have benefits from the point of view of extensibility, it has been criticized that this default incurs a considerable performance impact and harms forward compatibility in user code, unless explicitly disabled everywhere as appropriate using the <tt>final</tt> keyword.<br />
<br />
Although at one point Walter Bright [http://forum.dlang.org/post/lfqoan$5qq$1@digitalmars.com intended] to change the default (see [https://d.puremagic.com/issues/show_bug.cgi?id=11616 Issue 11616] and [[DIP51]]), ultimately this proposal [http://forum.dlang.org/post/lfrdst$oav$1@digitalmars.com has been rejected].<br />
<br />
== Default constructors ==<br />
<br />
D does not support custom default constructors for value types: attempting to declare a <tt>struct</tt> constructor without any arguments is an error. The rationale for this limitation is to allow any type to have a known constant default value (<tt>.init</tt> property). This is unlike C++, where structs and classes can have default constructors, which allow executing custom code at the point of a variable's declaration.<br />
<br />
D's restriction prevents implementing certain C++ patterns, and requires users to rely on conventions for factory functions.<br />
<br />
=== Advantages of <tt>.init</tt> ===<br />
<br />
[http://forum.dlang.org/post/m18aku$2q7e$1@digitalmars.com According to Walter Bright], some advantages of <tt>.init</tt> over default constructors are:<br />
<br />
# the default object is trivially constructable and cannot fail (for nested struct <code>.init</code> contains null context pointer, use default constructor instead)<br />
# an easy way for other constructors to not have overlooked field initializers, so they get garbage initialized like in C++<br />
# generic code can rely on the existence of trivial construction that cannot fail<br />
# dummy objects can be created, useful for "does this compile" semantics<br />
# an object can be "destroyed" by overwriting it with .init (overwriting with 0 is not the same thing)<br />
# when you see: <tt>T t;</tt> in code, you know it is trivially constructed and will succeed<br />
# objects can be created using <tt>TypeInfo</tt><br />
<br />
Notes:<br />
* (4) can be done with a function literal: <tt>(T v) { ... }</tt>. This works even when T has <tt>@disable this</tt>.<br />
* (5) can be done with <tt>obj.move;</tt>.<br />
<br />
<br />
=== Explicit syntax and <tt>@disable this</tt> ===<br />
<br />
In theory, explicit struct construction syntax <tt>S s = S();</tt> could allow calling a zero-argument constructor (vs. just <tt>S s;</tt> which is default construction). Forgetting to use the explicit syntax can be solved by disabling the default constructor (<tt>@disable this;</tt>).<br />
<br />
See also:<br />
* [http://forum.dlang.org/post/li3n8n$7ci$1@digitalmars.com April 2014 discussion]<br />
* [http://forum.dlang.org/post/k8ti2b$1iqj$1@digitalmars.com November 2012 discussion] (note we do now support <tt>int(2)</tt> syntax)<br />
<br />
== Memory management ==<br />
<br />
D is often criticized for its usage of garbage collection, and the quality of the current GC implementation.<br />
<br />
The default GC implementation is:<br />
<br />
* conservative (meaning, it can't guarantee whether any object actually has live references to it)<br />
* non-moving (the GC doesn't attempt to compact the heap to reduce fragmentation and working set size)<br />
* stop-the-world (all threads are stopped during a GC scan)<br />
<br />
Note: The GC only runs when a GC memory allocation is made.<br />
<br />
Built-in alternatives:<br />
<br />
* Precise GC is available as an option: https://dlang.org/spec/garbage.html#precise_gc.<br />
* A concurrent <tt>fork</tt>-based GC is available on *nix systems: https://dlang.org/blog/2019/07/22/symmetry-autumn-of-code-experience-report-porting-a-fork-based-gc/.<br />
<br />
Although GC collections can [https://dlang.org/phobos/core_memory.html#.GC.disable easily be disabled, re-enabled and run manually], using D completely without the GC may be challenging, as some features of D make GC allocations:<br />
<br />
* Many modules in Phobos, D's standard library, expect a GC to be present to clean up temporary allocations;<br />
* D language features such as dynamic arrays require careful use to avoid memory leaks;<br />
* D language features such as closures and heap exceptions cannot be used, as they do not provide a way to manually deallocate allocated memory.<br />
<br />
Note that <tt>@nogc</tt> can be used to statically check no GC allocations are made: https://dlang.org/spec/function.html#nogc-functions.<br />
<br />
Some alternative runtimes / standard libraries which do not rely on the GC are listed [[Libraries_and_Frameworks#Alternative_standard_libraries_.2F_runtimes|here]].</div>NickTreleavenhttps://wiki.dlang.org/?title=Language_issues&diff=10111Language issues2022-09-22T11:52:09Z<p>NickTreleaven: /* Unicode and ranges */ auto-decoding removal for Phobos 2</p>
<hr />
<div>Like any programming language, D is not perfect. This page lists some potential problems that have been brought up and debated throughout the language's history. Fixing these is not straight-forward or may not justify breaking backwards-compatibility. As of the moment of writing this, there are no plans for a major revision of D which would allow such breaking changes, but this list may also be useful for other programming languages which wish to learn from D's experience.<br />
<br />
See also: [[Language design discussions]]<br />
<br />
== Properties ==<br />
<br />
Design of properties has been an oft-discussed topic. This language feature has evolved throughout D's history (e.g. the addition and removal of the <tt>-property</tt> switch). There are numerous [[DIPs]] with proposals on improving the design:<br />
<br />
* [[DIP4]]<br />
* [[DIP5]]<br />
* [[DIP6]]<br />
* [[DIP21]]<br />
* [[DIP23]]<br />
* [[DIP24]]<br />
* [[DIP26]]<br />
* [[DIP28]]<br />
<br />
See also:<br />
<br />
* [[Property Discussion Wrap-up]]<br />
* [[Language design discussions#Properties]]<br />
<br />
== Unicode and ranges ==<br />
<br />
D's ranges currently treat strings in a special way: they present them as a range of code points, thus implicitly performing UTF decoding. Algorithms that do not require working with decoded code points, and which would gain a performance advantage by treating the input as a range of code units (or an array of code units), must incorporate D strings as a special case. This approach complicates the implementation by some degree, and only solves a certain subset of problems for a subset of written languages.<br />
<br />
Walter Bright has mentioned that auto-decoding is his #1 thing he currently dislikes about D [[http://www.reddit.com/r/programming/comments/2a20h5/wired_magazine_discovers_d/ciqqlg5 1]] [[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com 2]].<br />
<br />
See also:<br />
<br />
* [[Element type of string ranges]]<br />
* [http://forum.dlang.org/post/lfbbcn$2th7$1@digitalmars.com March 2014 discussion]<br />
* [https://github.com/D-Programming-Language/phobos/pull/2423 Related discussion in pull request "add range version of setExtension"]<br />
* [http://jackstouffer.com/blog/d_auto_decoding_and_you.html D's Auto Decoding and You]<br />
* [http://forum.dlang.org/post/nh2o9i$hr0$1@digitalmars.com The Case against Autodecode] - NG discussion in May 2016<br />
<br />
=== std2 ===<br />
<br />
Auto-decoding will be removed in Phobos V2:<br />
https://forum.dlang.org/thread/sl7l32$1umj$1@digitalmars.com<br />
<br />
Phobos 2 would allow importing certain modules from V2 whilst continuing to use other V1 modules.<br />
<br />
== Attribute creep ==<br />
<br />
In a 2014 forum thread titled "[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com What are the worst parts of D?]", a prevalent complaint was the number of attributes that functions can be decorated with.<br />
<br />
D currently allows the following attributes:<br />
<br />
* [http://dlang.org/function.html#virtual-functions <tt>override</tt> / <tt>final</tt>] / [http://dlang.org/attribute.html#abstract <tt>abstract</tt>]<br />
* [http://dlang.org/attribute.html#linkage <tt>extern</tt>]<br />
* [http://dlang.org/function.html#property-functions <tt>@property</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
* [http://dlang.org/function.html#safe-functions <tt>@safe</tt>] / [http://dlang.org/function.html#trusted-functions <tt>@trusted</tt>] / [http://dlang.org/function.html#system-functions <tt>@system</tt>]<br />
* [http://dlang.org/function.html#pure-functions <tt>pure</tt>]<br />
* [http://dlang.org/function.html#nothrow-functions <tt>nothrow</tt>]<br />
* [http://dlang.org/attribute.html#nogc <tt>@nogc</tt>]<br />
* [http://dlang.org/attribute.html#disable <tt>@disable</tt>]<br />
* [http://dlang.org/attribute.html#deprecated <tt>deprecated</tt>]<br />
* [[DIP25 | <tt>return</tt>]]<br />
<br />
Additionally, function return types can be or be annotated with the following keywords:<br />
<br />
* [http://dlang.org/function.html#auto-functions <tt>auto</tt>]<br />
* [http://dlang.org/function.html#ref-functions <tt>ref</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
<br />
== Signed/unsigned comparisons ==<br />
<br />
Currently, the following code fails:<br />
<br />
<syntaxhighlight lang="d"><br />
uint i = 1;<br />
assert(i > -2);<br />
</syntaxhighlight><br />
<br />
<tt>i > -2</tt> evaluates to <tt>false</tt> due to C compatibility (the same expression also evaluates to <tt>false</tt> in C, and one of D's goals is that if any C code compiles in D, then it should act like in C). One proposal is to make signed/unsigned comparisons generate a warning.<br />
<br />
See [https://d.puremagic.com/issues/show_bug.cgi?id=259 issue 259] for discussion.<br />
<br />
== Null References ==<br />
Null references have often been blamed as a common class of bugs, which could be prevented statically by the compiler (e.g. as a <tt>NotNull</tt> modifier, or explicitly marking variables possibly containing null values). This can be done by statically checking if all code paths (e.g. all class constructors) initialize a reference variable to a non-null value.<br />
<br />
See also:<br />
<br />
* [http://forum.dlang.org/post/vgntbohxwfnglyiyxgmi@forum.dlang.org February 2014 discussion]<br />
* [http://forum.dlang.org/post/vhtcmmnihixpmaqtakmg@forum.dlang.org September 2012 discussion]<br />
* [http://d.puremagic.com/issues/show_bug.cgi?id=4595 Issue 4595 - <nowiki>[tdpl]</nowiki> Accessing non-static member of a null reference compiles]<br />
<br />
== Arrays in boolean context ==<br />
Dynamic array variables in boolean context (e.g. when encountered in an <code>if</code> condition by themselves) are considered equivalent to their <code>.ptr</code> property. It has been argued they should instead use their <code>.length</code> property, so that empty (but not null) arrays evaluate as <code>false</code>. See [https://issues.dlang.org/show_bug.cgi?id=4733 Issue 4733 - Possible bugs caused by dynamic arrays in boolean evaluation context] and related pull requests.<br />
<br />
== Virtual by default ==<br />
<br />
In D, methods are virtual by default. Although this approach does have benefits from the point of view of extensibility, it has been criticized that this default incurs a considerable performance impact and harms forward compatibility in user code, unless explicitly disabled everywhere as appropriate using the <tt>final</tt> keyword.<br />
<br />
Although at one point Walter Bright [http://forum.dlang.org/post/lfqoan$5qq$1@digitalmars.com intended] to change the default (see [https://d.puremagic.com/issues/show_bug.cgi?id=11616 Issue 11616] and [[DIP51]]), ultimately this proposal [http://forum.dlang.org/post/lfrdst$oav$1@digitalmars.com has been rejected].<br />
<br />
== Default constructors ==<br />
<br />
D does not support custom default constructors for value types: attempting to declare a <tt>struct</tt> constructor without any arguments is an error. The rationale for this limitation is to allow any type to have a known constant default value (<tt>.init</tt> property). This is unlike C++, where structs and classes can have default constructors, which allow executing custom code at the point of a variable's declaration.<br />
<br />
D's restriction prevents implementing certain C++ patterns, and requires users to rely on conventions for factory functions.<br />
<br />
=== Advantages of <tt>.init</tt> ===<br />
<br />
[http://forum.dlang.org/post/m18aku$2q7e$1@digitalmars.com According to Walter Bright], some advantages of <tt>.init</tt> over default constructors are:<br />
<br />
# the default object is trivially constructable and cannot fail (for nested struct <code>.init</code> contains null context pointer, use default constructor instead)<br />
# an easy way for other constructors to not have overlooked field initializers, so they get garbage initialized like in C++<br />
# generic code can rely on the existence of trivial construction that cannot fail<br />
# dummy objects can be created, useful for "does this compile" semantics<br />
# an object can be "destroyed" by overwriting it with .init (overwriting with 0 is not the same thing)<br />
# when you see: <tt>T t;</tt> in code, you know it is trivially constructed and will succeed<br />
# objects can be created using <tt>TypeInfo</tt><br />
<br />
Notes:<br />
* (4) can be done with a function literal: <tt>(T v) { ... }</tt>. This works even when T has <tt>@disable this</tt>.<br />
* (5) can be done with <tt>obj.move;</tt>.<br />
<br />
<br />
=== Explicit syntax and <tt>@disable this</tt> ===<br />
<br />
In theory, explicit struct construction syntax <tt>S s = S();</tt> could allow calling a zero-argument constructor (vs. just <tt>S s;</tt> which is default construction). Forgetting to use the explicit syntax can be solved by disabling the default constructor (<tt>@disable this;</tt>).<br />
<br />
See also:<br />
* [http://forum.dlang.org/post/li3n8n$7ci$1@digitalmars.com April 2014 discussion]<br />
* [http://forum.dlang.org/post/k8ti2b$1iqj$1@digitalmars.com November 2012 discussion] (note we do now support <tt>int(2)</tt> syntax)<br />
<br />
== Memory management ==<br />
<br />
D is often criticized for its reliance on a garbage collector, and the quality of the current GC implementation.<br />
<br />
The current GC implementation is:<br />
<br />
* conservative (meaning, it can't guarantee whether any object actually has live references to it)<br />
* non-moving (the GC doesn't attempt to compact the heap to reduce fragmentation and working set size)<br />
* stop-the-world (all threads are stopped during a GC scan)<br />
<br />
Precise (as far as the heap is concerned) and concurrent D GC implementations have been presented:<br />
* [http://dconf.org/2013/talks/schuetze.html A Precise Garbage Collector for D] (DConf 2013 talk by Rainer Schütze)<br />
* [http://dconf.org/2013/talks/lucarella.html Concurrent Garbage Collection for D] (DConf 2013 talk by Leandro Lucarella)<br />
<br />
Although the GC can be disabled, using D completely without the GC may be challenging, as some parts of D expect a GC to be available:<br />
<br />
* Many modules in Phobos, D's standard library, expect a GC to be present to clean up temporary allocations;<br />
* D language features such as arrays require careful use to avoid memory leaks;<br />
* D language features such as closures and exceptions cannot be used, as they do not provide a way to manually deallocate allocated memory.<br />
<br />
Some alternative runtimes / standard libraries which do not rely on the GC are listed [[Libraries_and_Frameworks#Alternative_standard_libraries_.2F_runtimes|here]].</div>NickTreleavenhttps://wiki.dlang.org/?title=Language_issues&diff=10110Language issues2022-09-22T11:44:28Z<p>NickTreleaven: Rebut 2 points for T.init</p>
<hr />
<div>Like any programming language, D is not perfect. This page lists some potential problems that have been brought up and debated throughout the language's history. Fixing these is not straight-forward or may not justify breaking backwards-compatibility. As of the moment of writing this, there are no plans for a major revision of D which would allow such breaking changes, but this list may also be useful for other programming languages which wish to learn from D's experience.<br />
<br />
See also: [[Language design discussions]]<br />
<br />
== Properties ==<br />
<br />
Design of properties has been an oft-discussed topic. This language feature has evolved throughout D's history (e.g. the addition and removal of the <tt>-property</tt> switch). There are numerous [[DIPs]] with proposals on improving the design:<br />
<br />
* [[DIP4]]<br />
* [[DIP5]]<br />
* [[DIP6]]<br />
* [[DIP21]]<br />
* [[DIP23]]<br />
* [[DIP24]]<br />
* [[DIP26]]<br />
* [[DIP28]]<br />
<br />
See also:<br />
<br />
* [[Property Discussion Wrap-up]]<br />
* [[Language design discussions#Properties]]<br />
<br />
== Unicode and ranges ==<br />
<br />
D's ranges currently treat strings in a special way: they present them as a range of code points, thus implicitly performing UTF decoding. Algorithms that do not require working with decoded code points, and which would gain a performance advantage by treating the input as a range of code units (or an array of code units), must incorporate D strings as a special case. This approach complicates the implementation by some degree, and only solves a certain subset of problems for a subset of written languages.<br />
<br />
Walter Bright has mentioned that auto-decoding is his #1 thing he currently dislikes about D [[http://www.reddit.com/r/programming/comments/2a20h5/wired_magazine_discovers_d/ciqqlg5 1]] [[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com 2]].<br />
<br />
See also:<br />
<br />
* [[Element type of string ranges]]<br />
* [http://forum.dlang.org/post/lfbbcn$2th7$1@digitalmars.com March 2014 discussion]<br />
* [https://github.com/D-Programming-Language/phobos/pull/2423 Related discussion in pull request "add range version of setExtension"]<br />
* [http://jackstouffer.com/blog/d_auto_decoding_and_you.html D's Auto Decoding and You]<br />
* [http://forum.dlang.org/post/nh2o9i$hr0$1@digitalmars.com The Case against Autodecode] - NG discussion in May 2016<br />
<br />
== Attribute creep ==<br />
<br />
In a 2014 forum thread titled "[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com What are the worst parts of D?]", a prevalent complaint was the number of attributes that functions can be decorated with.<br />
<br />
D currently allows the following attributes:<br />
<br />
* [http://dlang.org/function.html#virtual-functions <tt>override</tt> / <tt>final</tt>] / [http://dlang.org/attribute.html#abstract <tt>abstract</tt>]<br />
* [http://dlang.org/attribute.html#linkage <tt>extern</tt>]<br />
* [http://dlang.org/function.html#property-functions <tt>@property</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
* [http://dlang.org/function.html#safe-functions <tt>@safe</tt>] / [http://dlang.org/function.html#trusted-functions <tt>@trusted</tt>] / [http://dlang.org/function.html#system-functions <tt>@system</tt>]<br />
* [http://dlang.org/function.html#pure-functions <tt>pure</tt>]<br />
* [http://dlang.org/function.html#nothrow-functions <tt>nothrow</tt>]<br />
* [http://dlang.org/attribute.html#nogc <tt>@nogc</tt>]<br />
* [http://dlang.org/attribute.html#disable <tt>@disable</tt>]<br />
* [http://dlang.org/attribute.html#deprecated <tt>deprecated</tt>]<br />
* [[DIP25 | <tt>return</tt>]]<br />
<br />
Additionally, function return types can be or be annotated with the following keywords:<br />
<br />
* [http://dlang.org/function.html#auto-functions <tt>auto</tt>]<br />
* [http://dlang.org/function.html#ref-functions <tt>ref</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
<br />
== Signed/unsigned comparisons ==<br />
<br />
Currently, the following code fails:<br />
<br />
<syntaxhighlight lang="d"><br />
uint i = 1;<br />
assert(i > -2);<br />
</syntaxhighlight><br />
<br />
<tt>i > -2</tt> evaluates to <tt>false</tt> due to C compatibility (the same expression also evaluates to <tt>false</tt> in C, and one of D's goals is that if any C code compiles in D, then it should act like in C). One proposal is to make signed/unsigned comparisons generate a warning.<br />
<br />
See [https://d.puremagic.com/issues/show_bug.cgi?id=259 issue 259] for discussion.<br />
<br />
== Null References ==<br />
Null references have often been blamed as a common class of bugs, which could be prevented statically by the compiler (e.g. as a <tt>NotNull</tt> modifier, or explicitly marking variables possibly containing null values). This can be done by statically checking if all code paths (e.g. all class constructors) initialize a reference variable to a non-null value.<br />
<br />
See also:<br />
<br />
* [http://forum.dlang.org/post/vgntbohxwfnglyiyxgmi@forum.dlang.org February 2014 discussion]<br />
* [http://forum.dlang.org/post/vhtcmmnihixpmaqtakmg@forum.dlang.org September 2012 discussion]<br />
* [http://d.puremagic.com/issues/show_bug.cgi?id=4595 Issue 4595 - <nowiki>[tdpl]</nowiki> Accessing non-static member of a null reference compiles]<br />
<br />
== Arrays in boolean context ==<br />
Dynamic array variables in boolean context (e.g. when encountered in an <code>if</code> condition by themselves) are considered equivalent to their <code>.ptr</code> property. It has been argued they should instead use their <code>.length</code> property, so that empty (but not null) arrays evaluate as <code>false</code>. See [https://issues.dlang.org/show_bug.cgi?id=4733 Issue 4733 - Possible bugs caused by dynamic arrays in boolean evaluation context] and related pull requests.<br />
<br />
== Virtual by default ==<br />
<br />
In D, methods are virtual by default. Although this approach does have benefits from the point of view of extensibility, it has been criticized that this default incurs a considerable performance impact and harms forward compatibility in user code, unless explicitly disabled everywhere as appropriate using the <tt>final</tt> keyword.<br />
<br />
Although at one point Walter Bright [http://forum.dlang.org/post/lfqoan$5qq$1@digitalmars.com intended] to change the default (see [https://d.puremagic.com/issues/show_bug.cgi?id=11616 Issue 11616] and [[DIP51]]), ultimately this proposal [http://forum.dlang.org/post/lfrdst$oav$1@digitalmars.com has been rejected].<br />
<br />
== Default constructors ==<br />
<br />
D does not support custom default constructors for value types: attempting to declare a <tt>struct</tt> constructor without any arguments is an error. The rationale for this limitation is to allow any type to have a known constant default value (<tt>.init</tt> property). This is unlike C++, where structs and classes can have default constructors, which allow executing custom code at the point of a variable's declaration.<br />
<br />
D's restriction prevents implementing certain C++ patterns, and requires users to rely on conventions for factory functions.<br />
<br />
=== Advantages of <tt>.init</tt> ===<br />
<br />
[http://forum.dlang.org/post/m18aku$2q7e$1@digitalmars.com According to Walter Bright], some advantages of <tt>.init</tt> over default constructors are:<br />
<br />
# the default object is trivially constructable and cannot fail (for nested struct <code>.init</code> contains null context pointer, use default constructor instead)<br />
# an easy way for other constructors to not have overlooked field initializers, so they get garbage initialized like in C++<br />
# generic code can rely on the existence of trivial construction that cannot fail<br />
# dummy objects can be created, useful for "does this compile" semantics<br />
# an object can be "destroyed" by overwriting it with .init (overwriting with 0 is not the same thing)<br />
# when you see: <tt>T t;</tt> in code, you know it is trivially constructed and will succeed<br />
# objects can be created using <tt>TypeInfo</tt><br />
<br />
Notes:<br />
* (4) can be done with a function literal: <tt>(T v) { ... }</tt>. This works even when T has <tt>@disable this</tt>.<br />
* (5) can be done with <tt>obj.move;</tt>.<br />
<br />
<br />
=== Explicit syntax and <tt>@disable this</tt> ===<br />
<br />
In theory, explicit struct construction syntax <tt>S s = S();</tt> could allow calling a zero-argument constructor (vs. just <tt>S s;</tt> which is default construction). Forgetting to use the explicit syntax can be solved by disabling the default constructor (<tt>@disable this;</tt>).<br />
<br />
See also:<br />
* [http://forum.dlang.org/post/li3n8n$7ci$1@digitalmars.com April 2014 discussion]<br />
* [http://forum.dlang.org/post/k8ti2b$1iqj$1@digitalmars.com November 2012 discussion] (note we do now support <tt>int(2)</tt> syntax)<br />
<br />
== Memory management ==<br />
<br />
D is often criticized for its reliance on a garbage collector, and the quality of the current GC implementation.<br />
<br />
The current GC implementation is:<br />
<br />
* conservative (meaning, it can't guarantee whether any object actually has live references to it)<br />
* non-moving (the GC doesn't attempt to compact the heap to reduce fragmentation and working set size)<br />
* stop-the-world (all threads are stopped during a GC scan)<br />
<br />
Precise (as far as the heap is concerned) and concurrent D GC implementations have been presented:<br />
* [http://dconf.org/2013/talks/schuetze.html A Precise Garbage Collector for D] (DConf 2013 talk by Rainer Schütze)<br />
* [http://dconf.org/2013/talks/lucarella.html Concurrent Garbage Collection for D] (DConf 2013 talk by Leandro Lucarella)<br />
<br />
Although the GC can be disabled, using D completely without the GC may be challenging, as some parts of D expect a GC to be available:<br />
<br />
* Many modules in Phobos, D's standard library, expect a GC to be present to clean up temporary allocations;<br />
* D language features such as arrays require careful use to avoid memory leaks;<br />
* D language features such as closures and exceptions cannot be used, as they do not provide a way to manually deallocate allocated memory.<br />
<br />
Some alternative runtimes / standard libraries which do not rely on the GC are listed [[Libraries_and_Frameworks#Alternative_standard_libraries_.2F_runtimes|here]].</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=8789Differences With TDPL2017-12-21T16:08:45Z<p>NickTreleaven: /* New Alias Syntax, Alias Templates */ enum templates</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias & Enum Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP42.md<br />
<br />
=== Attribute Inference for Templates and Function Literals ===<br />
http://dlang.org/function.html#function-attribute-inference<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
For example code, see:<br />
http://forum.dlang.org/post/mfjmysleuwfohoxcslpf@forum.dlang.org<br />
<br />
=== DIP25 - return ref ===<br />
https://dlang.org/spec/function.html#return-ref-parameters<br />
<br />
=== DIP60 - @nogc function attribute ===<br />
https://wiki.dlang.org/DIP60<br />
<br />
=== DIP1000 - scoped pointers ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md#fundamentals-of-scope<br />
<br />
=== DIP1010 - static foreach ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1010.md<br />
<br />
== Unimplemented / Incomplete Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Synchronized Classes ===<br />
<br />
For the most part, synchronized for classes currently acts like it does in Java with synchronized being on functions. The compiler does complain about having public members if a class is marked as synchronized, but none of the stuff like automatically stripping off the outer layer of shared in member functions is implemented, and the compiler allows you to put synchronized on individual functions without putting it on the class, which TDPL explicitly says is disallowed.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet. In particular, shared has no implicit memory barriers, and it's not clear that it ever will (they're not cheap). shared is usable as-is via atomic operations (as described in TDPL) or locking mutexes (be it explicit or via synchronized), but without synchronized classes, using shared typically requires temporarily, explicitly casting shared away after protecting the object with a lock so that it can be operated on as if it were thread-local while protected by the lock.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=8788Differences With TDPL2017-12-21T16:04:03Z<p>NickTreleaven: /* New Features */ static foreach</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
<br />
=== Attribute Inference for Templates and Function Literals ===<br />
http://dlang.org/function.html#function-attribute-inference<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
For example code, see:<br />
http://forum.dlang.org/post/mfjmysleuwfohoxcslpf@forum.dlang.org<br />
<br />
=== DIP25 - return ref ===<br />
https://dlang.org/spec/function.html#return-ref-parameters<br />
<br />
=== DIP60 - @nogc function attribute ===<br />
https://wiki.dlang.org/DIP60<br />
<br />
=== DIP1000 - scoped pointers ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md#fundamentals-of-scope<br />
<br />
=== DIP1010 - static foreach ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1010.md<br />
<br />
== Unimplemented / Incomplete Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Synchronized Classes ===<br />
<br />
For the most part, synchronized for classes currently acts like it does in Java with synchronized being on functions. The compiler does complain about having public members if a class is marked as synchronized, but none of the stuff like automatically stripping off the outer layer of shared in member functions is implemented, and the compiler allows you to put synchronized on individual functions without putting it on the class, which TDPL explicitly says is disallowed.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet. In particular, shared has no implicit memory barriers, and it's not clear that it ever will (they're not cheap). shared is usable as-is via atomic operations (as described in TDPL) or locking mutexes (be it explicit or via synchronized), but without synchronized classes, using shared typically requires temporarily, explicitly casting shared away after protecting the object with a lock so that it can be operated on as if it were thread-local while protected by the lock.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=8787Differences With TDPL2017-12-21T16:01:55Z<p>NickTreleaven: /* New Features */ @nogc attribute</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
<br />
=== Attribute Inference for Templates and Function Literals ===<br />
http://dlang.org/function.html#function-attribute-inference<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
For example code, see:<br />
http://forum.dlang.org/post/mfjmysleuwfohoxcslpf@forum.dlang.org<br />
<br />
=== DIP25 - return ref ===<br />
https://dlang.org/spec/function.html#return-ref-parameters<br />
<br />
=== DIP60 - @nogc function attribute ===<br />
https://wiki.dlang.org/DIP60<br />
<br />
=== DIP1000 - scoped pointers ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md#fundamentals-of-scope<br />
<br />
== Unimplemented / Incomplete Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Synchronized Classes ===<br />
<br />
For the most part, synchronized for classes currently acts like it does in Java with synchronized being on functions. The compiler does complain about having public members if a class is marked as synchronized, but none of the stuff like automatically stripping off the outer layer of shared in member functions is implemented, and the compiler allows you to put synchronized on individual functions without putting it on the class, which TDPL explicitly says is disallowed.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet. In particular, shared has no implicit memory barriers, and it's not clear that it ever will (they're not cheap). shared is usable as-is via atomic operations (as described in TDPL) or locking mutexes (be it explicit or via synchronized), but without synchronized classes, using shared typically requires temporarily, explicitly casting shared away after protecting the object with a lock so that it can be operated on as if it were thread-local while protected by the lock.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=8674Differences With TDPL2017-11-29T18:18:22Z<p>NickTreleaven: Remove SafeD - this is pretty much implemented</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
<br />
=== Attribute Inference for Templates and Function Literals ===<br />
http://dlang.org/function.html#function-attribute-inference<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
For example code, see:<br />
http://forum.dlang.org/post/mfjmysleuwfohoxcslpf@forum.dlang.org<br />
<br />
=== DIP25 - return ref ===<br />
https://dlang.org/spec/function.html#return-ref-parameters<br />
<br />
=== DIP1000 - scoped pointers ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md#fundamentals-of-scope<br />
<br />
== Unimplemented Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=8673Differences With TDPL2017-11-29T18:16:42Z<p>NickTreleaven: Add DIP25 and DIP1000</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
<br />
=== Attribute Inference for Templates and Function Literals ===<br />
http://dlang.org/function.html#function-attribute-inference<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
For example code, see:<br />
http://forum.dlang.org/post/mfjmysleuwfohoxcslpf@forum.dlang.org<br />
<br />
=== DIP25 - return ref ===<br />
https://dlang.org/spec/function.html#return-ref-parameters<br />
<br />
=== DIP1000 - scoped pointers ===<br />
https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md#fundamentals-of-scope<br />
<br />
== Unimplemented Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet.<br />
<br />
=== SafeD ===<br />
<br />
@safe (and therefore SafeD) isn't fully implemented. So, it doesn't <br />
necessarily work quite like it's supposed to yet.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Talk:DIP90&diff=7690Talk:DIP902016-07-04T11:38:19Z<p>NickTreleaven: List some typos to fix</p>
<hr />
<div>* Typo under 'Fundamentals of scope':<br />
<br />
The scope storage class ensures that the lifetime of a pointer/reference ''is a shorter of the'' lifetime of the referred object => ''is shorter than the''<br />
<br />
* Missing Rule 5 referenced:<br />
<br />
scope int* a;<br />
int* b;<br />
scope int* c = a; // Error, rule 5<br />
<br />
I think this is now part of Rule 1.<br />
<br />
* Under 'Escaping via Return', 5th & 6th code blocks:<br />
<br />
T func(T* t) {<br />
return t; // ok<br />
}<br />
<br />
Return type should be T*.<br />
<br />
T* foo() {<br />
T* t;<br />
return func(&t); // currently, no error detected, despite returning pointer to t<br />
}<br />
<br />
t should be declared T t.<br />
--[[User:NickTreleaven|NickTreleaven]] ([[User talk:NickTreleaven|talk]]) 11:38, 4 July 2016 (UTC)</div>NickTreleavenhttps://wiki.dlang.org/?title=Language_Designs_Explained&diff=7595Language Designs Explained2016-06-08T10:09:37Z<p>NickTreleaven: Fix typo</p>
<hr />
<div><br />
== Function attributes ==<br />
<br />
=== Why do some function attributes have an '@' and some don't? ===<br />
<br />
A function attribute requires an '@' if and only if it is not a keyword. Since "pure" and "nothrow" are keywords, but "safe" and "nogc" are not, using them all together would look like this:<br />
<br />
<syntaxhighlight lang="D">void foo() pure nothrow @safe @nogc;</syntaxhighlight><br />
<br />
A list of the current keywords are found [http://dlang.org/lex.html#Keyword here]. This looks odd, however, we haven't come up with an idea we like to solve this. Read on to understand the potential solutions and the problems they create.<br />
<br />
=== Why are some function attributes keywords and some not? ===<br />
<br />
Originally, all function attributes were also keywords, like <code>pure</code> and <code>nothrow</code>. Eventually, new features were added to the language that required new function attributes. However, making the new attributes into keywords would have fundamentally changed the syntax of the language and would result in breaking existing code. So instead of making these new attributes keywords, a decision was made to allow function attributes to be used that were not keywords so long as an '@' character was used. This allowed new function attributes to be added without breaking existing code. The disadvantage of this was that now a function with both kinds of attributes looks a bit odd, i.e.<br />
<br />
<syntaxhighlight lang="D">void foo() @safe pure @nogc nothrow;</syntaxhighlight><br />
<br />
Because of this, in the future some of these attributes may be added as keywords. However, doing so would result in breaking any code that previously used these words somewhere else such as a variable or function name. i.e.<br />
<br />
<syntaxhighlight lang="D">int safe = 0; // This code would break if "safe" was added as a keyword</syntaxhighlight><br />
<br />
=== Why do non-keyword attributes like safe and nogc require an '@' character? ===<br />
<br />
Supporting non-keyword attributes without requiring an '@' character would remove redundancy in the language. Redundancy in a language helps:<br />
<br />
* compilers give better error messages<br />
* syntax highlighters when the code is under development or contains errors<br />
<br />
The less redundancy a language has the more chances that one character change can propagate an error through the entire program. Consider the following example:<br />
<br />
<syntaxhighlight lang="D"><br />
void func()<br />
safe T = 7;<br />
</syntaxhighlight><br />
<br />
This is an error since the function definition is not finished. It should have ended with a semi-colon or a function body. If D allowed non-keyword function attributes, then "safe" and "T" would be considered attributes of the function by the parser and the error would not be found until the '=' character.<br />
<br />
<code>Error: expected ';' or '{' after function declaration, not '='</code><br />
<br />
=== Why don't we create a special rule in the syntax to handle non-keyword function attributes without an '@' character? ===<br />
<br />
The idea would be to add a new grammar rule for function attributes like this:<br />
<br />
<code><function-attribute> => <keyword> | "@" <identifier> | "safe" | "nogc" | ...</code><br />
<br />
This would allow a function to have attributes that are not keywords at the expense of syntax complexity. This solves the problem of redundancy, however, it is unknown whether or not this would make the grammar of the language ambiguous. If the function attributes were restricted to appear on the right hand side of a function signature (after the parameters), then this may solve the ambiguity problem. The other concern would be that this would complicate the syntax. The compiler and every syntax highlighter would need to handle this special case which can seem like a hack. In addition, this may seem confusing to some people. If a word is used as a function attribute, they may assume it is also a keyword, and if someone were to use it as an identifier this may be confusing. This would also create inconsistency with the brace and colon syntax:<br />
<syntaxhighlight lang="D"><br />
void foo1() safe;<br />
@safe {<br />
void foo2();<br />
}<br />
@safe:<br />
void foo3();<br />
</syntaxhighlight ><br />
<br />
These examples all apply the "safe" attribute to their respective function, but now some use an '@' and some don't.<br />
<br />
=== Why don't we just allow an '@' character on all function attributes so it looks consistent? ===<br />
<br />
To appreciate the answer for this remember that the original problem is a matter of consistency. It's inconsistent that some function attributes use an '@' character and some don't. If D supported putting an '@' character on the function attributes that are also keywords, then this moves the inconsistency somewhere else. Since keywords are re-used all over the place, some instances of the keyword will require an '@' and some will not, i.e.<br />
<br />
<syntaxhighlight lang="D"><br />
@abstract void foo();<br />
abstract class C { }<br />
</syntaxhighlight><br />
<br />
See the inconsistency? Then you might say, let's make some attributes require an '@' and some not, but how does that solve the original problem? You've just moved some keywords into the '@' bin and some into the "no @' bin. Even worse, you've now made the rule more complex. The current rule is "Use an '@' symbol if the word is not a keyword". Now the rule is "Use an '@' symbol if the word not a keyword, except when you are using the keyword as ...". When the alternatives are considered, the simple rule is not that bad of an option.<br />
<br />
=== Why wasn't nogc made a keyword? ===<br />
<br />
Ideally, if the language were designed from scratch, <code>nogc</code> ''would'' be made a keyword. However, since the language has been around for a while, it is deemed undesirable to introduce new keywords. The reason is that before <code>nogc</code> was introduced, some existing code may have used identifiers called <code>nogc</code>; if it were suddenly regarded as a keyword now, that code would no longer compile, and the author would need to revise all parts of the code that used that identifier.<br />
<br />
== Operators ==<br />
<br />
=== Why does D not support chaining comparison operators? ===<br />
<br />
First off, what are chaining comparison operators? The term refers to a certain way that comparison operators behave in various languages, which allows for writing multiple comparisons without using logical '''and''' between them. Chaining comparison operators are popular in more dynamic languages like Python or Perl, and also provide a slight performance benefit as the middle value only needs to be evaluated once.<br />
<br />
Example:<br />
<syntaxhighlight lang="Python"><br />
age = 25<br />
<br />
if 18 < age <= 25:<br />
print('Chained comparison!')<br />
</syntaxhighlight><br />
<br />
The equivalent C code would be:<br />
<syntaxhighlight lang="C"><br />
int age = 25;<br />
<br />
if (18 < age && age <= 25)<br />
{<br />
printf("No chaining here!");<br />
}<br />
</syntaxhighlight><br />
<br />
So why does D not support this behaviour for comparison operators if it is more efficient, more concise, and more elegant than the equivalent C code? It is because D strives to be backwards-compatible with C wherever possible, and comparison operator chaining is not backwards-compatible with C. <br />
<br />
While code like <code>18 < age <= 25</code> is valid C and will generally do what you want (at least in an if-statement), it is not the same as the Python code above. First <code>18 < age</code> is evaluated, producing 1 (C does not have the boolean type), which is then compared to 25, which just happens to be greater than 1. This is more evident when checking if two variables are equal to a third value:<br />
<br />
<syntaxhighlight lang="C"><br />
int age1 = 25;<br />
int age2 = 25;<br />
<br />
if (age1 == age2 == 25)<br />
{<br />
printf("Something's fishy...");<br />
}<br />
</syntaxhighlight><br />
<br />
The above code will '''NOT''' print "Something's fishy...", as the expression <code>age1 == age2</code> produces 1, which is then compared to 25. Since 1 is not equal to 25 the whole expression evaluates to false and the if-statement will not execute.<br />
<br />
As was mentioned earlier, D strives to be backwards-compatible with C wherever possible. It was decided that while chaining comparison operators are somewhat desirable, it would be a bad idea to have a construct that is also valid C code but with subtly different semantics. The potential benefits were not worth the break in compatibility with C.<br />
<br />
[[Category:Tutorials]]</div>NickTreleavenhttps://wiki.dlang.org/?title=People&diff=7504People2016-05-09T15:24:47Z<p>NickTreleaven: Add link to dlang/people on github</p>
<hr />
<div>== Points of contact ==<br />
{| cellpadding="5" border="2" class="wikitable"<br />
|-<br />
! | Responsibility<br />
! width="200" | Name<br />
! width="300" | Github ID<br />
|-<br />
|<br />
* BDFL<br />
* D Language Fundamentals<br />
| Walter Bright<br />
| [https://github.com/WalterBright WalterBright]<br />
|-<br />
|<br />
* D Language Fundamentals<br />
* Standard Library Fundamentals<br />
| [http://erdani.com/index.php/contact Andrei Alexandrescu]<br />
| [https://github.com/andralex andralex]<br />
|-<br />
|<br />
* Release Process<br />
| Andrew Edwards<br />
Martin Nowak<br />
| [https://github.com/AndrewEdwards AndrewEdwards]<br />
[https://github.com/MartinNowak MartinNowak]<br />
|-<br />
|<br />
* Language Specification<br />
| Brian Schott<br />
| [https://github.com/Hackerpilot Hackerpilot]<br />
|-<br />
|<br />
* D compiler development<br />
* All-round bug-fixing, new-feature-implementing superman<br />
| Kenji Hara<br />
| [https://github.com/9rnsr 9rnsr]<br />
|-<br />
|<br />
* Bugzilla ([https://issues.dlang.org/ issues.dlang.org])<br />
* Mailing lists ([http://lists.puremagic.com/ lists.puremagic.com])<br />
* D Auto-Tester ([https://auto-tester.puremagic.com/ auto-tester.puremagic.com])<br />
| Brad Roberts<br />
| [https://github.com/braddr braddr]<br />
|-<br />
|<br />
* D forum ([http://forum.dlang.org/ forum.dlang.org])<br />
* D wiki ([http://wiki.dlang.org/ wiki.dlang.org])<br />
| Vladimir Panteleev<br />
| [https://github.com/CyberShadow CyberShadow]<br />
|-<br />
|<br />
* Dub package registry ([http://code.dlang.org/ code.dlang.org])<br />
| Sönke Ludwig<br />
| [https://github.com/s-ludwig s-ludwig]<br />
|-<br />
|<br />
* Google Summer of Code Coordinator<br />
| Craig Dillabaugh<br />
| [https://github.com/craig-dillabaugh craig-dillabaugh]<br />
|}<br />
<br />
== Mapping of Github handles to real names ==<br />
<br />
See also [https://github.com/orgs/dlang/people dlang/people] for organisation members.<br />
<br />
{| class=wikitable<br />
!Github handle<br />
!Real name<br />
|-<br />
|9il||Ilya Yaroshenko<br />
|-<br />
|9rnsr||Hara Kenji<br />
|-<br />
|andralex||Andrei Alexandrescu<br />
|-<br />
|burner||Robert Schadek<br />
|-<br />
|Dicebot||Mihail Strashun (Михаил Страшун)<br />
|-<br />
|Element-126||Jean-Loup Tastet<br />
|-<br />
|ibuclaw||Iain Buclaw<br />
|-<br />
|jwhear||Justin Whear<br />
|-<br />
|klickverbot||David Nadlinger<br />
|-<br />
|ntrel||Nick Treleaven<br />
|-<br />
|quickfur||H. S. Teoh<br />
|-<br />
|jpf91||Johannes Pfau<br />
|-<br />
|redstar||Kai Nacke<br />
|}<br />
<br />
== Bios and Information ==<br />
{{:People_widget}}<br />
<br />
{{#ask: [[Category:People]]<br />
|?Homepage URL=<br />
|format=category<br />
}}<br />
<br />
=== How to add a Person ===<br />
Create a new page with the same name as the person. Add the text <tt><nowiki>{{Person}}</nowiki></tt> to the page. Save.</div>NickTreleavenhttps://wiki.dlang.org/?title=Is_expression&diff=7470Is expression2016-04-16T11:38:26Z<p>NickTreleaven: /* A More "Complex" Example */ Remove unnecessary _ identifier</p>
<hr />
<div>{{DISPLAYTITLE:is expression}}<br />
"is" expressions are used for checking for valid types and are heavily used in template constraints. <br />
* [http://dlang.org/spec/expression.html#IsExpression IsExpression] spec<br />
* [http://ddili.org/ders/d.en/is_expr.html Programming in D - is Expression]<br />
<br />
The following are simple demonstrations of the "is" expression, distilled from the main site:<br />
<br />
<source lang="D"><br />
import std.stdio;<br />
void main()<br />
{<br />
assert( !is(Foo) ); // Foo isnt a type, yet...<br />
struct Foo {}<br />
assert( is(Foo) ); // now it is<br />
<br />
short x = 1;<br />
assert( is(typeof(x) == short) );<br />
assert( is(typeof(x) : int ) ); // can be implicitly converted<br />
<br />
alias double MyDubble;<br />
void foo(MyDubble x) {<br />
static if( is(MyDubble T) ) {<br />
writeln("MyDubble is a double");<br />
}<br />
}<br />
// foo("hello"); // T is a string: fail<br />
foo(4.2); // T is a double: pass<br />
<br />
alias real MyReal;<br />
void bar(MyReal y) {<br />
static if( is(MyReal T : float) ) {<br />
writeln("MyReal");<br />
}<br />
}<br />
bar(3); // can be implicitly converted<br />
}<br />
</source> <br />
<br />
===A More "Complex" Example ===<br />
A question was asked on [http://form.dlang.org DForum learning channel] about how to create a template that would accept any numeric type including complex types. This author ([[User:Jniehus]]) made several attempts to solve the poster's problem which "eventually" resulted in a final solution that looked like the following:<br />
<br />
<source lang="D"><br />
import std.stdio, std.conv, std.traits, std.complex;<br />
template isComplex(T) {<br />
static if ( is(T == Complex!double) ) {<br />
enum bool isComplex = true;<br />
}<br />
else static if ( is(T == Complex!float) ) {<br />
enum bool isComplex = true;<br />
}<br />
else static if ( is(T == Complex!real) ) {<br />
enum bool isComplex = true;<br />
}<br />
else {<br />
enum bool isComplex = false;<br />
}<br />
}<br />
<br />
template isComplexOrNumeric(T) {<br />
enum bool isComplexOrNumeric = (isComplex!T || isNumeric!T);<br />
}<br />
<br />
class Example(T) if (isComplexOrNumeric!T) {<br />
T k = to!T(1);<br />
}<br />
<br />
void main() {<br />
auto x = new Example!(Complex!double)();<br />
writeln(x.k);<br />
auto y = new Example!double();<br />
writeln(y.k);<br />
}<br />
</source><br />
<br />
This unsightly "static if" chain was used because a Complex type is actually a template itself which can accept one of three primitive types; double, float, or real. But as a more experienced D programmer (Artur Skawina) pointed out, the "is" expression is flexible enough to accomodate situations like this. So instead of writing a "static if" statement for each possible template type, we can use the following syntax to infer the secondary types:<br />
<br />
<source lang="D"><br />
template isComplex(T) <br />
{<br />
static if ( is(T == Complex!CT, CT) ) {<br />
enum isComplex = true;<br />
}<br />
else {<br />
enum isComplex = false;<br />
}<br />
}<br />
</source><br />
<br />
This is clearly a more scalable solution.<br />
<br />
== Summary == <br />
"is" expressions might seem simple at first glance, but there is much more under the surface. The various forms of an "is" expression mean slightly different things, and knowing when and where to use them is important when writing templates. Also, familiarize yourself with [http://dlang.org/phobos/std_traits.html std.traits], the most common type checks have already been done for you! If you want to see how they are done, browse the Phobos source for traits.d.<br />
<br />
[[Category:Expressions]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Is_expression&diff=7469Is expression2016-04-16T11:36:23Z<p>NickTreleaven: add anchor for link to IsExpression</p>
<hr />
<div>{{DISPLAYTITLE:is expression}}<br />
"is" expressions are used for checking for valid types and are heavily used in template constraints. <br />
* [http://dlang.org/spec/expression.html#IsExpression IsExpression] spec<br />
* [http://ddili.org/ders/d.en/is_expr.html Programming in D - is Expression]<br />
<br />
The following are simple demonstrations of the "is" expression, distilled from the main site:<br />
<br />
<source lang="D"><br />
import std.stdio;<br />
void main()<br />
{<br />
assert( !is(Foo) ); // Foo isnt a type, yet...<br />
struct Foo {}<br />
assert( is(Foo) ); // now it is<br />
<br />
short x = 1;<br />
assert( is(typeof(x) == short) );<br />
assert( is(typeof(x) : int ) ); // can be implicitly converted<br />
<br />
alias double MyDubble;<br />
void foo(MyDubble x) {<br />
static if( is(MyDubble T) ) {<br />
writeln("MyDubble is a double");<br />
}<br />
}<br />
// foo("hello"); // T is a string: fail<br />
foo(4.2); // T is a double: pass<br />
<br />
alias real MyReal;<br />
void bar(MyReal y) {<br />
static if( is(MyReal T : float) ) {<br />
writeln("MyReal");<br />
}<br />
}<br />
bar(3); // can be implicitly converted<br />
}<br />
</source> <br />
<br />
===A More "Complex" Example ===<br />
A question was asked on [http://form.dlang.org DForum learning channel] about how to create a template that would accept any numeric type including complex types. This author ([[User:Jniehus]]) made several attempts to solve the poster's problem which "eventually" resulted in a final solution that looked like the following:<br />
<br />
<source lang="D"><br />
import std.stdio, std.conv, std.traits, std.complex;<br />
template isComplex(T) {<br />
static if ( is(T == Complex!double) ) {<br />
enum bool isComplex = true;<br />
}<br />
else static if ( is(T == Complex!float) ) {<br />
enum bool isComplex = true;<br />
}<br />
else static if ( is(T == Complex!real) ) {<br />
enum bool isComplex = true;<br />
}<br />
else {<br />
enum bool isComplex = false;<br />
}<br />
}<br />
<br />
template isComplexOrNumeric(T) {<br />
enum bool isComplexOrNumeric = (isComplex!T || isNumeric!T);<br />
}<br />
<br />
class Example(T) if (isComplexOrNumeric!T) {<br />
T k = to!T(1);<br />
}<br />
<br />
void main() {<br />
auto x = new Example!(Complex!double)();<br />
writeln(x.k);<br />
auto y = new Example!double();<br />
writeln(y.k);<br />
}<br />
</source><br />
<br />
This unsightly "static if" chain was used because a Complex type is actually a template itself which can accept one of three primitive types; double, float, or real. But as a more experienced D programmer (Artur Skawina) pointed out, the "is" expression is flexible enough to accomodate situations like this. So instead of writing a "static if" statement for each possible template type, we can use the following syntax to infer the secondary types:<br />
<br />
<source lang="D"><br />
template isComplex(T) <br />
{<br />
static if ( is(T _ == Complex!CT, CT) ) {<br />
enum isComplex = true;<br />
}<br />
else {<br />
enum isComplex = false;<br />
}<br />
}<br />
</source><br />
<br />
This is clearly a more scalable solution.<br />
<br />
== Summary == <br />
"is" expressions might seem simple at first glance, but there is much more under the surface. The various forms of an "is" expression mean slightly different things, and knowing when and where to use them is important when writing templates. Also, familiarize yourself with [http://dlang.org/phobos/std_traits.html std.traits], the most common type checks have already been done for you! If you want to see how they are done, browse the Phobos source for traits.d.<br />
<br />
[[Category:Expressions]]</div>NickTreleavenhttps://wiki.dlang.org/?title=User_talk:9rnsr/DIP:_Template_Parameter_Constraint&diff=7455User talk:9rnsr/DIP: Template Parameter Constraint2016-04-02T15:04:31Z<p>NickTreleaven: </p>
<hr />
<div>''(Page found through random Google search).''<br />
<br />
I really like the inline constraint feature:<br />
<br />
<code>auto foo(R if isInputRange)(R range);</code><br />
<br />
Would love to see this giving cleaner errors.<br />
<br />
Similar syntax could make the auto function parameter proposal more useful:<br />
<br />
<code>auto foo()(auto range if isInputRange);</code><br />
<br />
Beside being easier to read (DRY), this disallows the user from supplying a type for R, and clearly documents the fact the user isn't expected to provide a type.<br />
<br />
--[[User:NickTreleaven|NickTreleaven]] ([[User talk:NickTreleaven|talk]]) 15:03, 2 April 2016 (UTC)<br />
----</div>NickTreleavenhttps://wiki.dlang.org/?title=User_talk:9rnsr/DIP:_Template_Parameter_Constraint&diff=7454User talk:9rnsr/DIP: Template Parameter Constraint2016-04-02T15:03:18Z<p>NickTreleaven: pipedream: auto function parameter with inline constraint</p>
<hr />
<div>''(Page found through random Google search).''<br />
<br />
I really like the inline constraint feature:<br />
<br />
<code>auto foo(R if isInputRange)(R range);</code><br />
<br />
Would love to see this giving cleaner errors.<br />
<br />
Similar syntax could make the auto function parameter proposal more useful:<br />
<br />
<code>auto foo()(auto range if isInputRange);</code><br />
<br />
Beside being easier to read, this disallows the user from supplying a type for R, and clearly documents the fact the user isn't expected to provide a type.<br />
<br />
--[[User:NickTreleaven|NickTreleaven]] ([[User talk:NickTreleaven|talk]]) 15:03, 2 April 2016 (UTC)<br />
----</div>NickTreleavenhttps://wiki.dlang.org/?title=Language_issues&diff=7281Language issues2016-02-24T17:56:23Z<p>NickTreleaven: /* Explicit syntax and @disable this */ add 2nd discussion link</p>
<hr />
<div>Like any programming language, D is not perfect. This page lists some potential problems that have been brought up and debated throughout the language's history. Fixing these is not straight-forward or may not justify breaking backwards-compatibility. As of the moment of writing this, there are no plans for a major revision of D which would allow such breaking changes, but this list may also be useful for other programming languages which wish to learn from D's experience.<br />
<br />
See also: [[Language design discussions]]<br />
<br />
== Properties ==<br />
<br />
Design of properties has been an oft-discussed topic. This language feature has evolved throughout D's history (e.g. the addition and removal of the <tt>-property</tt> switch). There are numerous [[DIPs]] with proposals on improving the design:<br />
<br />
* [[DIP4]]<br />
* [[DIP5]]<br />
* [[DIP6]]<br />
* [[DIP21]]<br />
* [[DIP23]]<br />
* [[DIP24]]<br />
* [[DIP26]]<br />
* [[DIP28]]<br />
<br />
See also:<br />
<br />
* [[Property Discussion Wrap-up]]<br />
* [[Language design discussions#Properties]]<br />
<br />
== Unicode and ranges ==<br />
<br />
D's ranges currently treat strings in a special way: they present them as a range of code points, thus implicitly performing UTF decoding. Algorithms that do not require working with decoded code points, and which would gain a performance advantage by treating the input as a range of code units (or an array of code units), must incorporate D strings as a special case. This approach complicates the implementation by some degree, and only solves a certain subset of problems for a subset of written languages.<br />
<br />
Walter Bright has mentioned that auto-decoding is his #1 thing he currently dislikes about D [[http://www.reddit.com/r/programming/comments/2a20h5/wired_magazine_discovers_d/ciqqlg5 1]] [[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com 2]].<br />
<br />
See also:<br />
<br />
* [[Element type of string ranges]]<br />
* [http://forum.dlang.org/post/lfbbcn$2th7$1@digitalmars.com March 2014 discussion]<br />
* [https://github.com/D-Programming-Language/phobos/pull/2423 Related discussion in pull request "add range version of setExtension"]<br />
<br />
== Attribute creep ==<br />
<br />
In a 2014 forum thread titled "[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com What are the worst parts of D?]", a prevalent complaint was the number of attributes that functions can be decorated with.<br />
<br />
D currently allows the following attributes:<br />
<br />
* [http://dlang.org/function.html#virtual-functions <tt>override</tt> / <tt>final</tt>] / [http://dlang.org/attribute.html#abstract <tt>abstract</tt>]<br />
* [http://dlang.org/attribute.html#linkage <tt>extern</tt>]<br />
* [http://dlang.org/function.html#property-functions <tt>@property</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
* [http://dlang.org/function.html#safe-functions <tt>@safe</tt>] / [http://dlang.org/function.html#trusted-functions <tt>@trusted</tt>] / [http://dlang.org/function.html#system-functions <tt>@system</tt>]<br />
* [http://dlang.org/function.html#pure-functions <tt>pure</tt>]<br />
* [http://dlang.org/function.html#nothrow-functions <tt>nothrow</tt>]<br />
* [http://dlang.org/attribute.html#nogc <tt>@nogc</tt>]<br />
* [http://dlang.org/attribute.html#disable <tt>@disable</tt>]<br />
* [http://dlang.org/attribute.html#deprecated <tt>deprecated</tt>]<br />
* [[DIP25 | return]]<br />
<br />
Additionally, function return types can be or be annotated with the following keywords:<br />
<br />
* [http://dlang.org/function.html#auto-functions <tt>auto</tt>]<br />
* [http://dlang.org/function.html#ref-functions <tt>ref</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
<br />
== Signed/unsigned comparisons ==<br />
<br />
Currently, the following code fails:<br />
<br />
<syntaxhighlight lang="d"><br />
uint i = 1;<br />
assert(i > -2);<br />
</syntaxhighlight><br />
<br />
<tt>i > -2</tt> evaluates to <tt>false</tt> due to C compatibility (the same expression also evaluates to <tt>false</tt> in C, and one of D's goals is that if any C code compiles in D, then it should act like in C). One proposal is to make signed/unsigned comparisons generate a warning.<br />
<br />
See [https://d.puremagic.com/issues/show_bug.cgi?id=259 issue 259] for discussion.<br />
<br />
== Null References ==<br />
Null references have often been blamed as a common class of bugs, which could be prevented statically by the compiler (e.g. as a <tt>NotNull</tt> modifier, or explicitly marking variables possibly containing null values). This can be done by statically checking if all code paths (e.g. all class constructors) initialize a reference variable to a non-null value.<br />
<br />
See also:<br />
<br />
* [http://forum.dlang.org/post/vgntbohxwfnglyiyxgmi@forum.dlang.org February 2014 discussion]<br />
* [http://forum.dlang.org/post/vhtcmmnihixpmaqtakmg@forum.dlang.org September 2012 discussion]<br />
* [http://d.puremagic.com/issues/show_bug.cgi?id=4595 Issue 4595 - <nowiki>[tdpl]</nowiki> Accessing non-static member of a null reference compiles]<br />
<br />
== Virtual by default ==<br />
<br />
In D, methods are virtual by default. Although this approach does have benefits from the point of view of extensibility, it has been criticized that this default incurs a considerable performance impact and harms forward compatibility in user code, unless explicitly disabled everywhere as appropriate using the <tt>final</tt> keyword.<br />
<br />
Although at one point Walter Bright [http://forum.dlang.org/post/lfqoan$5qq$1@digitalmars.com intended] to change the default (see [https://d.puremagic.com/issues/show_bug.cgi?id=11616 Issue 11616] and [[DIP51]]), ultimately this proposal [http://forum.dlang.org/post/lfrdst$oav$1@digitalmars.com has been rejected].<br />
<br />
== Default constructors ==<br />
<br />
D does not support custom default constructors for value types: attempting to declare a <tt>struct</tt> constructor without any arguments is an error. The rationale for this limitation is to allow any type to have a known constant default value (<tt>.init</tt> property). This is unlike C++, where structs and classes can have default constructors, which allow executing custom code at the point of a variable's declaration.<br />
<br />
D's restriction prevents implementing certain C++ patterns, and requires users to rely on conventions for factory functions.<br />
<br />
=== Advantages of <tt>.init</tt> ===<br />
<br />
[http://forum.dlang.org/post/m18aku$2q7e$1@digitalmars.com According to Walter Bright], some advantages of <tt>.init</tt> over default constructors are:<br />
<br />
# the default object is trivially constructable and cannot fail<br />
# an easy way for other constructors to not have overlooked field initializers, so they get garbage initialized like in C++<br />
# generic code can rely on the existence of trivial construction that cannot fail<br />
# dummy objects can be created, useful for "does this compile" semantics<br />
# an object can be "destroyed" by overwriting it with .init (overwriting with 0 is not the same thing)<br />
# when you see: <tt>T t;</tt> in code, you know it is trivially constructed and will succeed<br />
# objects can be created using <tt>TypeInfo</tt><br />
<br />
=== Explicit syntax and <tt>@disable this</tt> ===<br />
<br />
In theory, explicit struct construction syntax <tt>S s = S();</tt> could allow calling a zero-argument constructor (vs. just <tt>S s;</tt> which is default construction). Forgetting to use the explicit syntax can be solved by disabling the default constructor (<tt>@disable this;</tt>).<br />
<br />
See also:<br />
* [http://forum.dlang.org/post/li3n8n$7ci$1@digitalmars.com April 2014 discussion]<br />
* [http://forum.dlang.org/post/k8ti2b$1iqj$1@digitalmars.com November 2012 discussion] (note we do now support <tt>int(2)</tt> syntax)<br />
<br />
== Memory management ==<br />
<br />
D is often criticized for its reliance on a garbage collector, and the quality of the current GC implementation.<br />
<br />
The current GC implementation is:<br />
<br />
* conservative (meaning, it can't guarantee whether any object actually has live references to it)<br />
* non-moving (the GC doesn't attempt to compact the heap to reduce fragmentation and working set size)<br />
* stop-the-world (all threads are stopped during a GC scan)<br />
<br />
Precise (as far as the heap is concerned) and concurrent D GC implementations have been presented:<br />
* [http://dconf.org/2013/talks/schuetze.html A Precise Garbage Collector for D] (DConf 2013 talk by Rainer Schütze)<br />
* [http://dconf.org/2013/talks/lucarella.html Concurrent Garbage Collection for D] (DConf 2013 talk by Leandro Lucarella)<br />
<br />
Although the GC can be disabled, using D completely without the GC may be challenging, as some parts of D expect a GC to be available:<br />
<br />
* Many modules in Phobos, D's standard library, expect a GC to be present to clean up temporary allocations;<br />
* D language features such as arrays require careful use to avoid memory leaks;<br />
* D language features such as closures and exceptions cannot be used, as they do not provide a way to manually deallocate allocated memory.<br />
<br />
Some alternative runtimes / standard libraries which do not rely on the GC are listed [[Libraries_and_Frameworks#Alternative_standard_libraries_.2F_runtimes|here]].</div>NickTreleavenhttps://wiki.dlang.org/?title=Language_issues&diff=7280Language issues2016-02-24T12:39:39Z<p>NickTreleaven: /* Explicit syntax and @disable this */ minor readability fixes</p>
<hr />
<div>Like any programming language, D is not perfect. This page lists some potential problems that have been brought up and debated throughout the language's history. Fixing these is not straight-forward or may not justify breaking backwards-compatibility. As of the moment of writing this, there are no plans for a major revision of D which would allow such breaking changes, but this list may also be useful for other programming languages which wish to learn from D's experience.<br />
<br />
See also: [[Language design discussions]]<br />
<br />
== Properties ==<br />
<br />
Design of properties has been an oft-discussed topic. This language feature has evolved throughout D's history (e.g. the addition and removal of the <tt>-property</tt> switch). There are numerous [[DIPs]] with proposals on improving the design:<br />
<br />
* [[DIP4]]<br />
* [[DIP5]]<br />
* [[DIP6]]<br />
* [[DIP21]]<br />
* [[DIP23]]<br />
* [[DIP24]]<br />
* [[DIP26]]<br />
* [[DIP28]]<br />
<br />
See also:<br />
<br />
* [[Property Discussion Wrap-up]]<br />
* [[Language design discussions#Properties]]<br />
<br />
== Unicode and ranges ==<br />
<br />
D's ranges currently treat strings in a special way: they present them as a range of code points, thus implicitly performing UTF decoding. Algorithms that do not require working with decoded code points, and which would gain a performance advantage by treating the input as a range of code units (or an array of code units), must incorporate D strings as a special case. This approach complicates the implementation by some degree, and only solves a certain subset of problems for a subset of written languages.<br />
<br />
Walter Bright has mentioned that auto-decoding is his #1 thing he currently dislikes about D [[http://www.reddit.com/r/programming/comments/2a20h5/wired_magazine_discovers_d/ciqqlg5 1]] [[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com 2]].<br />
<br />
See also:<br />
<br />
* [[Element type of string ranges]]<br />
* [http://forum.dlang.org/post/lfbbcn$2th7$1@digitalmars.com March 2014 discussion]<br />
* [https://github.com/D-Programming-Language/phobos/pull/2423 Related discussion in pull request "add range version of setExtension"]<br />
<br />
== Attribute creep ==<br />
<br />
In a 2014 forum thread titled "[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com What are the worst parts of D?]", a prevalent complaint was the number of attributes that functions can be decorated with.<br />
<br />
D currently allows the following attributes:<br />
<br />
* [http://dlang.org/function.html#virtual-functions <tt>override</tt> / <tt>final</tt>] / [http://dlang.org/attribute.html#abstract <tt>abstract</tt>]<br />
* [http://dlang.org/attribute.html#linkage <tt>extern</tt>]<br />
* [http://dlang.org/function.html#property-functions <tt>@property</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
* [http://dlang.org/function.html#safe-functions <tt>@safe</tt>] / [http://dlang.org/function.html#trusted-functions <tt>@trusted</tt>] / [http://dlang.org/function.html#system-functions <tt>@system</tt>]<br />
* [http://dlang.org/function.html#pure-functions <tt>pure</tt>]<br />
* [http://dlang.org/function.html#nothrow-functions <tt>nothrow</tt>]<br />
* [http://dlang.org/attribute.html#nogc <tt>@nogc</tt>]<br />
* [http://dlang.org/attribute.html#disable <tt>@disable</tt>]<br />
* [http://dlang.org/attribute.html#deprecated <tt>deprecated</tt>]<br />
* [[DIP25 | return]]<br />
<br />
Additionally, function return types can be or be annotated with the following keywords:<br />
<br />
* [http://dlang.org/function.html#auto-functions <tt>auto</tt>]<br />
* [http://dlang.org/function.html#ref-functions <tt>ref</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
<br />
== Signed/unsigned comparisons ==<br />
<br />
Currently, the following code fails:<br />
<br />
<syntaxhighlight lang="d"><br />
uint i = 1;<br />
assert(i > -2);<br />
</syntaxhighlight><br />
<br />
<tt>i > -2</tt> evaluates to <tt>false</tt> due to C compatibility (the same expression also evaluates to <tt>false</tt> in C, and one of D's goals is that if any C code compiles in D, then it should act like in C). One proposal is to make signed/unsigned comparisons generate a warning.<br />
<br />
See [https://d.puremagic.com/issues/show_bug.cgi?id=259 issue 259] for discussion.<br />
<br />
== Null References ==<br />
Null references have often been blamed as a common class of bugs, which could be prevented statically by the compiler (e.g. as a <tt>NotNull</tt> modifier, or explicitly marking variables possibly containing null values). This can be done by statically checking if all code paths (e.g. all class constructors) initialize a reference variable to a non-null value.<br />
<br />
See also:<br />
<br />
* [http://forum.dlang.org/post/vgntbohxwfnglyiyxgmi@forum.dlang.org February 2014 discussion]<br />
* [http://forum.dlang.org/post/vhtcmmnihixpmaqtakmg@forum.dlang.org September 2012 discussion]<br />
* [http://d.puremagic.com/issues/show_bug.cgi?id=4595 Issue 4595 - <nowiki>[tdpl]</nowiki> Accessing non-static member of a null reference compiles]<br />
<br />
== Virtual by default ==<br />
<br />
In D, methods are virtual by default. Although this approach does have benefits from the point of view of extensibility, it has been criticized that this default incurs a considerable performance impact and harms forward compatibility in user code, unless explicitly disabled everywhere as appropriate using the <tt>final</tt> keyword.<br />
<br />
Although at one point Walter Bright [http://forum.dlang.org/post/lfqoan$5qq$1@digitalmars.com intended] to change the default (see [https://d.puremagic.com/issues/show_bug.cgi?id=11616 Issue 11616] and [[DIP51]]), ultimately this proposal [http://forum.dlang.org/post/lfrdst$oav$1@digitalmars.com has been rejected].<br />
<br />
== Default constructors ==<br />
<br />
D does not support custom default constructors for value types: attempting to declare a <tt>struct</tt> constructor without any arguments is an error. The rationale for this limitation is to allow any type to have a known constant default value (<tt>.init</tt> property). This is unlike C++, where structs and classes can have default constructors, which allow executing custom code at the point of a variable's declaration.<br />
<br />
D's restriction prevents implementing certain C++ patterns, and requires users to rely on conventions for factory functions.<br />
<br />
=== Advantages of <tt>.init</tt> ===<br />
<br />
[http://forum.dlang.org/post/m18aku$2q7e$1@digitalmars.com According to Walter Bright], some advantages of <tt>.init</tt> over default constructors are:<br />
<br />
# the default object is trivially constructable and cannot fail<br />
# an easy way for other constructors to not have overlooked field initializers, so they get garbage initialized like in C++<br />
# generic code can rely on the existence of trivial construction that cannot fail<br />
# dummy objects can be created, useful for "does this compile" semantics<br />
# an object can be "destroyed" by overwriting it with .init (overwriting with 0 is not the same thing)<br />
# when you see: <tt>T t;</tt> in code, you know it is trivially constructed and will succeed<br />
# objects can be created using <tt>TypeInfo</tt><br />
<br />
=== Explicit syntax and <tt>@disable this</tt> ===<br />
<br />
In theory, explicit struct construction syntax <tt>S s = S();</tt> could allow calling a zero-argument constructor (vs. just <tt>S s;</tt> which is default construction). Forgetting to use the explicit syntax can be solved by disabling the default constructor (<tt>@disable this;</tt>).<br />
<br />
See also: [http://forum.dlang.org/post/li3n8n$7ci$1@digitalmars.com April 2014 discussion]<br />
<br />
== Memory management ==<br />
<br />
D is often criticized for its reliance on a garbage collector, and the quality of the current GC implementation.<br />
<br />
The current GC implementation is:<br />
<br />
* conservative (meaning, it can't guarantee whether any object actually has live references to it)<br />
* non-moving (the GC doesn't attempt to compact the heap to reduce fragmentation and working set size)<br />
* stop-the-world (all threads are stopped during a GC scan)<br />
<br />
Precise (as far as the heap is concerned) and concurrent D GC implementations have been presented:<br />
* [http://dconf.org/2013/talks/schuetze.html A Precise Garbage Collector for D] (DConf 2013 talk by Rainer Schütze)<br />
* [http://dconf.org/2013/talks/lucarella.html Concurrent Garbage Collection for D] (DConf 2013 talk by Leandro Lucarella)<br />
<br />
Although the GC can be disabled, using D completely without the GC may be challenging, as some parts of D expect a GC to be available:<br />
<br />
* Many modules in Phobos, D's standard library, expect a GC to be present to clean up temporary allocations;<br />
* D language features such as arrays require careful use to avoid memory leaks;<br />
* D language features such as closures and exceptions cannot be used, as they do not provide a way to manually deallocate allocated memory.<br />
<br />
Some alternative runtimes / standard libraries which do not rely on the GC are listed [[Libraries_and_Frameworks#Alternative_standard_libraries_.2F_runtimes|here]].</div>NickTreleavenhttps://wiki.dlang.org/?title=Language_issues&diff=7279Language issues2016-02-24T12:37:35Z<p>NickTreleaven: /* Default constructors */ Add subsection on explicit syntax + discussion link</p>
<hr />
<div>Like any programming language, D is not perfect. This page lists some potential problems that have been brought up and debated throughout the language's history. Fixing these is not straight-forward or may not justify breaking backwards-compatibility. As of the moment of writing this, there are no plans for a major revision of D which would allow such breaking changes, but this list may also be useful for other programming languages which wish to learn from D's experience.<br />
<br />
See also: [[Language design discussions]]<br />
<br />
== Properties ==<br />
<br />
Design of properties has been an oft-discussed topic. This language feature has evolved throughout D's history (e.g. the addition and removal of the <tt>-property</tt> switch). There are numerous [[DIPs]] with proposals on improving the design:<br />
<br />
* [[DIP4]]<br />
* [[DIP5]]<br />
* [[DIP6]]<br />
* [[DIP21]]<br />
* [[DIP23]]<br />
* [[DIP24]]<br />
* [[DIP26]]<br />
* [[DIP28]]<br />
<br />
See also:<br />
<br />
* [[Property Discussion Wrap-up]]<br />
* [[Language design discussions#Properties]]<br />
<br />
== Unicode and ranges ==<br />
<br />
D's ranges currently treat strings in a special way: they present them as a range of code points, thus implicitly performing UTF decoding. Algorithms that do not require working with decoded code points, and which would gain a performance advantage by treating the input as a range of code units (or an array of code units), must incorporate D strings as a special case. This approach complicates the implementation by some degree, and only solves a certain subset of problems for a subset of written languages.<br />
<br />
Walter Bright has mentioned that auto-decoding is his #1 thing he currently dislikes about D [[http://www.reddit.com/r/programming/comments/2a20h5/wired_magazine_discovers_d/ciqqlg5 1]] [[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com 2]].<br />
<br />
See also:<br />
<br />
* [[Element type of string ranges]]<br />
* [http://forum.dlang.org/post/lfbbcn$2th7$1@digitalmars.com March 2014 discussion]<br />
* [https://github.com/D-Programming-Language/phobos/pull/2423 Related discussion in pull request "add range version of setExtension"]<br />
<br />
== Attribute creep ==<br />
<br />
In a 2014 forum thread titled "[http://forum.dlang.org/post/m01r3d$1frl$1@digitalmars.com What are the worst parts of D?]", a prevalent complaint was the number of attributes that functions can be decorated with.<br />
<br />
D currently allows the following attributes:<br />
<br />
* [http://dlang.org/function.html#virtual-functions <tt>override</tt> / <tt>final</tt>] / [http://dlang.org/attribute.html#abstract <tt>abstract</tt>]<br />
* [http://dlang.org/attribute.html#linkage <tt>extern</tt>]<br />
* [http://dlang.org/function.html#property-functions <tt>@property</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
* [http://dlang.org/function.html#safe-functions <tt>@safe</tt>] / [http://dlang.org/function.html#trusted-functions <tt>@trusted</tt>] / [http://dlang.org/function.html#system-functions <tt>@system</tt>]<br />
* [http://dlang.org/function.html#pure-functions <tt>pure</tt>]<br />
* [http://dlang.org/function.html#nothrow-functions <tt>nothrow</tt>]<br />
* [http://dlang.org/attribute.html#nogc <tt>@nogc</tt>]<br />
* [http://dlang.org/attribute.html#disable <tt>@disable</tt>]<br />
* [http://dlang.org/attribute.html#deprecated <tt>deprecated</tt>]<br />
* [[DIP25 | return]]<br />
<br />
Additionally, function return types can be or be annotated with the following keywords:<br />
<br />
* [http://dlang.org/function.html#auto-functions <tt>auto</tt>]<br />
* [http://dlang.org/function.html#ref-functions <tt>ref</tt>]<br />
* [http://dlang.org/const3.html <tt>const</tt> / <tt>immutable</tt>] / [http://dlang.org/function.html#inout-functions <tt>inout</tt>]<br />
* [http://dlang.org/attribute.html#shared <tt>shared</tt>]<br />
<br />
== Signed/unsigned comparisons ==<br />
<br />
Currently, the following code fails:<br />
<br />
<syntaxhighlight lang="d"><br />
uint i = 1;<br />
assert(i > -2);<br />
</syntaxhighlight><br />
<br />
<tt>i > -2</tt> evaluates to <tt>false</tt> due to C compatibility (the same expression also evaluates to <tt>false</tt> in C, and one of D's goals is that if any C code compiles in D, then it should act like in C). One proposal is to make signed/unsigned comparisons generate a warning.<br />
<br />
See [https://d.puremagic.com/issues/show_bug.cgi?id=259 issue 259] for discussion.<br />
<br />
== Null References ==<br />
Null references have often been blamed as a common class of bugs, which could be prevented statically by the compiler (e.g. as a <tt>NotNull</tt> modifier, or explicitly marking variables possibly containing null values). This can be done by statically checking if all code paths (e.g. all class constructors) initialize a reference variable to a non-null value.<br />
<br />
See also:<br />
<br />
* [http://forum.dlang.org/post/vgntbohxwfnglyiyxgmi@forum.dlang.org February 2014 discussion]<br />
* [http://forum.dlang.org/post/vhtcmmnihixpmaqtakmg@forum.dlang.org September 2012 discussion]<br />
* [http://d.puremagic.com/issues/show_bug.cgi?id=4595 Issue 4595 - <nowiki>[tdpl]</nowiki> Accessing non-static member of a null reference compiles]<br />
<br />
== Virtual by default ==<br />
<br />
In D, methods are virtual by default. Although this approach does have benefits from the point of view of extensibility, it has been criticized that this default incurs a considerable performance impact and harms forward compatibility in user code, unless explicitly disabled everywhere as appropriate using the <tt>final</tt> keyword.<br />
<br />
Although at one point Walter Bright [http://forum.dlang.org/post/lfqoan$5qq$1@digitalmars.com intended] to change the default (see [https://d.puremagic.com/issues/show_bug.cgi?id=11616 Issue 11616] and [[DIP51]]), ultimately this proposal [http://forum.dlang.org/post/lfrdst$oav$1@digitalmars.com has been rejected].<br />
<br />
== Default constructors ==<br />
<br />
D does not support custom default constructors for value types: attempting to declare a <tt>struct</tt> constructor without any arguments is an error. The rationale for this limitation is to allow any type to have a known constant default value (<tt>.init</tt> property). This is unlike C++, where structs and classes can have default constructors, which allow executing custom code at the point of a variable's declaration.<br />
<br />
D's restriction prevents implementing certain C++ patterns, and requires users to rely on conventions for factory functions.<br />
<br />
=== Advantages of <tt>.init</tt> ===<br />
<br />
[http://forum.dlang.org/post/m18aku$2q7e$1@digitalmars.com According to Walter Bright], some advantages of <tt>.init</tt> over default constructors are:<br />
<br />
# the default object is trivially constructable and cannot fail<br />
# an easy way for other constructors to not have overlooked field initializers, so they get garbage initialized like in C++<br />
# generic code can rely on the existence of trivial construction that cannot fail<br />
# dummy objects can be created, useful for "does this compile" semantics<br />
# an object can be "destroyed" by overwriting it with .init (overwriting with 0 is not the same thing)<br />
# when you see: <tt>T t;</tt> in code, you know it is trivially constructed and will succeed<br />
# objects can be created using <tt>TypeInfo</tt><br />
<br />
=== Explicit syntax and <tt>@disable this</tt> ===<br />
<br />
In theory, explicit construction syntax <tt>S s = S();</tt> could allow calling a zero-argument constructor (vs. just <tt>S s;</tt> which is default construction). Forgetting to use the explicit syntax can be solved by disabling the default constructor (<tt>@disable this;</tt>).<br />
<br />
[http://forum.dlang.org/post/li3n8n$7ci$1@digitalmars.com April 2014 discussion]<br />
<br />
== Memory management ==<br />
<br />
D is often criticized for its reliance on a garbage collector, and the quality of the current GC implementation.<br />
<br />
The current GC implementation is:<br />
<br />
* conservative (meaning, it can't guarantee whether any object actually has live references to it)<br />
* non-moving (the GC doesn't attempt to compact the heap to reduce fragmentation and working set size)<br />
* stop-the-world (all threads are stopped during a GC scan)<br />
<br />
Precise (as far as the heap is concerned) and concurrent D GC implementations have been presented:<br />
* [http://dconf.org/2013/talks/schuetze.html A Precise Garbage Collector for D] (DConf 2013 talk by Rainer Schütze)<br />
* [http://dconf.org/2013/talks/lucarella.html Concurrent Garbage Collection for D] (DConf 2013 talk by Leandro Lucarella)<br />
<br />
Although the GC can be disabled, using D completely without the GC may be challenging, as some parts of D expect a GC to be available:<br />
<br />
* Many modules in Phobos, D's standard library, expect a GC to be present to clean up temporary allocations;<br />
* D language features such as arrays require careful use to avoid memory leaks;<br />
* D language features such as closures and exceptions cannot be used, as they do not provide a way to manually deallocate allocated memory.<br />
<br />
Some alternative runtimes / standard libraries which do not rely on the GC are listed [[Libraries_and_Frameworks#Alternative_standard_libraries_.2F_runtimes|here]].</div>NickTreleavenhttps://wiki.dlang.org/?title=DIP89&diff=7272DIP892016-02-21T18:12:06Z<p>NickTreleaven: Fix typo, number rules for easy reference</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''@mutable members in immutable data structures'''<br />
|-<br />
|DIP:<br />
|85<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2016-02-21<br />
|-<br />
|Last Modified:<br />
|{{REVISIONYEAR}}-{{REVISIONMONTH}}-{{REVISIONDAY}}<br />
|-<br />
|Author:<br />
|Marc Schütz<br />
|-<br />
|Links:<br />
|[https://forum.dlang.org/post/uilqvjlvkuvayygjnyen@forum.dlang.org Forum thread]<br />
|}<br />
<br />
== Abstract ==<br />
This DIP proposes an officially sanctioned way to mutate members in immutable data structures.<br />
<br />
== Rationale ==<br />
D's <code>immutable</code> signifies - in constrast to C++'s <code>const</code> - physical immutability, i.e. a guarantee that memory occupied by immutable variables will never change during their lifetime. This contrasts with logical immutability, which means that the underlying memory can change as long as the object represented by it remains semantically unchanged. Applications of logical immutability include lazy initialization, mutexes, reference counters or other embedded house-keeping data, as well as members changed for debugging purposes.<br />
<br />
Because D's <code>immutable</code> is as strict as it is (casting it away results in undefined behaviour), and <code>const</code> data may actually be <code>immutable</code>, in order to use the above-mentioned techniques, variables must either be mutable (which, because of <code>const</code> and <code>immutable</code>'s transitivity implies that many other variables and parameters cannot be marked as <code>const</code> either), or storing the mutable parts outside of the structures, which has considerable complexity, runtime and memory overhead, and can even be unsafe in combination with implicit sharing of <code>immutable</code> data (see below).<br />
<br />
With the proposed change, logical immutability (i.e. no changes are observable from the outside) can be achieved without provoking undefined behaviour while still having some basic statically enforced safety.<br />
<br />
== Description ==<br />
A new annotation <code>@mutable</code> for member variables and aggregate types is proposed. It is neither a type constructor, nor a storage class; it can be implemented as a compiler-recognized UDA. A member annotated as <code>@mutable</code> triggers the following behaviours:<br />
<br />
# It is required to be <code>private</code><br />
# Access to it is <code>@system</code><br />
# No static immutable objects with a <code>@mutable</code> member may be created<br />
# Dynamically created immutable objects with <code>@mutable</code> members are allowed if all <code>@mutable</code> members are marked as <code>shared</code> (analogously for implicit conversion of unique objects to immutable)<br />
<br />
These rules are enforced statically. Rationale for the rules:<br />
<br />
* The first rule (<code>private</code>) enforces encapsulation. This is the basic property of logical const-ness: an observer must never observe a change to an immutable object.<br />
* The second rule (<code>@system</code>) prevents accidental accesses that violate the above guarantee. This includes not just actual mutation of <code>@mutable</code> members, but even reads from them, because these can leak changed data to the outside. (If desired, this rule can be relaxed: reads in non-pure methods can be @safe.)<br />
* The third rule (no static immutables) is necessary because static immutable objects could be placed in physically read-only memory by the linker and therefore cannot be modified. Even though existing memory can be made read-only after initialization (using system calls like <code>mmap(2)</code>), doing this is not supposed to be prevented by the type system, because the <code>mmap</code>ed region can just as well contain normal mutable data.<br />
* The fourth rule (<code>shared</code>) prevents race conditions for implicitly shared immutable objects. Access to shared <code>@mutable</code> members must be atomic or otherwise synchronized.<br />
<br />
The compiler needs to make sure not to apply optimizations based on the assumption that a <code>@mutable</code> member never changes. Because D supports opaque data structures (<code>struct S;</code>), the <code>@mutable</code> annotation can also be attached to struct declarations: <code>@mutable struct S;</code>.<br />
<br />
To enable introspection, two traits are added: <code>isMutable</code>, and <code>hasMutableMembers</code>. The latter determines whether a types contains any mutable members, either directly, or embedded through another member.<br />
<br />
== Usage ==<br />
<source lang="D"><br />
struct S {<br />
@safe int expensiveComputation();<br />
lazy private int bar_;<br />
@trusted @property bar() const {<br />
if(!bar_)<br />
bar_ = expensiveComputation();<br />
return bar_;<br />
}<br />
}<br />
</source><br />
<br />
==About the AA solution==<br />
It has been proposed to place the mutable members into an external associate array, with the object as a key. This approach is surprisingly complex: not only does it have a considerable computational and memory cost (including caching effects), it also requires lifetime management of the AA's values.<br />
<br />
Additionally, it can have unexpected effects with shared objects (including immutable ones, which are implicitly shareable): while strictly speaking, it doesn't really violate safety by itself, it can have surprising consequences that the compiler is unable to guard against, because the associative array and the objects themselves can have non-matching shared-ness, as there is no formal relationship between the two. Take a reference counted immutable object as an example:<br />
<br />
<source lang="D"><br />
int[const(RCObject)] refcounts;<br />
struct RCObject {<br />
this() {<br />
refcounts[this] = 1;<br />
}<br />
this(this) {<br />
refcounts[this]++;<br />
}<br />
~this() {<br />
if(--refcounts[this] == 0)<br />
releaseResources();<br />
}<br />
}<br />
void foo() {<br />
auto o = new immutable(RCObject);<br />
send(otherTid, o);<br />
}<br />
</source><br />
<br />
Because <code>refcounts</code> in the example above is not marked as shared, it will be a thread-local instance. An immutable object sent to another thread will not have an entry in that thread's AA. The correct solution in this case would be to make the AA <code>shared</code> and to use atomic operations on its values. On the other hand, if it's guaranteed that the objects never cross a thread-boundary, the code is sufficient as-is. Unfortunately, the compiler cannot enforce the correct solution here.<br />
<br />
Now, using the changes proposed in this DIP, the code can be made safe by providing a shareable and a thread-local implementation of <code>RCObject</code>. Should the user choose the wrong one, the compiler will reject it because of rule 4.<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.<br />
<br />
[[Category: DIP]]</div>NickTreleavenhttps://wiki.dlang.org/?title=Memory_Management&diff=5183Memory Management2014-12-16T14:31:26Z<p>NickTreleaven: s/controling/controlling</p>
<hr />
<div>Most non-trivial programs needs to allocate and free memory. Memory management techniques become more and more important as programs increase in complexity, size, and performance. D offers many options for managing memory.<br />
<br />
The three primary methods for allocating memory in D are:<br />
<br />
* Static data, allocated in the default data segment.<br />
* Stack data, allocated on the CPU program stack.<br />
* Garbage collected data, allocated dynamically on the garbage collection heap.<br />
<br />
The techniques for using them, as well as some advanced alternatives are:<br />
<br />
== Strings (and Array) Copy-on-Write ==<br />
Consider the case of passing an array to a function, possibly modifying the contents of the array, and returning the modified array. As the contents of an array are accessed through a reference, a crucial issue is who owns the contents of the array? For example, a function to convert an array of characters to upper case: <br />
<syntaxhighlight lang="D"><br />
char[] toupper(char[] s)<br />
{<br />
int i;<br />
<br />
for (i = 0; i < s.length; i++)<br />
{<br />
char c = s[i];<br />
if ('a' <= c && c <= 'z')<br />
s[i] = cast(char)(c - ('a' - 'A'));<br />
}<br />
return s;<br />
}<br />
</syntaxhighlight><br />
<br />
Note that the caller's version of s[] is also modified. This may be not at all what was intended, or worse, s[] may be a slice into a read-only section of memory.<br />
<br />
If a copy of s[] was always made by toupper(), then that will unnecessarily consume time and memory for strings that are already all upper case.<br />
<br />
The solution is to implement copy-on-write, which means that a copy is made only if the string needs to be modified. Some string processing languages do do this as the default behavior, but there is a huge cost to it. The string "abcdeF" will wind up being copied 5 times by the function. To get the maximum efficiency using the protocol, it'll have to be done explicitly in the code. Here's toupper() rewritten to implement copy-on-write in an efficient manner: <br />
<br />
<syntaxhighlight lang="D"><br />
char[] toupper(char[] s)<br />
{<br />
int changed;<br />
int i;<br />
<br />
changed = 0;<br />
for (i = 0; i < s.length; i++)<br />
{<br />
char c = s[i];<br />
if ('a' <= c && c <= 'z')<br />
{<br />
if (!changed)<br />
{<br />
char[] r = new char[s.length];<br />
r[] = s;<br />
s = r;<br />
changed = 1;<br />
}<br />
s[i] = cast(char)(c - ('a' - 'A'));<br />
}<br />
}<br />
return s;<br />
}<br />
</syntaxhighlight><br />
<br />
Copy-on-write is the protocol implemented by array processing functions in the D Phobos runtime library.<br />
<br />
== Real Time ==<br />
Real time programming means that a program must be able to guarantee a maximum latency, or time to complete an operation. With most memory allocation schemes, including malloc/free and garbage collection, the latency is theoretically not bound. The most reliable way to guarantee latency is to preallocate all data that will be needed by the time critical portion. If no calls to allocate memory are done, the GC will not run and so will not cause the maximum latency to be exceeded. <br />
<br />
== Smooth Operation ==<br />
Related to real time programming is the need for a program to operate smoothly, without arbitrary pauses while the garbage collector stops everything to run a collection. An example of such a program would be an interactive shooter type game. Having the game play pause erratically, while not fatal to the program, can be annoying to the user.<br />
<br />
There are several techniques to eliminate or mitigate the effect:<br />
<br />
* Preallocate all data needed before the part of the code that needs to be smooth is run.<br />
* Manually run a GC collection cycle at points in program execution where it is already paused. An example of such a place would be where the program has just displayed a prompt for user input and the user has not responded yet. This reduces the odds that a collection cycle will be needed during the smooth code.<br />
* Call std.gc.disable() before the smooth code is run, and std.gc.enable() afterwards. This will cause the GC to favor allocating more memory instead of running a collection pass.<br />
<br />
== Free Lists ==<br />
Free lists are a great way to accelerate access to a frequently allocated and discarded type. The idea is simple - instead of deallocating an object when done with it, put it on a free list. When allocating, pull one off the free list first. <br />
<br />
<syntaxhighlight lang="D"><br />
class Foo<br />
{<br />
static Foo freelist; // start of free list<br />
<br />
static Foo allocate()<br />
{ Foo f;<br />
<br />
if (freelist)<br />
{ f = freelist;<br />
freelist = f.next;<br />
}<br />
else<br />
f = new Foo();<br />
return f;<br />
}<br />
<br />
static void deallocate(Foo f)<br />
{<br />
f.next = freelist;<br />
freelist = f;<br />
}<br />
<br />
Foo next; // for use by FooFreeList<br />
...<br />
}<br />
<br />
void test()<br />
{<br />
Foo f = Foo.allocate();<br />
...<br />
Foo.deallocate(f);<br />
}<br />
</syntaxhighlight><br />
<br />
Such free list approaches can be very high performance.<br />
<br />
* If used by multiple threads, the allocate() and deallocate() functions need to be synchronized.<br />
* The Foo constructor is not re-run by allocate() when allocating from the free list, so the allocator may need to reinitialize some of the members.<br />
* It is not necessary to practice RAII with this, since if any objects are not passed to deallocate() when done, because of a thrown exception, they'll eventually get picked up by the GC anyway.<br />
<br />
== Reference Counting ==<br />
The idea behind reference counting is to include a count field in the object. Increment it for each additional reference to it, and decrement it whenever a reference to it ceases. When the count hits 0, the object can be deleted.<br />
<br />
D doesn't provide any automated support for reference counting, it will have to be done explicitly.<br />
<br />
[[COM_Programming | Win32 COM programming]] uses the members AddRef() and Release() to maintain the reference counts.<br />
<br />
== Explicit Class Instance Allocation ==<br />
'''Note:''' [http://dlang.org/class.html#allocators Class allocators] and [http://dlang.org/class.html#deallocators deallocators] are deprecated in D2, but the following example provides an alternative.<br />
<br />
D provides a means of creating custom allocators and deallocators for class instances. Normally, these would be allocated on the garbage collected heap, and deallocated when the collector decides to run. For specialized purposes, this can be handled by creating New Declarations (<code>heapAllocate</code> in the example below) and Delete Declarations(<code>heapDeallocate</code> in the example below). For example, to allocate using the C runtime library's <code>malloc</code> and <code>free</code>:<br />
<br />
<syntaxhighlight lang="D"><br />
import std.stdio;<br />
<br />
class TestClass <br />
{<br />
int x;<br />
<br />
this(int x) <br />
{<br />
writeln("TestClass's constructor called");<br />
this.x = x;<br />
}<br />
<br />
~this() <br />
{<br />
writeln("TestClass's destructor called");<br />
}<br />
} <br />
<br />
T heapAllocate(T, Args...) (Args args) <br />
{<br />
import std.conv : emplace;<br />
import core.stdc.stdlib : malloc;<br />
import core.memory : GC;<br />
<br />
// get class size of class instance in bytes<br />
auto size = __traits(classInstanceSize, T);<br />
<br />
// allocate memory for the object<br />
auto memory = malloc(size)[0..size];<br />
if(!memory)<br />
{<br />
import core.exception : onOutOfMemoryError;<br />
onOutOfMemoryError();<br />
} <br />
<br />
writeln("Memory allocated");<br />
<br />
// notify garbage collector that it should scan this memory<br />
GC.addRange(memory.ptr, size);<br />
<br />
// call T's constructor and emplace instance on<br />
// newly allocated memory<br />
return emplace!(T, Args)(memory, args); <br />
}<br />
<br />
void heapDeallocate(T)(T obj) <br />
{<br />
import core.stdc.stdlib : free;<br />
import core.memory : GC;<br />
<br />
// calls obj's destructor<br />
destroy(obj); <br />
<br />
// garbage collector should no longer scan this memory<br />
GC.removeRange(cast(void*)obj);<br />
<br />
// free memory occupied by object<br />
free(cast(void*)obj);<br />
<br />
writeln("Memory deallocated");<br />
}<br />
<br />
void main() <br />
{<br />
// allocate new instance of TestClass on the heap<br />
auto test = heapAllocate!TestClass(42);<br />
scope(exit)<br />
{<br />
heapDeallocate(test); <br />
}<br />
<br />
writefln("test.x = %s", test.x);<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Output:<br />
<pre><br />
Memory allocated <br />
TestClass's constructor called <br />
test.x = 42 <br />
TestClass's destructor called <br />
Memory deallocated<br />
</pre><br />
<br />
The critical features of <code>heapAllocate</code> are:<br />
<br />
* A null is not returned if storage cannot be allocated. Instead, an exception is thrown. Which exception gets thrown is up to the programmer, in this case, <code>onOutOfMemoryError()</code> is called to throw an <code>OutOfMemoryError</code> exception.<br />
* When scanning memory for root pointers into the garbage collected heap, the static data segment and the stack are scanned automatically. The C heap is not. Therefore, if Foo or any class derived from Foo using the allocator contains any references to data allocated by the garbage collector, the GC needs to be notified. This is done with the <code>std.gc.addRange()</code> method.<br />
<br />
The critical features of <code>heapDeallocate</code> are:<br />
<br />
* The destructor (if any) is executed with a call to <code>destroy</code>, so the data <code>obj</code> points to should be assumed to be garbage.<br />
* If the GC was notified with <code>std.gc.addRange()</code>, a corresponding call to <code>std.gc.removeRange()</code> must happen in the deallocator.<br />
* If there is a <code>heapDeallocate</code>, there should be a corresponding <code>heapAllocate</code>.<br />
<br />
If memory is allocated using this method, careful coding practices must be followed to avoid memory leaks and dangling references. In the presence of exceptions, it is particularly important to practice RAII to prevent memory leaks.<br />
<br />
Custom allocators and deallocators can be done for structs and unions, too.<br />
<br />
== Mark/Release ==<br />
Mark/Release is equivalent to a stack method of allocating and freeing memory. A ‘stack’ is created in memory. Objects are allocated by simply moving a pointer down the stack. Various points are ‘marked’, and then whole sections of memory are released simply by resetting the stack pointer back to a marked point. <br />
<br />
<syntaxhighlight lang="D"><br />
import std.stdio;<br />
<br />
void[] buffer;<br />
size_t currentIndex;<br />
const size_t bufferSize = 100;<br />
<br />
// Static constructor will be called before main to allocate the buffer memory<br />
static this()<br />
{<br />
import core.stdc.stdlib : malloc;<br />
import core.memory : GC;<br />
<br />
writeln("Allocating buffer memory");<br />
<br />
auto p = malloc(bufferSize);<br />
<br />
if (p is null)<br />
{<br />
import core.exception : onOutOfMemoryError;<br />
onOutOfMemoryError();<br />
}<br />
<br />
// notify garbage collector that it should scan this memory<br />
GC.addRange(p, bufferSize);<br />
<br />
buffer = p[0 .. bufferSize];<br />
}<br />
<br />
// Static destructor will be called after leaving main to deallocate buffer memory<br />
static ~this()<br />
{<br />
if (buffer.length)<br />
{<br />
import core.stdc.stdlib : free;<br />
import core.memory : GC;<br />
<br />
// garbage collector should no longer scan this memory<br />
GC.removeRange(buffer.ptr);<br />
<br />
free(buffer.ptr);<br />
buffer = null;<br />
}<br />
<br />
writeln("Deallocated buffer memory");<br />
}<br />
<br />
// remember where to return to when memory is released<br />
size_t mark()<br />
{<br />
writefln("Marked at %s", currentIndex);<br />
return currentIndex;<br />
}<br />
<br />
// release the memory by returning to where it was marked<br />
void release(size_t markedIndex)<br />
{<br />
currentIndex = markedIndex;<br />
<br />
writefln("Released memory back to %s", currentIndex);<br />
}<br />
<br />
// Reserve memory for the object, and instantiate it<br />
T create(T, Args...) (Args args) <br />
{<br />
import std.conv : emplace;<br />
<br />
writefln("Reserving memory for %s", T.stringof);<br />
<br />
// get class size of class instance in bytes<br />
auto size = __traits(classInstanceSize, T);<br />
<br />
// check if there's enough room in the buffer<br />
auto newIndex = currentIndex + size;<br />
if (newIndex >= buffer.length)<br />
{<br />
import core.exception : onOutOfMemoryError;<br />
onOutOfMemoryError();<br />
}<br />
<br />
// get location where new instance will be emplaced<br />
auto memory = buffer[currentIndex..newIndex];<br />
<br />
// reserve the memory by advancing the index<br />
currentIndex = newIndex;<br />
<br />
// call T's constructor and emplace instance on<br />
// newly reserved memory<br />
return emplace!(T, Args)(memory, args);<br />
}<br />
<br />
class TestClass <br />
{<br />
int x;<br />
<br />
this(int x) <br />
{<br />
writeln("TestClass's constructor called");<br />
this.x = x;<br />
}<br />
<br />
~this() <br />
{<br />
writeln("TestClass's destructor called");<br />
}<br />
} <br />
<br />
void main()<br />
{<br />
writeln("Entered main");<br />
<br />
// Remember where to return to when memory is released<br />
size_t markedIndex = mark();<br />
scope(exit)<br />
{<br />
release(markedIndex); <br />
}<br />
<br />
// Instantiate new class on the buffer<br />
auto test = create!TestClass(42);<br />
scope (exit)<br />
{<br />
// be sure to call its destructor<br />
destroy(test);<br />
}<br />
<br />
writefln("test.x = %s", test.x);<br />
<br />
writeln("Leaving main");<br />
}<br />
</syntaxhighlight><br />
<br />
Output:<br />
<pre><br />
Allocating buffer memory <br />
Entered main <br />
Marked at 0 <br />
Reserving memory for TestClass <br />
TestClass's constructor called <br />
test.x = 42 <br />
Leaving main <br />
TestClass's destructor called <br />
Released memory back to 0 <br />
Deallocated buffer memory<br />
</pre><br />
<br />
The allocation of buffer[] itself is added as a region to the GC, so there is no need for a separate call when instantiating <code>TestClass</code>.<br />
<br />
== RAII (Resource Acquisition Is Initialization) ==<br />
RAII techniques can be useful in avoiding memory leaks when using explicit allocators and deallocators. Adding the [http://dlang.org/attribute.html#scope scope attribute] to such classes can help.<br />
<br />
'''Note:''' <code>scope</code> for allocating classes on the stack is [http://dlang.org/deprecate.html#scope%20for%20allocating%20classes%20on%20the%20stack planned for deprecation]. Also, see this [http://forum.dlang.org/post/juspoa$5g9$1@digitalmars.com forum discussion] and [https://issues.dlang.org/show_bug.cgi?id=5270 bug 5270] for more information.<br />
<br />
== Allocating Class Instances On The Stack ==<br />
'''Note:''' <code>scope</code> for allocating classes on the stack is [http://dlang.org/deprecate.html#scope%20for%20allocating%20classes%20on%20the%20stack planned for deprecation]. Also, see this [http://forum.dlang.org/post/juspoa$5g9$1@digitalmars.com forum discussion] and [https://issues.dlang.org/show_bug.cgi?id=5270 bug 5270] for more information.<br />
<br />
Class instances are normally allocated on the garbage collected heap. However, if they:<br />
<br />
* are allocated as local symbols in a function and<br />
* are allocated using <code>new</code> and<br />
* use <code>new</code> with no arguments (constructor arguments are allowed) and<br />
* have the <code>scope</code> storage class<br />
<br />
then they are allocated on the stack. This is more efficient than doing an allocate/free cycle on the instance. But be careful that any reference to the object does not survive the return of the function.<br />
<br />
<syntaxhighlight lang="D"><br />
class C { ... }<br />
<br />
scope c = new C(); // c is allocated on the stack<br />
scope c2 = new C(5); // allocated on stack<br />
scope c3 = new(5) C(); // allocated by a custom allocator<br />
</syntaxhighlight><br />
<br />
If the class has a destructor, then that destructor is guaranteed to be run when the class object goes out of scope, even if the scope is exited via an exception.<br />
<br />
== Allocating Uninitialized Arrays On The Stack ==<br />
Arrays are always initialized in D. So, the following declaration:<br />
<br />
<syntaxhighlight lang="D"><br />
void foo()<br />
{ byte[1024] buffer;<br />
<br />
fillBuffer(buffer);<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
will not be as fast as it might be since the buffer[] contents are always initialized. If careful profiling of the program shows that this initialization is a speed problem, it can be eliminated using a ''VoidInitializer'': <br />
<br />
<br />
<syntaxhighlight lang="D"><br />
void foo()<br />
{ byte[1024] buffer = void;<br />
<br />
fillBuffer(buffer);<br />
...<br />
}<br />
</syntaxhighlight><br />
<br />
Uninitialized data on the stack comes with some caveats that need to be carefully evaluated before using:<br />
<br />
* The uninitialized data that is on the stack will get scanned by the garbage collector looking for any references to allocated memory. Since the uninitialized data consists of old D stack frames, it is highly likely that some of that garbage will look like references into the GC heap, and the GC memory will not get freed. This problem really does happen, and can be pretty frustrating to track down.<br />
* It's possible for a function to pass out of it a reference to data on that function's stack frame. By then allocating a new stack frame over the old data, and not initializing, the reference to the old data may still appear to be valid. The program will then behave erratically. Initializing all data on the stack frame will greatly increase the probability of forcing that bug into the open in a repeatable manner.<br />
* Uninitialized data can be a source of bugs and trouble, even when used correctly. One design goal of D is to improve reliability and portability by eliminating sources of undefined behavior, and uninitialized data is one huge source of undefined, unportable, erratic and unpredictable behavior. Hence this idiom should only be used after other opportunities for speed optimization are exhausted and if benchmarking shows that it really does speed up the overall execution.<br />
<br />
<br />
== Writing GC free code ==<br />
<br />
As of D release version 2.066, it is possible to disallows GC-heap allocation in code sections, by marking them with the '''@nogc''' attribute.<br />
<br />
<syntaxhighlight lang="D"><br />
@nogc void foo(char[] a)<br />
{<br />
auto p = new int; // error, operator new allocates<br />
a ~= 'c'; // error, appending to arrays allocates<br />
bar(); // error, bar() may allocate<br />
}<br />
<br />
void bar() { }<br />
</syntaxhighlight><br />
<br />
This allows the compiler to enforce that the GC heap is not going to be used.<br />
<br />
Array concatenation, dynamic closures, calls to new operator and calls to functions not marked as '''@nogc''' are not allowed inside functions marked as '''@nogc'''.<br />
<br />
Work is in progress to make the D standard library, Phobos, usable without any use of the garbage collector. Eventually Phobos will be fully '''@nogc''' compliant.<br />
<br />
== Controlling GC Allocations ==<br />
<br />
As of release 2.066, the compiler switch ''-vgc'' provides a mechanism to identify GC heap allocations. When enabled, the compiler will list locations in the source code where GC heap allocations are being performed. The following example illustrates this.<br />
<br />
<syntaxhighlight lang="D"><br />
// main.d<br />
module main;<br />
<br />
class TestClass<br />
{ }<br />
<br />
void main(string[] args)<br />
{<br />
auto c = new TestClass();<br />
}<br />
</syntaxhighlight><br />
<br />
Compile with: <br />
<pre><br />
dmd -vgc main.d<br />
</pre><br />
<br />
Output:<br />
<pre><br />
test.d(9): vgc: 'new' causes GC allocation<br />
</pre><br />
<br />
Note, however, that this is ''not'' a compile-time error; the source code still compiles to an executable.<br />
<br />
== Composable Memory Allocators ==<br />
<br />
There is work in progress to add composable memory allocators as part of Phobos.<br />
<br />
An early peek at the current state of implementation is possible at:<br />
<br />
https://github.com/andralex/phobos/blob/allocator/std/allocator.d (Source code)<br />
<br />
http://erdani.com/d/phobos-prerelease/std_allocator.html (Documentation)<br />
<br />
== Interrupt Service Routines ==<br />
When the garbage collector does a collection pass, it must pause all running threads in order to scan their stacks and register contents for references to GC allocated objects. If an ISR (Interrupt Service Routine) thread is paused, this can break the program.<br />
<br />
Therefore, the ISR thread should not be paused. Threads created with the [http://dlang.org/phobos/core_thread.html core.thread] functions will be paused. But threads created with C's <code>_beginthread()</code> or equivalent won't be, the GC won't know they exist.<br />
<br />
For this to work successfully:<br />
<br />
* The ISR thread cannot allocate any memory using the GC. This means that the global <code>new</code> cannot be used. Nor can dynamic arrays be resized, nor can any elements be added to associative arrays. Any use of the D runtime library should be examined for any possibility of allocating GC memory - or better yet, the ISR should not call any D runtime library functions at all.<br />
* The ISR cannot hold the sole reference to any GC allocated memory, otherwise the GC may free the memory while the ISR is still using it. The solution is to have one of the paused threads hold a reference to it too, or store a reference to it in global data.</div>NickTreleavenhttps://wiki.dlang.org/?title=DIP69&diff=5148DIP692014-12-04T18:22:08Z<p>NickTreleaven: j is not scope, so remove wrong line comment</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''Implement scope for escape proof references'''<br />
|-<br />
|DIP:<br />
|69<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2014-12-04<br />
|-<br />
|Last Modified:<br />
|2014-12-04<br />
|-<br />
|Authors:<br />
|Marc Sch&uuml;tz, deadalnix, Andrei Alexandrescu and Walter Bright<br />
|-<br />
|Links:<br />
|'''Proposals'''<br />
* [http://wiki.dlang.org/User:Schuetzm/scope Scope Proposal by Marc Sch&uuml;tz. The above document is derived from this one.]<br />
* [http://wiki.dlang.org/DIP36 DIP36: Scope References by Dicebot]<br />
* [http://wiki.dlang.org/DIP35 DIP35: Addition to DIP25: Sealed References by Zach Tollen]<br />
* [http://wiki.dlang.org/DIP25 DIP25: Sealed References by Andrei Alexandrescu and Walter Bright]<br />
|'''Discussions'''<br />
* [http://forum.dlang.org/post/m5p99m$luk$1@digitalmars.com Discussion about this proposal]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/Why_is_scope_planned_for_deprecation_247445.html Why is scope planned for deprecation?]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/RFC_scope_and_borrowing_240834.html RFC: scope and borrowing]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/borrowed_pointers_vs_ref_232090.html borrowed pointers vs ref]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_for_design_of_scope_Was_Re_Opportunities_for_D_236686.html Proposal for design of scope]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/Re_Proposal_for_design_of_scope_Was_Re_Opportunities_for_D_236705.html Proposal for the design of scope pt 2]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/scope_escaping_222858.html scope escaping]<br />
|}<br />
<br />
<br />
=== Abstract ===<br />
<br />
A garbage collected language is inherently memory safe. References to data can be passed<br />
around without concern for ownership, lifetimes, etc. But this runs into difficulty when<br />
combined with other sorts of memory management, like stack allocation, malloc/free allocation,<br />
reference counting, etc.<br />
<br />
Knowing when the lifetime of a reference is over is critical for safely implementing memory<br />
management schemes other than GC. It is also critical for the performance of reference<br />
counting systems, as it will expose opportunities for elision of the inc/dec operations.<br />
<br />
<tt>scope</tt> provides a mechanism to guarantee that a reference cannot<br />
escape lexical scope.<br />
<br />
=== Benefits ===<br />
<br />
* References to stack variables can no longer escape.<br />
* Delegates currently defensively allocate closures with the GC. Few actually escape, and with scope only those that actually escape need to have the closures allocated.<br />
* <tt>@system</tt> code like <tt>std.internal.scopebuffer</tt> can be made <tt>@safe</tt>.<br />
* Reference counting systems need not adjust the count when passing references that do not escape.<br />
* Better self-documentation of encapsulation.<br />
<br />
=== Definitions ===<br />
<br />
==== Lifetime ====<br />
<br />
Any object exists for a specific period of time, with a well defined beginning and end point: from the<br />
point it is created (constructed), to the point it is released (destroyed). This is called its ''lifetime''.<br />
A reference that points to an object whose lifetime has ended is a dangling reference.<br />
Use of such references can cause all kinds of errors, and must therefore be prevented. <br />
<br />
The lifetime of variables is based purely on their lexical scope and order of declaration.<br />
The following rules define a hierarchy of lifetimes:<br />
<br />
* A variable's lifetime starts at the point of its declaration, and ends with the lexical scope it is defined in.<br />
* An (rvalue) expression's lifetime is temporary; it lives till the end of the statement that it appears in.<br />
* The lifetime of A is higher than that of B, if A appears in a higher scope than B, or if both appear in the same scope, but A comes lexically before B. This matches the order of destruction of local variables. <br />
* The lifetime of a function parameter is higher than that of that function's local variables, but lower than any variables in higher scopes.<br />
<br />
<br />
<br />
==== Ownership ====<br />
<br />
A variable ''owns'' the data it contains if, when the lifetime of the variable is ended, the data can be destroyed. There can be at most one owner for any piece of data.<br />
<br />
Ownership may be ''transitive'', meaning anything reachable through the owned data is also owned, or ''head'' where only<br />
the top level reference is owned.<br />
<br />
==== View ====<br />
<br />
Other references to ''owned'' data are called ''views''. Views must not survive the end of the lifetime of the owner<br />
of the data. A view v<sub>2</sub> may be taken of another view v<sub>1</sub>, and the lifetime of v<sub>2</sub> must be subset of the<br />
lifetime of v<sub>1</sub>.<br />
Views may also be transitive or head.<br />
<br />
=== Scope Fundamentals ===<br />
<br />
The purpose of <tt>scope</tt> is to provide a means for ensuring the lifetime of a viewer is a subset of the lifetime of the viewee.<br />
<br />
<tt>scope</tt> is a storage class, and affects declarations. It is not a type constructor.<br />
There is no change to existing [http://dlang.org/attribute#scope <tt>scope</tt> grammar]. It fits in the grammar as a storage class.<br />
<br />
Scope affects:<br />
<br />
* local variables allocated on the stack<br />
* function parameters<br />
* non-static member functions (applying to the <tt>this</tt>)<br />
* delegates (applying to the <tt>this</tt>)<br />
* return value of functions<br />
<br />
It is ignored for other declarations. It is ignored for declarations which are not views.<br />
<br />
<syntaxhighlight lang="D"><br />
scope enum e = 3; // scope is ignored for enums<br />
scope int i; // scope is ignored because integers are not references and so are not views<br />
</syntaxhighlight><br />
<br />
Scope affects variables according to these rules:<br />
<br />
# Scope variables can only be assigned values that have lifetimes that are a superset of the variable's lifetime.<br />
# Scope variables can only be assigned to scope variables with a lifetime that is a subset.<br />
# A variable is inferred to be scope if it is initialized with a view that has a non-&infin; lifetime.<br />
# A scope variable cannot be initialized with the address of a scoped variable.<br />
# A scope ref variable can be initialized with another scope ref variable - scope ref is idempotent.<br />
<br />
<br />
Basic operation:<br />
<br />
<syntaxhighlight lang="D"><br />
int global_var;<br />
int* global_ptr;<br />
<br />
void bar(scope int* input);<br />
<br />
void foo() {<br />
scope int* a;<br />
a = &global_var; // Ok, `global_var` has a greater lifetime than `a`<br />
scope b = &global_var; // Ok, type deduction<br />
int c;<br />
<br />
if(...) {<br />
scope x = a; // Ok, copy of reference,`x` has shorter lifetime than `a`<br />
scope y = &c; // Ok, lifetime(y) < lifetime(& c)<br />
int z;<br />
b = &z; // Error, `b` will outlive `z`<br />
int* d = a; // Ok: d is inferred to be `scope`<br />
}<br />
<br />
bar(a); // Ok, scoped pointer is passed to scoped parameter<br />
bar(&c); // Ok, lifetime(parameter input) < lifetime(c)<br />
int* e;<br />
e = &c; // Error, lifetime(e's view) is &infin; and is greater than lifetime(c)<br />
a = e; // Ok, lifetime(a) < lifetime(e)<br />
scope int** f = &a; // Error, rule 5<br />
scope int** h = &e; // Ok<br />
int* j = *h; // Ok, scope is not transitive<br />
}<br />
<br />
void abc() {<br />
scope int* a;<br />
int* b;<br />
scope ref int* c = a; // Error, rule 5<br />
scope ref int* d = b; // Ok<br />
int* i = a; // Ok, scope is inferred for i<br />
global_ptr = d; // Error, lifetime(d) < lifetime(global_ptr)<br />
global_ptr = i; // Error, lifetime(i) < lifetime(global_ptr)<br />
int* j;<br />
global_ptr = j; // Ok, j is not scope<br />
}<br />
</syntaxhighlight><br />
<br />
=== Return Statement ===<br />
<br />
A view annotated with <tt>scope</tt> cannot be returned from a function.<br />
<br />
<syntaxhighlight lang="D"><br />
class C { ... }<br />
scope C c;<br />
return c; // Error<br />
<br />
scope int i;<br />
return i; // Ok, i is not a view<br />
<br />
scope int* p;<br />
return p; // Error<br />
return p+1; // Error, nice try!<br />
return &*p; // Error, won't work either<br />
<br />
ref int func(scope ref int r, scope out int s)<br />
{<br />
return r; // Error<br />
return s; // Error, 'out' is treated like 'ref'<br />
}<br />
</syntaxhighlight><br />
<br />
=== Functions ===<br />
<br />
==== Inference ====<br />
<br />
Scope is inferred for function parameters if not specified, under the same circumstances as <tt>pure</tt>, <tt>nothrow</tt>, <tt>@nogc</tt><br />
and safety are inferred.<br />
<br />
==== Overloading ====<br />
<br />
Scope does not affect overloading. If it did, then whether a variable was scope or not would affect the code path, making<br />
scope inference impractical. It also makes turning scope checking on/off impractical.<br />
<br />
<syntaxhighlight lang="D"><br />
T func(scope ref T);<br />
T func(ref T);<br />
<br />
T t; func(t); // Error, ambiguous<br />
scope T u; func(u); // Error, ambiguous<br />
</syntaxhighlight><br />
<br />
<br />
==== Implicit Conversion of Function Pointers and Delegates ====<br />
<br />
<tt>scope</tt> can be added to parameters, but not removed.<br />
<br />
<syntaxhighlight lang="D"><br />
alias int function(ref T) fp_t;<br />
alias int function(scope ref T) fps_t;<br />
<br />
int foo(ref T);<br />
int bar(scope ref T);<br />
<br />
fp_t fp = &bar; // Ok, scope behavior is subset of non-scope<br />
fps_t fp = &foo; // Error, fps_t demands scope behavior<br />
</syntaxhighlight><br />
<br />
==== Inheritance ====<br />
<br />
Overriding functions inherit any <tt>scope</tt> annotations from their antecedents.<br />
Scope is covariant, meaning it can be added to overriding functions.<br />
<br />
<syntaxhighlight lang="D"><br />
class C<br />
{<br />
int foo(ref T);<br />
int bar(scope ref T);<br />
}<br />
<br />
class D : C<br />
{<br />
override int foo(scope ref T); // Ok, can add scope<br />
override int bar(ref T); // Error, cannot remove scope<br />
}<br />
</syntaxhighlight><br />
<br />
==== Mangling ====<br />
<br />
Scope will require additional mangling, as it affects the interface of the function.<br />
In cases where scope is ignored, it does not contribute to the mangling.<br />
Scope parameters will be mangled with ???.<br />
<br />
==== Nested Functions ====<br />
<br />
Nested functions have more objects available than just their arguments:<br />
<br />
<syntaxhighlight lang="D"><br />
ref T foo() {<br />
T t;<br />
ref T func() { return t; }<br />
return func(); // disallowed<br />
}<br />
</syntaxhighlight><br />
<br />
Nested functions are analyzed as if each variable accessed outside of its scope was passed as a ref parameter.<br />
All parameters have scope inferred from how they are used in the function body.<br />
<br />
<br />
=== Ref ===<br />
<br />
==== Escaping via Return ====<br />
<br />
The simple cases of this are disallowed:<br />
<br />
<syntaxhighlight lang="D"><br />
T* func(T t) {<br />
T u;<br />
return &t; // Error: escaping reference to local t<br />
return &u; // Error: escaping reference to local u<br />
}<br />
</syntaxhighlight><br />
<br />
But are easily circumvented:<br />
<br />
<syntaxhighlight lang="D"><br />
T* func(T t) {<br />
T* p = &t;<br />
return p; // no error detected<br />
}<br />
</syntaxhighlight><br />
<br />
@safe currently deals with this by preventing taking the address of a local:<br />
<br />
<syntaxhighlight lang="D"><br />
T* func(T t) @safe {<br />
T* p = &t; // Error: cannot take address of parameter t in @safe function func<br />
return p;<br />
}<br />
</syntaxhighlight><br />
<br />
This is restrictive. The <tt>ref</tt> storage class was introduced which<br />
defines a special purpose pointer. <tt>ref</tt> can only appear in certain contexts,<br />
in particular function parameters and returns, only applies to declarations,<br />
cannot be stored, and cannot be incremented.<br />
<br />
<syntaxhighlight lang="D"><br />
ref T func(T t) @safe {<br />
return t; // Error: escaping reference to local variable t<br />
}<br />
</syntaxhighlight><br />
<br />
Ref can be passed down to functions:<br />
<br />
<syntaxhighlight lang="D"><br />
void func(ref T t) @safe;<br />
void bar(ref T t) @safe {<br />
func(t); // ok<br />
}<br />
</syntaxhighlight><br />
<br />
But the following idiom is far too useful to be disallowed:<br />
<br />
<syntaxhighlight lang="D"><br />
ref T func(ref T t) {<br />
return t; // ok<br />
}<br />
</syntaxhighlight><br />
<br />
And if it is misused it can result in stack corruption:<br />
<br />
<syntaxhighlight lang="D"><br />
ref T foo() {<br />
T t;<br />
return func(t); // currently, no error detected, despite returning pointer to t<br />
}<br />
</syntaxhighlight><br />
<br />
The:<br />
<br />
<syntaxhighlight lang="D"><br />
return func(t);<br />
</syntaxhighlight><br />
<br />
case is detected by all of the following conditions being true:<br />
<br />
<br />
* foo() returns by reference<br />
* func() returns by reference<br />
* func() has one or more parameters that are by reference<br />
* 1 or more of the arguments to those parameters are stack objects local to foo()<br />
* Those arguments can be @safe-ly converted from the parameter to the return type.<br />
For example, if the return type is larger than the parameter type, the return type<br />
cannot be a reference to the argument. If the return type is a pointer, and the<br />
parameter type is a size_t, it cannot be a reference to the argument. The larger<br />
a list of these cases can be made, the more code will pass @safe checks without requiring<br />
further annotation.<br />
<br />
==== Scope Ref ====<br />
<br />
The above solution is correct, but a bit restrictive. After all, func(t, u) could be returning<br />
a reference to non-local u, not local t, and so should work. To fix this, introduce the concept<br />
of <tt>scope ref</tt>:<br />
<br />
<syntaxhighlight lang="D"><br />
ref T func(scope ref T t, ref T u) {<br />
return t; // Error: escaping scope ref t<br />
return u; // ok<br />
}<br />
</syntaxhighlight><br />
<br />
Scope means that the ref is guaranteed not to escape.<br />
<br />
<syntaxhighlight lang="D"><br />
T u;<br />
ref T foo() @safe {<br />
T t;<br />
return func(t, u); // Ok, u is not local<br />
return func(u, t); // Error: escaping scope ref t<br />
}<br />
</syntaxhighlight><br />
<br />
This minimizes the number of <tt>scope</tt> annotations required.<br />
<br />
==== Scope Function Returns ====<br />
<br />
<tt>scope</tt> can be applied to function return values (even though it is not a type constructor).<br />
It must be applied to the left of the declaration, in the same way <tt>ref</tt> is:<br />
<br />
<br />
<syntaxhighlight lang="D"><br />
int* foo() scope; // applies to 'this' reference<br />
scope: int* foo(); // applies to 'this' reference<br />
scope { int* foo(); } // applies to 'this' reference<br />
scope int* foo(); // applies to return value<br />
</syntaxhighlight><br />
<br />
The lifetime of a scope return value is the lifetime of an rvalue. It may not be copied in a way that extends its life.<br />
<br />
<syntaxhighlight lang="D"><br />
int* bar(scope int*);<br />
scope int* foo();<br />
...<br />
return foo(); // Error, lifetime(return) > lifetime(foo())<br />
int* p = foo(); // Error, lifetime(p) is &infin;<br />
bar(foo()); // Ok, lifetime(foo()) > lifetime(bar())<br />
scope int* q = foo(); // error, lifetime(q) > lifetime(rvalue)<br />
</syntaxhighlight><br />
<br />
This enables scope return values to be safely chained from function to function; in particular<br />
it also allows a ref counted struct to safely expose a reference to its wrapped type.<br />
<br />
==== Out Parameters ====<br />
<br />
<tt>out</tt> parameters are treated like <tt>ref</tt> parameters when <tt>scope</tt> is applied.<br />
<br />
=== Expressions ===<br />
<br />
The ''lifetime'' of an expression is either &infin; or the lifetime of a single variable. Which it is can be statically<br />
deduced by looking at the type and AST of the expression.<br />
<br />
The root cases are:<br />
<br />
<table border=1 cellpadding=4 cellspacing=0><br />
<tr><th class="donthyphenate">'''root case'''</th><th class="donthyphenate">'''lifetime'''</th></tr><br />
<tr><td>address of variable v</td><td>lifetime(v)</td></tr><br />
<tr><td>v containing value with references</td><td>lifetime(v)</td></tr><br />
<tr><td>otherwise</td><td>&infin;</td></tr><br />
</table><br />
<br />
<br />
More complex expressions can be reduced to be one of the root cases:<br />
<br />
<table border=1 cellpadding=4 cellspacing=0><br />
<tr><th class="donthyphenate">'''expression'''</th><th class="donthyphenate">'''lifetime'''</th></tr><br />
<tr><td><tt>&amp;(*e)</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>*(&e + integer)</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>*((e1? &amp; e2 : &e3) + integer)</tt></td><td>min(lifetime(e2), lifetime(e3))</td></tr><br />
<tr><td><tt>*e</tt></td><td>&infin;</td></tr><br />
<tr><td><tt>e1,e2</tt></td><td>lifetime(e2)</td></tr><br />
<tr><td><tt>e1 = e2</tt></td><td>lifetime(e1)</td></tr><br />
<tr><td><tt>e1 op= e2</tt></td><td>lifetime(e1)</td></tr><br />
<tr><td><tt>e1 ? e2 : e3</tt></td><td>min(lifetime(e2), lifetime(e3))</td></tr><br />
<tr><td><tt>ptr + integer</tt></td><td>lifetime(ptr)</td></tr><br />
<tr><td><tt>e1 op e2</tt></td><td>min(lifetime(e1), lifetime(e2))</td></tr><br />
<tr><td><tt>op e</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>e++</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>e--</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>cast(type) e</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>new</tt></td><td>&infin;</td></tr><br />
<tr><td><tt>e.field</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>(*e).field</tt></td><td>lifetime(*e)</td></tr><br />
<tr><td><tt>e.func(args)</tt></td><td>min(lifetime(e, args), &infin;)</td></tr><br />
<tr><td><tt>func(args)</tt></td><td>min(lifetime(non-scope-ref args), &infin;)</td></tr><br />
<tr><td><tt>e[]</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>e[i..j]</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>e[i]</tt></td><td>lifetime(*e)</td></tr><br />
<tr><td>''ArrayLiteral''</td><td>min(lifetime(args))</td></tr><br />
<tr><td>''ArrayLiteral[constant]''</td><td>lifetime(ArrayLiteral[constant])</td></tr><br />
</table><br />
<br />
=== Classes ===<br />
<br />
Scope class semantics are equivalent to a pointer to a struct.<br />
<br />
=== Static Arrays ===<br />
<br />
Scope static array semantics are equivalent to a scope struct:<br />
<br />
<syntaxhighlight lang="D"><br />
T[3] a;<br />
struct A { T t0, t1, t2; } A a;<br />
</syntaxhighlight><br />
<br />
=== @safe ===<br />
<br />
Errors for scope violations are only reported in @safe code.<br />
<br />
=== Breaking Existing Code ===<br />
<br />
Some code will no longer work. Although inference will take care of a lot of cases,<br />
there are still some that will fail.<br />
<br />
<syntaxhighlight lang="D"><br />
int i,j;<br />
int* p = &i; // Ok, scope is inferred for p<br />
int* q;<br />
q = &i; // Error: too late to infer scope for q<br />
</syntaxhighlight><br />
<br />
Currently, <tt>scope</tt> is ignored except that a new class use to initialize a scope variable allocates the class<br />
instance on the stack. Fortunately, this can work with this new proposal, with an optimization that recognizes<br />
that if a new class is unique, and assigned to a scope variable, then that instance can be placed on the stack.<br />
<br />
=== Implementation Plan ===<br />
<br />
Turning this on may cause significant breakage, and may also be found to be an unworkable design. Therefore, implementation stages will be:<br />
<br />
* enable new behavior with a compiler switch <tt>-scope</tt><br />
* remove <tt>-scope</tt>, issue warning when errors are detected<br />
* replace warnings with deprecation messages<br />
* replace deprecations with errors</div>NickTreleavenhttps://wiki.dlang.org/?title=DIP69&diff=5147DIP692014-12-04T18:15:01Z<p>NickTreleaven: Fix some obvious typos, link anchor: attribute#scope, class D : C</p>
<hr />
<div>{| class="wikitable"<br />
!Title:<br />
!'''Implement scope for escape proof references'''<br />
|-<br />
|DIP:<br />
|69<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2014-12-04<br />
|-<br />
|Last Modified:<br />
|2014-12-04<br />
|-<br />
|Authors:<br />
|Marc Sch&uuml;tz, deadalnix, Andrei Alexandrescu and Walter Bright<br />
|-<br />
|Links:<br />
|'''Proposals'''<br />
* [http://wiki.dlang.org/User:Schuetzm/scope Scope Proposal by Marc Sch&uuml;tz. The above document is derived from this one.]<br />
* [http://wiki.dlang.org/DIP36 DIP36: Scope References by Dicebot]<br />
* [http://wiki.dlang.org/DIP35 DIP35: Addition to DIP25: Sealed References by Zach Tollen]<br />
* [http://wiki.dlang.org/DIP25 DIP25: Sealed References by Andrei Alexandrescu and Walter Bright]<br />
|'''Discussions'''<br />
* [http://forum.dlang.org/post/m5p99m$luk$1@digitalmars.com Discussion about this proposal]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/Why_is_scope_planned_for_deprecation_247445.html Why is scope planned for deprecation?]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/RFC_scope_and_borrowing_240834.html RFC: scope and borrowing]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/borrowed_pointers_vs_ref_232090.html borrowed pointers vs ref]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_for_design_of_scope_Was_Re_Opportunities_for_D_236686.html Proposal for design of scope]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/Re_Proposal_for_design_of_scope_Was_Re_Opportunities_for_D_236705.html Proposal for the design of scope pt 2]<br />
* [http://www.digitalmars.com/d/archives/digitalmars/D/scope_escaping_222858.html scope escaping]<br />
|}<br />
<br />
<br />
=== Abstract ===<br />
<br />
A garbage collected language is inherently memory safe. References to data can be passed<br />
around without concern for ownership, lifetimes, etc. But this runs into difficulty when<br />
combined with other sorts of memory management, like stack allocation, malloc/free allocation,<br />
reference counting, etc.<br />
<br />
Knowing when the lifetime of a reference is over is critical for safely implementing memory<br />
management schemes other than GC. It is also critical for the performance of reference<br />
counting systems, as it will expose opportunities for elision of the inc/dec operations.<br />
<br />
<tt>scope</tt> provides a mechanism to guarantee that a reference cannot<br />
escape lexical scope.<br />
<br />
=== Benefits ===<br />
<br />
* References to stack variables can no longer escape.<br />
* Delegates currently defensively allocate closures with the GC. Few actually escape, and with scope only those that actually escape need to have the closures allocated.<br />
* <tt>@system</tt> code like <tt>std.internal.scopebuffer</tt> can be made <tt>@safe</tt>.<br />
* Reference counting systems need not adjust the count when passing references that do not escape.<br />
* Better self-documentation of encapsulation.<br />
<br />
=== Definitions ===<br />
<br />
==== Lifetime ====<br />
<br />
Any object exists for a specific period of time, with a well defined beginning and end point: from the<br />
point it is created (constructed), to the point it is released (destroyed). This is called its ''lifetime''.<br />
A reference that points to an object whose lifetime has ended is a dangling reference.<br />
Use of such references can cause all kinds of errors, and must therefore be prevented. <br />
<br />
The lifetime of variables is based purely on their lexical scope and order of declaration.<br />
The following rules define a hierarchy of lifetimes:<br />
<br />
* A variable's lifetime starts at the point of its declaration, and ends with the lexical scope it is defined in.<br />
* An (rvalue) expression's lifetime is temporary; it lives till the end of the statement that it appears in.<br />
* The lifetime of A is higher than that of B, if A appears in a higher scope than B, or if both appear in the same scope, but A comes lexically before B. This matches the order of destruction of local variables. <br />
* The lifetime of a function parameter is higher than that of that function's local variables, but lower than any variables in higher scopes.<br />
<br />
<br />
<br />
==== Ownership ====<br />
<br />
A variable ''owns'' the data it contains if, when the lifetime of the variable is ended, the data can be destroyed. There can be at most one owner for any piece of data.<br />
<br />
Ownership may be ''transitive'', meaning anything reachable through the owned data is also owned, or ''head'' where only<br />
the top level reference is owned.<br />
<br />
==== View ====<br />
<br />
Other references to ''owned'' data are called ''views''. Views must not survive the end of the lifetime of the owner<br />
of the data. A view v<sub>2</sub> may be taken of another view v<sub>1</sub>, and the lifetime of v<sub>2</sub> must be subset of the<br />
lifetime of v<sub>1</sub>.<br />
Views may also be transitive or head.<br />
<br />
=== Scope Fundamentals ===<br />
<br />
The purpose of <tt>scope</tt> is to provide a means for ensuring the lifetime of a viewer is a subset of the lifetime of the viewee.<br />
<br />
<tt>scope</tt> is a storage class, and affects declarations. It is not a type constructor.<br />
There is no change to existing [http://dlang.org/attribute#scope <tt>scope</tt> grammar]. It fits in the grammar as a storage class.<br />
<br />
Scope affects:<br />
<br />
* local variables allocated on the stack<br />
* function parameters<br />
* non-static member functions (applying to the <tt>this</tt>)<br />
* delegates (applying to the <tt>this</tt>)<br />
* return value of functions<br />
<br />
It is ignored for other declarations. It is ignored for declarations which are not views.<br />
<br />
<syntaxhighlight lang="D"><br />
scope enum e = 3; // scope is ignored for enums<br />
scope int i; // scope is ignored because integers are not references and so are not views<br />
</syntaxhighlight><br />
<br />
Scope affects variables according to these rules:<br />
<br />
# Scope variables can only be assigned values that have lifetimes that are a superset of the variable's lifetime.<br />
# Scope variables can only be assigned to scope variables with a lifetime that is a subset.<br />
# A variable is inferred to be scope if it is initialized with a view that has a non-&infin; lifetime.<br />
# A scope variable cannot be initialized with the address of a scoped variable.<br />
# A scope ref variable can be initialized with another scope ref variable - scope ref is idempotent.<br />
<br />
<br />
Basic operation:<br />
<br />
<syntaxhighlight lang="D"><br />
int global_var;<br />
int* global_ptr;<br />
<br />
void bar(scope int* input);<br />
<br />
void foo() {<br />
scope int* a;<br />
a = &global_var; // Ok, `global_var` has a greater lifetime than `a`<br />
scope b = &global_var; // Ok, type deduction<br />
int c;<br />
<br />
if(...) {<br />
scope x = a; // Ok, copy of reference,`x` has shorter lifetime than `a`<br />
scope y = &c; // Ok, lifetime(y) < lifetime(& c)<br />
int z;<br />
b = &z; // Error, `b` will outlive `z`<br />
int* d = a; // Ok: d is inferred to be `scope`<br />
}<br />
<br />
bar(a); // Ok, scoped pointer is passed to scoped parameter<br />
bar(&c); // Ok, lifetime(parameter input) < lifetime(c)<br />
int* e;<br />
e = &c; // Error, lifetime(e's view) is &infin; and is greater than lifetime(c)<br />
a = e; // Ok, lifetime(a) < lifetime(e)<br />
scope int** f = &a; // Error, rule 5<br />
scope int** h = &e; // Ok<br />
int* j = *h; // Ok, scope is not transitive<br />
}<br />
<br />
void abc() {<br />
scope int* a;<br />
int* b;<br />
scope ref int* c = a; // Error, rule 5<br />
scope ref int* d = b; // Ok<br />
int* i = a; // Ok, scope is inferred for i<br />
global_ptr = d; // Error, lifetime(d) < lifetime(global_ptr)<br />
global_ptr = i; // Error, lifetime(i) < lifetime(global_ptr)<br />
int* j; // Ok, scope is inferred for i<br />
global_ptr = j; // Ok, j is not scope<br />
}<br />
</syntaxhighlight><br />
<br />
=== Return Statement ===<br />
<br />
A view annotated with <tt>scope</tt> cannot be returned from a function.<br />
<br />
<syntaxhighlight lang="D"><br />
class C { ... }<br />
scope C c;<br />
return c; // Error<br />
<br />
scope int i;<br />
return i; // Ok, i is not a view<br />
<br />
scope int* p;<br />
return p; // Error<br />
return p+1; // Error, nice try!<br />
return &*p; // Error, won't work either<br />
<br />
ref int func(scope ref int r, scope out int s)<br />
{<br />
return r; // Error<br />
return s; // Error, 'out' is treated like 'ref'<br />
}<br />
</syntaxhighlight><br />
<br />
=== Functions ===<br />
<br />
==== Inference ====<br />
<br />
Scope is inferred for function parameters if not specified, under the same circumstances as <tt>pure</tt>, <tt>nothrow</tt>, <tt>@nogc</tt><br />
and safety are inferred.<br />
<br />
==== Overloading ====<br />
<br />
Scope does not affect overloading. If it did, then whether a variable was scope or not would affect the code path, making<br />
scope inference impractical. It also makes turning scope checking on/off impractical.<br />
<br />
<syntaxhighlight lang="D"><br />
T func(scope ref T);<br />
T func(ref T);<br />
<br />
T t; func(t); // Error, ambiguous<br />
scope T u; func(u); // Error, ambiguous<br />
</syntaxhighlight><br />
<br />
<br />
==== Implicit Conversion of Function Pointers and Delegates ====<br />
<br />
<tt>scope</tt> can be added to parameters, but not removed.<br />
<br />
<syntaxhighlight lang="D"><br />
alias int function(ref T) fp_t;<br />
alias int function(scope ref T) fps_t;<br />
<br />
int foo(ref T);<br />
int bar(scope ref T);<br />
<br />
fp_t fp = &bar; // Ok, scope behavior is subset of non-scope<br />
fps_t fp = &foo; // Error, fps_t demands scope behavior<br />
</syntaxhighlight><br />
<br />
==== Inheritance ====<br />
<br />
Overriding functions inherit any <tt>scope</tt> annotations from their antecedents.<br />
Scope is covariant, meaning it can be added to overriding functions.<br />
<br />
<syntaxhighlight lang="D"><br />
class C<br />
{<br />
int foo(ref T);<br />
int bar(scope ref T);<br />
}<br />
<br />
class D : C<br />
{<br />
override int foo(scope ref T); // Ok, can add scope<br />
override int bar(ref T); // Error, cannot remove scope<br />
}<br />
</syntaxhighlight><br />
<br />
==== Mangling ====<br />
<br />
Scope will require additional mangling, as it affects the interface of the function.<br />
In cases where scope is ignored, it does not contribute to the mangling.<br />
Scope parameters will be mangled with ???.<br />
<br />
==== Nested Functions ====<br />
<br />
Nested functions have more objects available than just their arguments:<br />
<br />
<syntaxhighlight lang="D"><br />
ref T foo() {<br />
T t;<br />
ref T func() { return t; }<br />
return func(); // disallowed<br />
}<br />
</syntaxhighlight><br />
<br />
Nested functions are analyzed as if each variable accessed outside of its scope was passed as a ref parameter.<br />
All parameters have scope inferred from how they are used in the function body.<br />
<br />
<br />
=== Ref ===<br />
<br />
==== Escaping via Return ====<br />
<br />
The simple cases of this are disallowed:<br />
<br />
<syntaxhighlight lang="D"><br />
T* func(T t) {<br />
T u;<br />
return &t; // Error: escaping reference to local t<br />
return &u; // Error: escaping reference to local u<br />
}<br />
</syntaxhighlight><br />
<br />
But are easily circumvented:<br />
<br />
<syntaxhighlight lang="D"><br />
T* func(T t) {<br />
T* p = &t;<br />
return p; // no error detected<br />
}<br />
</syntaxhighlight><br />
<br />
@safe currently deals with this by preventing taking the address of a local:<br />
<br />
<syntaxhighlight lang="D"><br />
T* func(T t) @safe {<br />
T* p = &t; // Error: cannot take address of parameter t in @safe function func<br />
return p;<br />
}<br />
</syntaxhighlight><br />
<br />
This is restrictive. The <tt>ref</tt> storage class was introduced which<br />
defines a special purpose pointer. <tt>ref</tt> can only appear in certain contexts,<br />
in particular function parameters and returns, only applies to declarations,<br />
cannot be stored, and cannot be incremented.<br />
<br />
<syntaxhighlight lang="D"><br />
ref T func(T t) @safe {<br />
return t; // Error: escaping reference to local variable t<br />
}<br />
</syntaxhighlight><br />
<br />
Ref can be passed down to functions:<br />
<br />
<syntaxhighlight lang="D"><br />
void func(ref T t) @safe;<br />
void bar(ref T t) @safe {<br />
func(t); // ok<br />
}<br />
</syntaxhighlight><br />
<br />
But the following idiom is far too useful to be disallowed:<br />
<br />
<syntaxhighlight lang="D"><br />
ref T func(ref T t) {<br />
return t; // ok<br />
}<br />
</syntaxhighlight><br />
<br />
And if it is misused it can result in stack corruption:<br />
<br />
<syntaxhighlight lang="D"><br />
ref T foo() {<br />
T t;<br />
return func(t); // currently, no error detected, despite returning pointer to t<br />
}<br />
</syntaxhighlight><br />
<br />
The:<br />
<br />
<syntaxhighlight lang="D"><br />
return func(t);<br />
</syntaxhighlight><br />
<br />
case is detected by all of the following conditions being true:<br />
<br />
<br />
* foo() returns by reference<br />
* func() returns by reference<br />
* func() has one or more parameters that are by reference<br />
* 1 or more of the arguments to those parameters are stack objects local to foo()<br />
* Those arguments can be @safe-ly converted from the parameter to the return type.<br />
For example, if the return type is larger than the parameter type, the return type<br />
cannot be a reference to the argument. If the return type is a pointer, and the<br />
parameter type is a size_t, it cannot be a reference to the argument. The larger<br />
a list of these cases can be made, the more code will pass @safe checks without requiring<br />
further annotation.<br />
<br />
==== Scope Ref ====<br />
<br />
The above solution is correct, but a bit restrictive. After all, func(t, u) could be returning<br />
a reference to non-local u, not local t, and so should work. To fix this, introduce the concept<br />
of <tt>scope ref</tt>:<br />
<br />
<syntaxhighlight lang="D"><br />
ref T func(scope ref T t, ref T u) {<br />
return t; // Error: escaping scope ref t<br />
return u; // ok<br />
}<br />
</syntaxhighlight><br />
<br />
Scope means that the ref is guaranteed not to escape.<br />
<br />
<syntaxhighlight lang="D"><br />
T u;<br />
ref T foo() @safe {<br />
T t;<br />
return func(t, u); // Ok, u is not local<br />
return func(u, t); // Error: escaping scope ref t<br />
}<br />
</syntaxhighlight><br />
<br />
This minimizes the number of <tt>scope</tt> annotations required.<br />
<br />
==== Scope Function Returns ====<br />
<br />
<tt>scope</tt> can be applied to function return values (even though it is not a type constructor).<br />
It must be applied to the left of the declaration, in the same way <tt>ref</tt> is:<br />
<br />
<br />
<syntaxhighlight lang="D"><br />
int* foo() scope; // applies to 'this' reference<br />
scope: int* foo(); // applies to 'this' reference<br />
scope { int* foo(); } // applies to 'this' reference<br />
scope int* foo(); // applies to return value<br />
</syntaxhighlight><br />
<br />
The lifetime of a scope return value is the lifetime of an rvalue. It may not be copied in a way that extends its life.<br />
<br />
<syntaxhighlight lang="D"><br />
int* bar(scope int*);<br />
scope int* foo();<br />
...<br />
return foo(); // Error, lifetime(return) > lifetime(foo())<br />
int* p = foo(); // Error, lifetime(p) is &infin;<br />
bar(foo()); // Ok, lifetime(foo()) > lifetime(bar())<br />
scope int* q = foo(); // error, lifetime(q) > lifetime(rvalue)<br />
</syntaxhighlight><br />
<br />
This enables scope return values to be safely chained from function to function; in particular<br />
it also allows a ref counted struct to safely expose a reference to its wrapped type.<br />
<br />
==== Out Parameters ====<br />
<br />
<tt>out</tt> parameters are treated like <tt>ref</tt> parameters when <tt>scope</tt> is applied.<br />
<br />
=== Expressions ===<br />
<br />
The ''lifetime'' of an expression is either &infin; or the lifetime of a single variable. Which it is can be statically<br />
deduced by looking at the type and AST of the expression.<br />
<br />
The root cases are:<br />
<br />
<table border=1 cellpadding=4 cellspacing=0><br />
<tr><th class="donthyphenate">'''root case'''</th><th class="donthyphenate">'''lifetime'''</th></tr><br />
<tr><td>address of variable v</td><td>lifetime(v)</td></tr><br />
<tr><td>v containing value with references</td><td>lifetime(v)</td></tr><br />
<tr><td>otherwise</td><td>&infin;</td></tr><br />
</table><br />
<br />
<br />
More complex expressions can be reduced to be one of the root cases:<br />
<br />
<table border=1 cellpadding=4 cellspacing=0><br />
<tr><th class="donthyphenate">'''expression'''</th><th class="donthyphenate">'''lifetime'''</th></tr><br />
<tr><td><tt>&amp;(*e)</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>*(&e + integer)</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>*((e1? &amp; e2 : &e3) + integer)</tt></td><td>min(lifetime(e2), lifetime(e3))</td></tr><br />
<tr><td><tt>*e</tt></td><td>&infin;</td></tr><br />
<tr><td><tt>e1,e2</tt></td><td>lifetime(e2)</td></tr><br />
<tr><td><tt>e1 = e2</tt></td><td>lifetime(e1)</td></tr><br />
<tr><td><tt>e1 op= e2</tt></td><td>lifetime(e1)</td></tr><br />
<tr><td><tt>e1 ? e2 : e3</tt></td><td>min(lifetime(e2), lifetime(e3))</td></tr><br />
<tr><td><tt>ptr + integer</tt></td><td>lifetime(ptr)</td></tr><br />
<tr><td><tt>e1 op e2</tt></td><td>min(lifetime(e1), lifetime(e2))</td></tr><br />
<tr><td><tt>op e</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>e++</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>e--</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>cast(type) e</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>new</tt></td><td>&infin;</td></tr><br />
<tr><td><tt>e.field</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>(*e).field</tt></td><td>lifetime(*e)</td></tr><br />
<tr><td><tt>e.func(args)</tt></td><td>min(lifetime(e, args), &infin;)</td></tr><br />
<tr><td><tt>func(args)</tt></td><td>min(lifetime(non-scope-ref args), &infin;)</td></tr><br />
<tr><td><tt>e[]</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>e[i..j]</tt></td><td>lifetime(e)</td></tr><br />
<tr><td><tt>e[i]</tt></td><td>lifetime(*e)</td></tr><br />
<tr><td>''ArrayLiteral''</td><td>min(lifetime(args))</td></tr><br />
<tr><td>''ArrayLiteral[constant]''</td><td>lifetime(ArrayLiteral[constant])</td></tr><br />
</table><br />
<br />
=== Classes ===<br />
<br />
Scope class semantics are equivalent to a pointer to a struct.<br />
<br />
=== Static Arrays ===<br />
<br />
Scope static array semantics are equivalent to a scope struct:<br />
<br />
<syntaxhighlight lang="D"><br />
T[3] a;<br />
struct A { T t0, t1, t2; } A a;<br />
</syntaxhighlight><br />
<br />
=== @safe ===<br />
<br />
Errors for scope violations are only reported in @safe code.<br />
<br />
=== Breaking Existing Code ===<br />
<br />
Some code will no longer work. Although inference will take care of a lot of cases,<br />
there are still some that will fail.<br />
<br />
<syntaxhighlight lang="D"><br />
int i,j;<br />
int* p = &i; // Ok, scope is inferred for p<br />
int* q;<br />
q = &i; // Error: too late to infer scope for q<br />
</syntaxhighlight><br />
<br />
Currently, <tt>scope</tt> is ignored except that a new class use to initialize a scope variable allocates the class<br />
instance on the stack. Fortunately, this can work with this new proposal, with an optimization that recognizes<br />
that if a new class is unique, and assigned to a scope variable, then that instance can be placed on the stack.<br />
<br />
=== Implementation Plan ===<br />
<br />
Turning this on may cause significant breakage, and may also be found to be an unworkable design. Therefore, implementation stages will be:<br />
<br />
* enable new behavior with a compiler switch <tt>-scope</tt><br />
* remove <tt>-scope</tt>, issue warning when errors are detected<br />
* replace warnings with deprecation messages<br />
* replace deprecations with errors</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=3783Differences With TDPL2014-02-27T15:52:35Z<p>NickTreleaven: /* IFTI now uses the tail-const type of arrays and pointers */ - add link</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
<br />
=== Attribute Inference for Templates and Function Literals ===<br />
http://dlang.org/function.html#function-attribute-inference<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
For example code, see:<br />
http://forum.dlang.org/post/mfjmysleuwfohoxcslpf@forum.dlang.org<br />
<br />
== Unimplemented Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet.<br />
<br />
=== SafeD ===<br />
<br />
@safe (and therefore SafeD) isn't fully implemented. So, it doesn't <br />
necessarily work quite like it's supposed to yet.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=3780Differences With TDPL2014-02-27T15:42:43Z<p>NickTreleaven: link to attribute inference docs</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
<br />
=== Attribute Inference for Templates and Function Literals ===<br />
http://dlang.org/function.html#function-attribute-inference<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
<br />
== Unimplemented Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet.<br />
<br />
=== SafeD ===<br />
<br />
@safe (and therefore SafeD) isn't fully implemented. So, it doesn't <br />
necessarily work quite like it's supposed to yet.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=3779Differences With TDPL2014-02-27T15:38:18Z<p>NickTreleaven: add link to purity article</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
http://klickverbot.at/blog/2012/05/purity-in-d/<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
<br />
=== Attribute Inference for Templates and Delegates ===<br />
<br />
(or at least delegate literals - I'm not sure exactly when delegates get their attributes inferred)<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
<br />
== Unimplemented Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet.<br />
<br />
=== SafeD ===<br />
<br />
@safe (and therefore SafeD) isn't fully implemented. So, it doesn't <br />
necessarily work quite like it's supposed to yet.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Differences_With_TDPL&diff=3778Differences With TDPL2014-02-27T15:32:04Z<p>NickTreleaven: add lambda syntax link, add new alias syntax subsection</p>
<hr />
<div>The following is a list of differences between D2 and The D Programming Language book by Andrei Alexandrescu.<br />
<br />
These need to be verified. This list was simply gathered from a [http://forum.dlang.org/post/mailman.647.1327135415.16222.digitalmars-d-learn@puremagic.com| post by Jonathan M. Davis] on the NG to get this page started.<br />
<br />
== New Features ==<br />
<br />
=== Weak vs Strong Purity ===<br />
<br />
=== New Lambda Syntax ===<br />
http://dlang.org/expression.html#Lambda<br />
<br />
=== New Alias Syntax, Alias Templates ===<br />
http://dlang.org/declaration.html#AliasDeclaration<br />
<br />
=== Attribute Inference for Templates and Delegates ===<br />
<br />
(or at least delegate literals - I'm not sure exactly when delegates get their attributes inferred)<br />
<br />
=== IFTI now uses the tail-const type of arrays and pointers ===<br />
<br />
== Unimplemented Features ==<br />
<br />
=== Multiple alias this ===<br />
<br />
You can only have one subtyping member currently.<br />
<br />
=== Shared ===<br />
<br />
Not all of shared's guarantees are implemented yet.<br />
<br />
=== SafeD ===<br />
<br />
@safe (and therefore SafeD) isn't fully implemented. So, it doesn't <br />
necessarily work quite like it's supposed to yet.<br />
<br />
== Differences ==<br />
<br />
=== Overriding private methods ===<br />
<br />
According to TDPL, you can override private, but right now only public and <br />
protected functions are virtual. I'm not sure that it's 100% clear whether the <br />
compiler will be changed to match or whether TDPL is going to have to be <br />
changed. You can look at http://d.puremagic.com/issues/show_bug.cgi?id=4542 <br />
for details.</div>NickTreleavenhttps://wiki.dlang.org/?title=Review_Queue&diff=2732Review Queue2013-07-27T11:33:01Z<p>NickTreleaven: change std.stream to std.io, add link</p>
<hr />
<div>This is the review queue of pending packages to get into the D Standard Library ([[Phobos]]). The review process is explained [[Review/Process|here]].<br />
<br />
If you want a project to put on this list, please look at the [[wish list]].<br />
<br />
== Current Review Queue ==<br />
<br />
{| class="wikitable sortable" border="1"<br />
|-<br />
! scope="col" | Package<br />
! scope="col" | Champion<br />
! scope="col" class="unsortable" | Code<br />
! scope="col" class="unsortable" | Documentation<br />
! scope="col" class="unsortable" | Other<br />
! scope="col" | Status<br />
|-<br />
| std.serialize<br />
|| Jacob Carlborg<br />
|| [https://github.com/jacob-carlborg/phobos/tree/serialization Code]<br />
|| [https://dl.dropboxusercontent.com/u/18386187/docs/std.serialization/index.html Docs] <br />
|| [https://github.com/jacob-carlborg/orange/wiki/_pages Examples]<br />
|| <font color=darkorange>Ready for Review</font><br />
|-<br />
| std.d.lexer<br />
|| Brian Schott<br />
|| [https://github.com/Hackerpilot/Dscanner/blob/range-based-lexer/std/d/lexer.d Code]<br />
|| [http://hackerpilot.github.io/experimental/std_lexer/phobos/lexer.html Docs]<br />
||<br />
|| <font color=darkorange>Ready for review</font><br />
|-<br />
| std.compression.lz77<br />
|| Walter Bright<br />
|| [https://github.com/D-Programming-Language/phobos/pull/1335 Code]<br />
|| <br />
|| [http://forum.dlang.org/post/koqrq8$h4b$1@digitalmars.com Discussion]<br />
|| <font color=darkorange>Ready for review</font><br />
|-<br />
| std.idioms<br />
|| Idan Arye<br />
|| [https://github.com/D-Programming-Language/phobos/pull/1294 Code]<br />
|| [http://someboddy.github.io/phobos/ddocs/for-idioms/idioms.html Docs]<br />
|| [http://forum.dlang.org/post/fofbrlqruxbevnxchxdp@forum.dlang.org Discussion Thread]<br />
|| <font color=darkorange>Ready for review</font><br />
|-<br />
| std.decimal<br />
|| Paul D. Anderson<br />
|| [https://github.com/andersonpd/decimal Code]<br />
|| [https://github.com/andersonpd/decimal/wiki Docs] <br />
|| [http://www.speleotrove.com/decimal/decarith.pdf Specification]<br />
|| <font color=darkorange>Ready for comments</font><br />
|-<br />
| std.xml2<br />
|| Michael Rynn<br />
|| [https://launchpad.net/d2-xml Code]<br />
|| [http://dsource.org/projects/xmlp Docs] <br />
||<br />
|| <font color=darkorange>Ready for comments</font><br />
|-<br />
| std.signal<br />
|| Robert Klotzner<br />
|| [https://github.com/phobos-x/phobosx/blob/master/source/phobosx/signal.d Code]<br />
|| [https://vhios.dyndns.org/signal.html Docs]<br />
|| Replacement for std.signals<br />
|| <font color=darkorange>Ready for review</font><br />
|-<br />
| std.log<br />
|| Jose Armando Garcia<br />
|| [https://github.com/D-Programming-Language/phobos/pull/432/files Code]<br />
|| [http://jsancio.github.com/phobos/phobos/std_log.html Docs] <br />
|| [http://forum.dlang.org/post/jhbbfd$1tmk$1@digitalmars.com Review thread]<br />
|| <font color=black>On hold</font><br />
|-<br />
| std.benchmark<br />
|| Andrei Alexandrecu<br />
|| [https://github.com/D-Programming-Language/phobos/pull/529 Code]<br />
|| [http://erdani.com/d/web/phobos-prerelease/std_benchmark.html Docs] <br />
|| <br />
|| <font color=black>Work in progress</font><br />
|-<br />
| std.io<br />
|| Steven Schveighoffer<br />
|| [https://github.com/schveiguy/phobos/blob/new-io/std/io.d Code]<br />
|| <br />
|| <br />
|| <font color=black>Work in progress</font><br />
|}<br />
<br />
== Previously Reviewed ==<br />
<br />
{| class="wikitable sortable" border="1"<br />
|-<br />
! scope="col" | Date<br />
! scope="col" | Module<br />
! scope="col" | Description<br />
! scope="col" | Author<br />
! scope="col" | Accepted<br />
! scope="col" | Votes (yes/no)<br />
! scope="col" | Review Manager<br />
! scope="col" | Date included in Phobos<br />
! scope="col" | Commit<br />
|-<br />
| 2013-05-27<br />
|| std.uni<br />
|| More complete API<br />
|| Dmitry Olshansky<br />
|bgcolor=limegreen| Yes<br />
|| 15/0<br />
|| Jesse Phillips<br />
|| --<br />
|| --<br />
|-<br />
| 2013-04-20<br />
|| std.process<br />
|| Revamped API<br />
|| Lars T. Kyllingstad / Steven Schveighoffer<br />
|bgcolor=limegreen| Yes<br />
|| 18/0<br />
|| Jesse Phillips<br />
|| 2013-05-07<br />
|| http://goo.gl/LJhQy<br />
|-<br />
| 2012-08-29<br />
|| std.digest<br />
|| Digests (SHA; CRC)<br />
|| Johannes Pfau<br />
|bgcolor=limegreen| Yes<br />
|| 6/1<br />
|| Dmitry Olshansky<br />
|| 2012-09-16<br />
|| http://goo.gl/ibqpA<br />
|-<br />
| 2012-06-27<br />
|| std.uuid<br />
|| UUIDs<br />
|| Johannes Pfau<br />
|bgcolor=limegreen| Yes<br />
|| 10/0<br />
|| Dmitry Olshansky<br />
|| 2012-07-02<br />
|| http://goo.gl/QNmRy<br />
|-<br />
| 2012-03-12<br />
|| std.log<br />
|| Logging<br />
|| José Armando García<br />
|bgcolor=gold| Suspended<br />
|| -<br />
|| David Nadlinger<br />
|| -<br />
|| -<br />
|-<br />
| 2011-12-29<br />
|| std.net.curl<br />
|| CURL wrapper<br />
|| Jonas Drewsen<br />
|bgcolor=limegreen| Yes<br />
|| 14/0<br />
|| DSimcha<br />
|| 2012-01-28<br />
|| http://goo.gl/l7Yyk<br />
|-<br />
| 2011-11-20<br />
|| std.csv<br />
|| csv handling<br />
|| Jesse Phillips<br />
|bgcolor=limegreen| Yes<br />
|| 5/1<br />
|| DSimcha<br />
|| ?<br />
|| ?<br />
|-<br />
| 2011-10-08<br />
|| std.regex<br />
|| Regular Expressions<br />
|| Dmitry Olshansky<br />
|bgcolor=limegreen| Yes<br />
|| 10/0<br />
|| Jesse Phillips<br />
|| 2011-11-06<br />
|| http://goo.gl/PcoHr<br />
|-<br />
| 2011-09-01<br />
|| std.net.curl<br />
|| CURL wrapper<br />
|| Jonas Drewsen<br />
|bgcolor=gold| Postponed<br />
|| -<br />
|| David Nadlinger<br />
|| -<br />
|| -<br />
|-<br />
| 2011-08-12<br />
|| std.path<br />
|| Path manipulation<br />
|| Lars Kyllingstad<br />
|bgcolor=limegreen| Yes<br />
|| 22/0<br />
|| DSimcha<br />
|| ?<br />
|| ?<br />
|}<br />
<br />
[[Category:Review]]<br />
[[Category:Library Development]]</div>NickTreleavenhttps://wiki.dlang.org/?title=DIP25&diff=1921DIP252013-02-06T18:21:57Z<p>NickTreleaven: s/2nd try/3rd try/, s/&example,method/&example.method/</p>
<hr />
<div>== DIP25: Sealed references ==<br />
{| class="wikitable"<br />
!Title: <br />
!''Sealed references''<br />
|-<br />
|DIP: <br />
|25<br />
|-<br />
|Version:<br />
|1<br />
|-<br />
|Status:<br />
|Draft<br />
|-<br />
|Created:<br />
|2013-02-05<br />
|-<br />
|Last Modified:<br />
|2013-02-05<br />
|-<br />
|Author:<br />
|Andrei Alexandrescu and Walter Bright<br />
|-<br />
|Links:<br />
|<br />
|}<br />
<br />
== Abstract ==<br />
<br />
D offers a number of features aimed at systems-level coding, such as unrestricted pointers, casting between integers and pointers, and the [http://dlang.org/function.html#system-functions <code>@system</code>] attribute. These means, combined with the other features of D, make it a complete and expressive language for systems-level tasks. On the other hand, economy of means should be exercised in defining such powerful but dangerous features. Most other features should offer good safety guarantees with little or no loss in efficiency or expressiveness. This proposal makes <code>ref</code> provide such a guarantee: with the proposed rules, it is impossible in safe code to have <code>ref</code> refer to a destroyed object. The restrictions introduced are not backward compatible, but disallow code that is stylistically questionable and that can be easily replaced either with equivalent and clearer code.<br />
<br />
== In a nutshell ==<br />
<br />
== Description ==<br />
<br />
Currently, D has some provisions for avoiding dangling references:<br />
<br />
<syntaxhighlight lang=D><br />
ref int fun(int x) {<br />
return x; // Error: escaping reference to local variable x <br />
}<br />
<br />
ref int gun() {<br />
int x;<br />
return x; // Error: escaping reference to local variable x <br />
}<br />
</syntaxhighlight><br />
<br />
However, this enforcement is shallow. The following code compiles and allows reads and writes through defunct stack locations, bypassing scoping and lifetime rules:<br />
<br />
<syntaxhighlight lang=D><br />
ref int id(ref int x) {<br />
return x; <br />
}<br />
<br />
ref int fun(int x) {<br />
return id(x); <br />
}<br />
<br />
ref int gun() {<br />
int x;<br />
return id(x); <br />
}<br />
</syntaxhighlight><br />
<br />
The escape pattern is obvious in this simple example with all code in sight, and may be found automatically. The problem is that generally the compiler cannot see the body of <code>id</code>. We need to devise a method for compiling such functions separately.<br />
<br />
We want to devise rules that allow us to pass objects by reference ''down'' into functions, and return references ''up'' from functions, while disallowing cases such as the above when a reference passed up ends up referring to a deallocated temporary.<br />
<br />
=== Typechecking rules ===<br />
<br />
The rules below discuss under what circumstances functions receiving and/or returning <code>ref T</code> may be called, where <code>T</code> is some arbitrary type. Let us also denote with <code>S<sub>T</sub></code> any <code>struct</code> that has a non-static member variable of type <code>T</code>.<br />
<br />
# An invocation of a function that takes a parameter of type <code>ref T</code> may pass one of the following:<br />
## An lvalue of type <code>T</code>, including function arguments, array and <code>struct</code> members;<br />
## An incoming <code>ref T</code> parameter or a member of type <code>T</code> of <code>S<sub>T</sub></code> received as <code>ref S<sub>T</sub></code><br />
## The result of a function returning <code>ref T</code>, or a member of <code>S<sub>T</sub></code> returned as <code>ref S<sub>T</sub></code>.<br />
# A function that returns a <code>ref T</code> may return one of the following:<br />
## A static lvalue of type <code>T</code>, including members of static <code>struct</code> values;<br />
## A member variable of type <code>T</code> belonging to a <code>class</code> object;<br />
## A <code>ref T</code> parameter;<br />
## A member of type <code>T</code> of <code>S<sub>T</sub></code> that has been passed as <code>ref S<sub>T</sub></code> into the function;<br />
## The invocation of a function <code>fun</code> returning <code>ref T</code> IF <code>fun</code> does NOT take any parameters of type <code>T</code> or <code>S<sub>T</sub></code>.<br />
## The invocation of a function <code>fun</code> returning <code>ref T</code> IF none of <code>fun</code>'s parameters of type <code>ref T</code> and <code>ref S</code> are bound to local variables.<br />
<br />
=== Discussion and Examples ===<br />
<br />
The rules allow unrestricted pass-down and conservatively restrict pass-up to avoid escaping values. Itemized discussion follows.<br />
<br />
1.1 Regular lvalues can be passed down:<br />
<br />
<syntaxhighlight lang=D><br />
void fun(ref T);<br />
<br />
struct S { int a; T b; }<br />
<br />
void caller(T v1, S v2) {<br />
static T v3;<br />
T v4;<br />
static S v5;<br />
S v6;<br />
<br />
// Fine: pass argument<br />
fun(v1);<br />
// Fine: pass member of argument<br />
fun(v2.b);<br />
// Fine: pass static lvalue<br />
fun(v3);<br />
// Fine: pass of stack variable<br />
fun(v4);<br />
// Fine: pass member of static struct<br />
fun(v5.b);<br />
// Fine: pass member of local struct<br />
fun(v6.b);<br />
}<br />
</syntaxhighlight><br />
<br />
1.2. This rule allows forwarding references transitively.<br />
<br />
<syntaxhighlight lang=D><br />
void fun(ref T);<br />
<br />
struct S { int a; T b; }<br />
<br />
void caller(ref T v1, ref S v2) {<br />
// Fine: pass ref argument<br />
fun(v1);<br />
// Fine: pass member of ref argument<br />
fun(v2.b);<br />
}<br />
</syntaxhighlight><br />
<br />
1.3. This rule enables passing down references obtained from other function calls.<br />
<br />
<syntaxhighlight lang=D><br />
void fun(ref T);<br />
ref T gun();<br />
struct S { int a; T b; }<br />
ref S hun();<br />
<br />
void caller() {<br />
// Fine: pass ref result<br />
fun(gun());<br />
// Fine: pass member of ref result<br />
fun(hun().b);<br />
}<br />
</syntaxhighlight><br />
<br />
2.1. Static lvalues can be returned:<br />
<br />
<syntaxhighlight lang=D><br />
struct S { int a; T b; }<br />
static T v1;<br />
static S v2;<br />
<br />
ref T caller(bool condition) {<br />
static T v3;<br />
static S v4;<br />
// Fine<br />
if (condition) return fun(v1);<br />
if (condition) return fun(v2);<br />
if (condition) return fun(v3);<br />
if (condition) return fun(v4);<br />
}<br />
</syntaxhighlight><br />
<br />
2.2.Member variables of classes can be returned because they live on the garbage-collected heap:<br />
<br />
<syntaxhighlight lang=D><br />
class C { int a; T b; }<br />
<br />
ref T caller() {<br />
auto c = new C;<br />
return c.b;<br />
}<br />
</syntaxhighlight><br />
<br />
2.3. This rule allows returning back an incoming parameter, which in turn allows implementing the <code>identity</code> function and idioms derived from it.<br />
<br />
<syntaxhighlight lang=D><br />
ref T fun(ref T v1) {<br />
return v1;<br />
}<br />
</syntaxhighlight><br />
<br />
2.4. As above, but for members of <code>structs</code>.<br />
<br />
<syntaxhighlight lang=D><br />
struct S { int a; T b; }<br />
ref T fun(ref S v1) {<br />
return v1.b;<br />
}<br />
</syntaxhighlight><br />
<br />
2.5. This allows to pass up the result of a function that has no chance at all to return a reference to a local.<br />
<br />
<syntaxhighlight lang=D><br />
// Assume T is not double or string<br />
ref T fun(double, ref string);<br />
struct S { int a; T b; }<br />
ref S gun(double, ref string);<br />
<br />
ref T caller(bool condition, ref T v1) {<br />
string s = "asd";<br />
if (condition) return fun(1, s);<br />
return gun(1, s).b;<br />
}<br />
</syntaxhighlight><br />
<br />
2.6. This is the most sophisticated rule. It allows passing up the result of a function while disallowing those cases in which the function may actually return a reference to a local.<br />
<br />
<syntaxhighlight lang=D><br />
ref T fun(T);<br />
ref T gun(ref T);<br />
struct S { int a; T b; }<br />
ref S hun(S);<br />
ref S iun(ref S);<br />
<br />
ref T caller(bool condition, ref T v1, ref S v2, T v3, S v4) {<br />
T v5;<br />
S v6;<br />
<br />
// Fine, no ref parameters<br />
if (condition) return fun(v1);<br />
if (condition) return fun(v2.b);<br />
if (condition) return fun(v3);<br />
if (condition) return fun(v4.b);<br />
if (condition) return fun(v5);<br />
if (condition) return fun(v6.b);<br />
<br />
// Fine, bound to ref parameters<br />
if (condition) return gun(v1);<br />
if (condition) return gun(v2.b);<br />
<br />
// Not fine, bound to locals<br />
// if (condition) return gun(v3);<br />
// if (condition) return gun(v4.b);<br />
// if (condition) return gun(v5);<br />
// if (condition) return gun(v6.b);<br />
<br />
// Fine, no ref at all<br />
if (condition) return hun(v2).b;<br />
if (condition) return hun(v4).b;<br />
if (condition) return hun(v6).b;<br />
<br />
// Fine, ref bound to ref argument<br />
if (condition) return iun(v2).b;<br />
<br />
// Not fine, bound to locals<br />
// if (condition) return iun(v4);<br />
// if (condition) return iun(v6);<br />
}<br />
</syntaxhighlight><br />
<br />
=== Member functions ===<br />
<br />
The rules above apply to member functions as well, considering that the <code>this</code> special parameter in a method belonging to type <code>A</code> is passed as a <code>ref A</code> parameter. This may cause problems with rvalue structs. (Currently, D allows calling a method against a struct rvalue.) Special rules concerning struct rvalues may be necessary.<br />
<br />
== Taking address ==<br />
<br />
This proposal introduces a related restriction: taking the address of the following entities shall be disallowed, even in <code>@system</code>. <br />
<br />
* Parameters (either value or <code>ref</code>)<br />
* Stack-allocated locals.<br />
* Member variables of a <code>struct</code> if the <code>struct</code> is a parameter (either value or <code>ref</code>) or stack-allocated.<br />
** Note that using a pointer to a <code>struct</code> does allow taking the address of a member.<br />
** Also note that a <code>struct</code> that is part of a <code>class</code> object also allows address taking.<br />
* The result of functions that return <code>ref</code>.<br />
<br />
This is because escaping pointers away from expressions is too dangerous and should be more explicit. The capability must still be present, otherwise very simple uses are not possible anymore. Consider:<br />
<br />
<syntaxhighlight lang=D><br />
bool parse1(ref double v) {<br />
// Use C's scanf<br />
return scanf("%f", &v) == 1; // Error: cannot take the address of v<br />
}<br />
<br />
double parse2() {<br />
// Use C's scanf, 2nd try<br />
double v;<br />
enforce(scanf("%f", &v) == 1); // Error: cannot take the address of v<br />
return v;<br />
}<br />
<br />
double parse3() {<br />
// Use C's scanf, 3rd try<br />
auto pv = new double;<br />
enforce(scanf("%f", pv) == 1); // Fine<br />
return *pv;<br />
}<br />
</syntaxhighlight><br />
<br />
That would force many variables to exist on the heap even though it's easy to figure that the code is safe since the semantics of <code>scanf</code> is understood by the programmer. To address this issue, this proposal fosters introducing a standard function with the signature:<br />
<br />
<syntaxhighlight lang=D><br />
@system T* addressOf(ref T value);<br />
</syntaxhighlight><br />
<br />
The function returns the address of <code>value</code> and can only be used in <code>@system</code> or <code>@trusted</code> code. <code>addressOf</code> itself cannot use the <code>&</code> address-of operator because it's forbidden even in <code>@system</code> code. But there are many possible implementations, including escaping into C or assembler. One possible portable implementation is:<br />
<br />
<syntaxhighlight lang=D><br />
@system T* addressOf(ref T value) {<br />
static T* id(T* p) { return p; }<br />
auto pfun = cast(T* function(ref T)) id;<br />
return *pfun(value);<br />
}<br />
</syntaxhighlight><br />
<br />
This relies on the fact that at binary level a <code>ref</code> parameter is passed as a pointer. <br />
<br />
With this function available as part of the standard library, efficient code can be written that forwards to <code>scanf</code> without the compiler knowing its semantics:<br />
<br />
<syntaxhighlight lang=D><br />
@trusted bool parse1(ref double v) {<br />
// Use C's scanf<br />
return scanf("%f", addressOf(v)) == 1; // Fine<br />
}<br />
<br />
@trusted double parse2() {<br />
// Use C's scanf, 2nd try<br />
double v;<br />
enforce(scanf("%f", addressOf(v)) == 1); // Fine<br />
return v;<br />
}<br />
</syntaxhighlight><br />
<br />
===Note: Isn't replacing <code>&</code> with <code>addressOf</code> just shuffling? How does it mark an improvement?===<br />
<br />
Forbidding use of <code>&</code> against specific objects has two positive effects. First, it eliminates by design some thorny syntactic ambiguities discussed in [[DIP23]]. In the expression <code>&fun</code> or <code>&expression.method</code>, the <code>&</code> may apply to either the function/method itself or to the value returned by the function/method (which doesn't compile if the result is an rvalue, but does and is unsafe if the result is a <code>ref</code>). Forbidding the unsafe case leaves only one meaning for <code>&</code> in this context: take the address of the function or delegate. To get the address of the result, one would write <code>addressof(fun)</code> or <code>addressof(expr.method)</code>, which has unsurprising syntax and semantics.<br />
<br />
The second beneficial effect is that <code>addressOf</code> is annotated appropriately with <code>@system</code> and as such integrates naturally with the rest of the type system without a need to ascribe special rules and exceptions to <code>&</code>.<br />
<br />
== Copyright ==<br />
This document has been placed in the Public Domain.</div>NickTreleaven