| 1 |
Ddoc |
|---|
| 2 |
|
|---|
| 3 |
$(SPEC_S Modules, |
|---|
| 4 |
|
|---|
| 5 |
$(GRAMMAR |
|---|
| 6 |
$(GNAME Module): |
|---|
| 7 |
$(GLINK ModuleDeclaration) $(GLINK DeclDefs) |
|---|
| 8 |
$(GLINK DeclDefs) |
|---|
| 9 |
|
|---|
| 10 |
$(GNAME DeclDefs): |
|---|
| 11 |
$(GLINK DeclDef) |
|---|
| 12 |
$(GLINK DeclDef) $(I DeclDefs) |
|---|
| 13 |
|
|---|
| 14 |
$(GNAME DeclDef): |
|---|
| 15 |
$(LINK2 attribute.html#AttributeSpecifier, $(I AttributeSpecifier)) |
|---|
| 16 |
$(GLINK ImportDeclaration) |
|---|
| 17 |
$(LINK2 enum.html#EnumDeclaration, $(I EnumDeclaration)) |
|---|
| 18 |
$(LINK2 class.html#ClassDeclaration, $(I ClassDeclaration)) |
|---|
| 19 |
$(LINK2 interface.html#InterfaceDeclaration, $(I InterfaceDeclaration)) |
|---|
| 20 |
$(LINK2 struct.html#AggregateDeclaration, $(I AggregateDeclaration)) |
|---|
| 21 |
$(LINK2 declaration.html#Declaration, $(I Declaration)) |
|---|
| 22 |
$(LINK2 class.html#Constructor, $(I Constructor)) |
|---|
| 23 |
$(LINK2 class.html#Destructor, $(I Destructor)) |
|---|
| 24 |
$(LINK2 unittest.html#UnitTest, $(I UnitTest)) |
|---|
| 25 |
$(LINK2 class.html#StaticConstructor, $(I StaticConstructor)) |
|---|
| 26 |
$(LINK2 class.html#StaticDestructor, $(I StaticDestructor)) |
|---|
| 27 |
$(V2 |
|---|
| 28 |
$(LINK2 class.html#SharedStaticConstructor, $(I SharedStaticConstructor)) |
|---|
| 29 |
$(LINK2 class.html#SharedStaticDestructor, $(I SharedStaticDestructor)) |
|---|
| 30 |
) $(LINK2 version.html#ConditionalDeclaration, $(I ConditionalDeclaration)) |
|---|
| 31 |
$(LINK2 version.html#StaticAssert, $(I StaticAssert)) |
|---|
| 32 |
$(LINK2 template.html#TemplateDeclaration, $(I TemplateDeclaration)) |
|---|
| 33 |
$(LINK2 template-mixin.html#TemplateMixin, $(I TemplateMixin)) |
|---|
| 34 |
$(GLINK MixinDeclaration) |
|---|
| 35 |
$(B ;) |
|---|
| 36 |
) |
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
$(P Modules have a one-to-one correspondence with source files. |
|---|
| 40 |
The module name is the file name with the path and extension |
|---|
| 41 |
stripped off. |
|---|
| 42 |
) |
|---|
| 43 |
|
|---|
| 44 |
$(P Modules automatically provide a namespace scope for their contents. |
|---|
| 45 |
Modules superficially resemble classes, but differ in that: |
|---|
| 46 |
) |
|---|
| 47 |
|
|---|
| 48 |
$(UL |
|---|
| 49 |
$(LI There's only one instance of each module, and it is |
|---|
| 50 |
statically allocated.) |
|---|
| 51 |
|
|---|
| 52 |
$(LI There is no virtual table.) |
|---|
| 53 |
|
|---|
| 54 |
$(LI Modules do not inherit, they have no super modules, etc.) |
|---|
| 55 |
|
|---|
| 56 |
$(LI Only one module per file.) |
|---|
| 57 |
|
|---|
| 58 |
$(LI Module symbols can be imported.) |
|---|
| 59 |
|
|---|
| 60 |
$(LI Modules are always compiled at global scope, and are unaffected |
|---|
| 61 |
by surrounding attributes or other modifiers.) |
|---|
| 62 |
) |
|---|
| 63 |
|
|---|
| 64 |
$(P Modules can be grouped together in hierarchies called $(I packages). |
|---|
| 65 |
) |
|---|
| 66 |
|
|---|
| 67 |
$(P Modules offer several guarantees:) |
|---|
| 68 |
|
|---|
| 69 |
$(UL |
|---|
| 70 |
|
|---|
| 71 |
$(LI The order in which modules are imported does not affect the |
|---|
| 72 |
semantics.) |
|---|
| 73 |
|
|---|
| 74 |
$(LI The semantics of a module are not affected by what imports |
|---|
| 75 |
it.) |
|---|
| 76 |
|
|---|
| 77 |
$(LI If a module C imports modules A and B, any modifications to B |
|---|
| 78 |
will not silently change code in C that is dependent on A.) |
|---|
| 79 |
|
|---|
| 80 |
) |
|---|
| 81 |
|
|---|
| 82 |
<h3>Module Declaration</h3> |
|---|
| 83 |
|
|---|
| 84 |
$(P The $(I ModuleDeclaration) sets the name of the module and what |
|---|
| 85 |
package it belongs to. If absent, the module name is taken to be the |
|---|
| 86 |
same name (stripped of path and extension) of the source file name. |
|---|
| 87 |
) |
|---|
| 88 |
|
|---|
| 89 |
$(GRAMMAR |
|---|
| 90 |
$(GNAME ModuleDeclaration): |
|---|
| 91 |
$(B module) $(I ModuleFullyQualifiedName) $(B ;) |
|---|
| 92 |
|
|---|
| 93 |
$(GNAME ModuleFullyQualifiedName): |
|---|
| 94 |
$(I ModuleName) |
|---|
| 95 |
$(I Packages) $(B .) $(I ModuleName) |
|---|
| 96 |
|
|---|
| 97 |
$(GNAME ModuleName): |
|---|
| 98 |
$(I Identifier) |
|---|
| 99 |
|
|---|
| 100 |
$(GNAME Packages): |
|---|
| 101 |
$(I PackageName) |
|---|
| 102 |
$(I Packages) $(B .) $(I PackageName) |
|---|
| 103 |
|
|---|
| 104 |
$(GNAME PackageName): |
|---|
| 105 |
$(I Identifier) |
|---|
| 106 |
) |
|---|
| 107 |
|
|---|
| 108 |
$(P The $(I Identifiers) preceding the rightmost are the $(I Packages) |
|---|
| 109 |
that the module is in. The packages correspond to directory names in |
|---|
| 110 |
the source file path. |
|---|
| 111 |
Package names cannot be keywords, hence the corresponding |
|---|
| 112 |
directory names cannot be keywords, either. |
|---|
| 113 |
) |
|---|
| 114 |
|
|---|
| 115 |
$(P If present, the $(I ModuleDeclaration) appears syntactically first |
|---|
| 116 |
in the source file, and there can be only one per source file. |
|---|
| 117 |
) |
|---|
| 118 |
|
|---|
| 119 |
$(P Example:) |
|---|
| 120 |
|
|---|
| 121 |
--------- |
|---|
| 122 |
module c.stdio; // this is module $(B stdio) in the $(B c) package |
|---|
| 123 |
--------- |
|---|
| 124 |
|
|---|
| 125 |
$(P By convention, package and module names are all lower case. This is |
|---|
| 126 |
because those names have a one-to-one correspondence with the operating |
|---|
| 127 |
system's directory and file names, and many file systems |
|---|
| 128 |
are not case sensitive. All lower case package and module names will |
|---|
| 129 |
minimize problems moving projects between dissimilar file systems. |
|---|
| 130 |
) |
|---|
| 131 |
|
|---|
| 132 |
<h2><a name="ImportDeclaration">Import Declaration</a></h2> |
|---|
| 133 |
|
|---|
| 134 |
$(P |
|---|
| 135 |
Symbols from one module are made available in another module |
|---|
| 136 |
by using the $(I ImportDeclaration): |
|---|
| 137 |
) |
|---|
| 138 |
|
|---|
| 139 |
$(GRAMMAR |
|---|
| 140 |
$(GNAME ImportDeclaration): |
|---|
| 141 |
$(B import) $(I ImportList) $(B ;) |
|---|
| 142 |
$(B static import) $(I ImportList) $(B ;) |
|---|
| 143 |
|
|---|
| 144 |
$(GNAME ImportList): |
|---|
| 145 |
$(I Import) |
|---|
| 146 |
$(I ImportBindings) |
|---|
| 147 |
$(I Import) $(B ,) $(I ImportList) |
|---|
| 148 |
|
|---|
| 149 |
$(GNAME Import): |
|---|
| 150 |
$(I ModuleFullyQualifiedName) |
|---|
| 151 |
$(I ModuleAliasIdentifier) $(B =) $(I ModuleFullyQualifiedName) |
|---|
| 152 |
|
|---|
| 153 |
$(GNAME ImportBindings): |
|---|
| 154 |
$(I Import) $(B :) $(I ImportBindList) |
|---|
| 155 |
|
|---|
| 156 |
$(GNAME ImportBindList): |
|---|
| 157 |
$(I ImportBind) |
|---|
| 158 |
$(I ImportBind) $(B ,) $(I ImportBindList) |
|---|
| 159 |
|
|---|
| 160 |
$(GNAME ImportBind): |
|---|
| 161 |
$(I Identifier) |
|---|
| 162 |
$(I Identifier) = $(I Identifier) |
|---|
| 163 |
|
|---|
| 164 |
$(GNAME ModuleAliasIdentifier): |
|---|
| 165 |
$(I Identifier) |
|---|
| 166 |
) |
|---|
| 167 |
|
|---|
| 168 |
$(P There are several forms of the $(I ImportDeclaration), |
|---|
| 169 |
from generalized to fine-grained importing.) |
|---|
| 170 |
|
|---|
| 171 |
$(P The order in which $(I ImportDeclarations) occur has no |
|---|
| 172 |
significance.) |
|---|
| 173 |
|
|---|
| 174 |
$(P $(I ModuleFullyQualifiedName)s in the $(I ImportDeclaration) must be |
|---|
| 175 |
fully qualified |
|---|
| 176 |
with whatever packages they are in. They are not considered to |
|---|
| 177 |
be relative to the module that imports them.) |
|---|
| 178 |
|
|---|
| 179 |
<h3>Basic Imports</h3> |
|---|
| 180 |
|
|---|
| 181 |
$(P The simplest form of importing is to just list the |
|---|
| 182 |
modules being imported:) |
|---|
| 183 |
|
|---|
| 184 |
--------- |
|---|
| 185 |
import std.stdio; // import module $(B stdio) from the $(B std) package |
|---|
| 186 |
import foo, bar; // import modules $(B foo) and $(B bar) |
|---|
| 187 |
|
|---|
| 188 |
void main() |
|---|
| 189 |
{ |
|---|
| 190 |
writefln("hello!\n"); // calls std.stdio.writefln |
|---|
| 191 |
} |
|---|
| 192 |
--------- |
|---|
| 193 |
|
|---|
| 194 |
$(P How basic imports work is that first a name is searched for in the |
|---|
| 195 |
current namespace. If it is not found, then it is looked for in the |
|---|
| 196 |
imports. |
|---|
| 197 |
If it is found uniquely among the imports, then that is used. If it is |
|---|
| 198 |
in more than one import, an error occurs. |
|---|
| 199 |
) |
|---|
| 200 |
|
|---|
| 201 |
--- |
|---|
| 202 |
module A; |
|---|
| 203 |
void foo(); |
|---|
| 204 |
void bar(); |
|---|
| 205 |
--- |
|---|
| 206 |
|
|---|
| 207 |
--- |
|---|
| 208 |
module B; |
|---|
| 209 |
void foo(); |
|---|
| 210 |
void bar(); |
|---|
| 211 |
--- |
|---|
| 212 |
|
|---|
| 213 |
--- |
|---|
| 214 |
module C; |
|---|
| 215 |
import A; |
|---|
| 216 |
void foo(); |
|---|
| 217 |
void test() |
|---|
| 218 |
{ foo(); // C.foo() is called, it is found before imports are searched |
|---|
| 219 |
bar(); // A.bar() is called, since imports are searched |
|---|
| 220 |
} |
|---|
| 221 |
--- |
|---|
| 222 |
|
|---|
| 223 |
--- |
|---|
| 224 |
module D; |
|---|
| 225 |
import A; |
|---|
| 226 |
import B; |
|---|
| 227 |
void test() |
|---|
| 228 |
{ foo(); // error, A.foo() or B.foo() ? |
|---|
| 229 |
A.foo(); // ok, call A.foo() |
|---|
| 230 |
B.foo(); // ok, call B.foo() |
|---|
| 231 |
} |
|---|
| 232 |
--- |
|---|
| 233 |
|
|---|
| 234 |
--- |
|---|
| 235 |
module E; |
|---|
| 236 |
import A; |
|---|
| 237 |
import B; |
|---|
| 238 |
alias B.foo foo; |
|---|
| 239 |
void test() |
|---|
| 240 |
{ foo(); // call B.foo() |
|---|
| 241 |
A.foo(); // call A.foo() |
|---|
| 242 |
B.foo(); // call B.foo() |
|---|
| 243 |
} |
|---|
| 244 |
--- |
|---|
| 245 |
|
|---|
| 246 |
<h3>Public Imports</h3> |
|---|
| 247 |
|
|---|
| 248 |
$(P By default, imports are $(I private). This means that |
|---|
| 249 |
if module A imports module B, and module B imports module |
|---|
| 250 |
C, then C's names are not searched for. An import can |
|---|
| 251 |
be specifically declared $(I public), when it will be |
|---|
| 252 |
treated as if any imports of the module with the $(I ImportDeclaration) |
|---|
| 253 |
also import the public imported modules. |
|---|
| 254 |
) |
|---|
| 255 |
|
|---|
| 256 |
--- |
|---|
| 257 |
module A; |
|---|
| 258 |
void foo() { } |
|---|
| 259 |
--- |
|---|
| 260 |
|
|---|
| 261 |
--- |
|---|
| 262 |
module B; |
|---|
| 263 |
void bar() { } |
|---|
| 264 |
--- |
|---|
| 265 |
|
|---|
| 266 |
--- |
|---|
| 267 |
module C; |
|---|
| 268 |
import A; |
|---|
| 269 |
public import B; |
|---|
| 270 |
... |
|---|
| 271 |
foo(); // call A.foo() |
|---|
| 272 |
bar(); // calls B.bar() |
|---|
| 273 |
--- |
|---|
| 274 |
|
|---|
| 275 |
--- |
|---|
| 276 |
module D; |
|---|
| 277 |
import C; |
|---|
| 278 |
... |
|---|
| 279 |
foo(); // error, foo() is undefined |
|---|
| 280 |
bar(); // ok, calls B.bar() |
|---|
| 281 |
--- |
|---|
| 282 |
|
|---|
| 283 |
<h3>Static Imports</h3> |
|---|
| 284 |
|
|---|
| 285 |
$(P Basic imports work well for programs with relatively few modules |
|---|
| 286 |
and imports. If there are a lot of imports, name collisions |
|---|
| 287 |
can start occurring between the names in the various imported modules. |
|---|
| 288 |
One way to stop this is by using static imports. |
|---|
| 289 |
A static import requires one to use a fully qualified name |
|---|
| 290 |
to reference the module's names: |
|---|
| 291 |
) |
|---|
| 292 |
|
|---|
| 293 |
--- |
|---|
| 294 |
static import std.stdio; |
|---|
| 295 |
|
|---|
| 296 |
void main() |
|---|
| 297 |
{ |
|---|
| 298 |
writefln("hello!"); // error, writefln is undefined |
|---|
| 299 |
std.stdio.writefln("hello!"); // ok, writefln is fully qualified |
|---|
| 300 |
} |
|---|
| 301 |
--- |
|---|
| 302 |
|
|---|
| 303 |
|
|---|
| 304 |
<h3>Renamed Imports</h3> |
|---|
| 305 |
|
|---|
| 306 |
$(P A local name for an import can be given, through which |
|---|
| 307 |
all references to the module's symbols must be qualified |
|---|
| 308 |
with:) |
|---|
| 309 |
|
|---|
| 310 |
--- |
|---|
| 311 |
import io = std.stdio; |
|---|
| 312 |
|
|---|
| 313 |
void main() |
|---|
| 314 |
{ |
|---|
| 315 |
io.writefln("hello!"); // ok, calls std.stdio.writefln |
|---|
| 316 |
std.stdio.writefln("hello!"); // error, std is undefined |
|---|
| 317 |
writefln("hello!"); // error, writefln is undefined |
|---|
| 318 |
} |
|---|
| 319 |
--- |
|---|
| 320 |
|
|---|
| 321 |
$(P Renamed imports are handy when dealing with |
|---|
| 322 |
very long import names.) |
|---|
| 323 |
|
|---|
| 324 |
<h3>Selective Imports</h3> |
|---|
| 325 |
|
|---|
| 326 |
$(P Specific symbols can be exclusively imported from |
|---|
| 327 |
a module and bound into the current namespace:) |
|---|
| 328 |
|
|---|
| 329 |
--- |
|---|
| 330 |
import std.stdio : writefln, foo = writef; |
|---|
| 331 |
|
|---|
| 332 |
void main() |
|---|
| 333 |
{ |
|---|
| 334 |
std.stdio.writefln("hello!"); // error, std is undefined |
|---|
| 335 |
writefln("hello!"); // ok, writefln bound into current namespace |
|---|
| 336 |
writef("world"); // error, writef is undefined |
|---|
| 337 |
foo("world"); // ok, calls std.stdio.writef() |
|---|
| 338 |
fwritefln(stdout, "abc"); // error, fwritefln undefined |
|---|
| 339 |
} |
|---|
| 340 |
--- |
|---|
| 341 |
|
|---|
| 342 |
$(P $(B static) cannot be used with selective imports.) |
|---|
| 343 |
|
|---|
| 344 |
<h3>Renamed and Selective Imports</h3> |
|---|
| 345 |
|
|---|
| 346 |
$(P When renaming and selective importing are combined:) |
|---|
| 347 |
|
|---|
| 348 |
------------ |
|---|
| 349 |
import io = std.stdio : foo = writefln; |
|---|
| 350 |
|
|---|
| 351 |
void main() |
|---|
| 352 |
{ |
|---|
| 353 |
writefln("bar"); // error, writefln is undefined |
|---|
| 354 |
std.stdio.foo("bar"); // error, foo is bound into current namespace |
|---|
| 355 |
std.stdio.writefln("bar"); // error, std is undefined |
|---|
| 356 |
foo("bar"); // ok, foo is bound into current namespace, |
|---|
| 357 |
// FQN not required |
|---|
| 358 |
io.writefln("bar"); // ok, io=std.stdio bound the name io in |
|---|
| 359 |
// the current namespace to refer to the entire module |
|---|
| 360 |
io.foo("bar"); // error, foo is bound into current namespace, |
|---|
| 361 |
// foo is not a member of io |
|---|
| 362 |
-------------- |
|---|
| 363 |
|
|---|
| 364 |
<h3>Module Scope Operator</h3> |
|---|
| 365 |
|
|---|
| 366 |
Sometimes, it's necessary to override the usual lexical scoping rules |
|---|
| 367 |
to access a name hidden by a local name. This is done with the |
|---|
| 368 |
global scope operator, which is a leading $(SINGLEQUOTE .): |
|---|
| 369 |
|
|---|
| 370 |
--------- |
|---|
| 371 |
int x; |
|---|
| 372 |
|
|---|
| 373 |
int foo(int x) |
|---|
| 374 |
{ |
|---|
| 375 |
if (y) |
|---|
| 376 |
return x; // returns foo.x, not global x |
|---|
| 377 |
else |
|---|
| 378 |
return .x; // returns global x |
|---|
| 379 |
} |
|---|
| 380 |
--------- |
|---|
| 381 |
|
|---|
| 382 |
The leading $(SINGLEQUOTE .) means look up the name at the module scope level. |
|---|
| 383 |
|
|---|
| 384 |
<a name="staticorder"><h2>Static Construction and Destruction</h2></a> |
|---|
| 385 |
|
|---|
| 386 |
$(P Static constructors are code that gets executed to initialize |
|---|
| 387 |
a module or a class before the main() function gets called. |
|---|
| 388 |
Static destructors are code that gets executed after the main() |
|---|
| 389 |
function returns, and are normally used for releasing |
|---|
| 390 |
system resources.) |
|---|
| 391 |
|
|---|
| 392 |
$(P There can be multiple static constructors and static destructors |
|---|
| 393 |
within one module. The static constructors are run in lexical order, |
|---|
| 394 |
the static destructors are run in reverse lexical order.) |
|---|
| 395 |
|
|---|
| 396 |
$(V2 |
|---|
| 397 |
$(P Static constructors and static destructors run on thread local |
|---|
| 398 |
data, and are run whenever threads are created or destroyed.) |
|---|
| 399 |
|
|---|
| 400 |
$(P Shared static constructors and shared static destructors are run |
|---|
| 401 |
on global shared data, and constructors are run once on program startup |
|---|
| 402 |
and destructors are run once on program termination. |
|---|
| 403 |
) |
|---|
| 404 |
) |
|---|
| 405 |
|
|---|
| 406 |
<h3>Order of Static Construction</h3> |
|---|
| 407 |
|
|---|
| 408 |
$(V2 |
|---|
| 409 |
$(P Shared static constructors on all modules are run before any static |
|---|
| 410 |
constructors. |
|---|
| 411 |
) |
|---|
| 412 |
) |
|---|
| 413 |
|
|---|
| 414 |
$(P The order of static initialization is implicitly determined by |
|---|
| 415 |
the $(I import) declarations in each module. Each module is |
|---|
| 416 |
assumed to depend on any imported modules being statically |
|---|
| 417 |
constructed first. |
|---|
| 418 |
Other than following that rule, there is no imposed order |
|---|
| 419 |
on executing the module static constructors. |
|---|
| 420 |
) |
|---|
| 421 |
|
|---|
| 422 |
$(P Cycles (circular dependencies) in the import declarations are |
|---|
| 423 |
allowed as long as not both of the modules contain static constructors |
|---|
| 424 |
or static destructors. Violation of this rule will result |
|---|
| 425 |
in a runtime exception. |
|---|
| 426 |
) |
|---|
| 427 |
|
|---|
| 428 |
<h3>Order of Static Construction within a Module</h3> |
|---|
| 429 |
|
|---|
| 430 |
Within a module, the static construction occurs in the lexical |
|---|
| 431 |
order in which they appear. |
|---|
| 432 |
|
|---|
| 433 |
<h3>Order of Static Destruction</h3> |
|---|
| 434 |
|
|---|
| 435 |
$(P It is defined to be exactly the reverse order that static |
|---|
| 436 |
construction was performed in. Static destructors for individual |
|---|
| 437 |
modules will only be run if the corresponding static constructor |
|---|
| 438 |
successfully completed. |
|---|
| 439 |
) |
|---|
| 440 |
$(V2 |
|---|
| 441 |
$(P Shared static destructors are executed after static destructors. |
|---|
| 442 |
) |
|---|
| 443 |
) |
|---|
| 444 |
|
|---|
| 445 |
|
|---|
| 446 |
<h3>Order of Unit tests</h3> |
|---|
| 447 |
|
|---|
| 448 |
Unit tests are run in the lexical order in which they appear |
|---|
| 449 |
within a module. |
|---|
| 450 |
|
|---|
| 451 |
<h2>$(LNAME2 MixinDeclaration, Mixin Declaration)</h2> |
|---|
| 452 |
|
|---|
| 453 |
$(GRAMMAR |
|---|
| 454 |
$(GNAME MixinDeclaration): |
|---|
| 455 |
$(B mixin) $(B $(LPAREN)) $(ASSIGNEXPRESSION) $(B $(RPAREN)) $(B ;) |
|---|
| 456 |
) |
|---|
| 457 |
|
|---|
| 458 |
$(P The $(ASSIGNEXPRESSION) |
|---|
| 459 |
must evaluate at compile time |
|---|
| 460 |
to a constant string. |
|---|
| 461 |
The text contents of the string must be compilable as a valid |
|---|
| 462 |
$(GLINK DeclDefs), and is compiled as such. |
|---|
| 463 |
) |
|---|
| 464 |
|
|---|
| 465 |
) |
|---|
| 466 |
|
|---|
| 467 |
Macros: |
|---|
| 468 |
TITLE=Modules |
|---|
| 469 |
WIKI=Module |
|---|
| 470 |
GLINK=$(LINK2 #$0, $(I $0)) |
|---|
| 471 |
GNAME=$(LNAME2 $0, $0) |
|---|
| 472 |
FOO= |
|---|