www.digitalmars.com [Home] [Search] [D]
Last update Mar 10, 2004

Modules

	Module:
		ModuleDeclaration DeclDefs
		DeclDefs

	DeclDefs:
		DeclDef
		DeclDef DeclDefs

	DeclDef:
		AttributeSpecifier
		ImportDeclaration
		EnumDeclaration
		ClassDeclaration
		InterfaceDeclaration
		AggregateDeclaration
		Declaration
		Constructor
		Destructor
		Invariant
		Unittest
		StaticConstructor
		StaticDestructor
		DebugSpecification
		VersionSpecification
		;
	
Modules have a one-to-one correspondence with source files. The module name is the file name with the path and extension stripped off.

Modules automatically provide a namespace scope for their contents. Modules superficially resemble classes, but differ in that:

Modules can be grouped together in heirarchies called packages.

Module Declaration

The ModuleDeclaration sets the name of the module and what package it belongs to. If absent, the module name is taken to be the same name (stripped of path and extension) of the source file name.
	ModuleDeclaration:
		module ModuleName ;

	ModuleName:
		Identifier
		ModuleName . Identifier
	
The Identifier preceding the rightmost are the packages that the module is in. The packages correspond to directory names in the source file path.

If present, the ModuleDeclaration appears syntactically first in the source file, and there can be only one per source file.

Example:

	module c.stdio;    // this is module stdio in the c package
	
By convention, package and module names are all lower case. This is because those names have a one-to-one correspondence with the operating system's directory and file names, and many file systems are not case sensitive. All lower case package and module names will minimize problems moving projects between dissimilar file systems.

Import Declaration

Rather than text include files, D imports symbols symbolically with the import declaration:
	ImportDeclaration:
		import ModuleNameList ;

	ModuleNameList:
		ModuleName
		ModuleName , ModuleNameList
	
The rightmost Identifier becomes the module name. The top level scope in the module is merged with the current scope.

Example:

	import std.c.stdio;  // import module stdio from the c package
	import foo, bar;     // import modules foo and bar
	

Scope and Modules

Each module forms its own namespace. When a module is imported into another module, by default all its top level declarations are available without qualification. Ambiguities are illegal, and can be resolved by explicitly qualifying the symbol with the module name.

For example, assume the following modules:

	Module foo
	int x = 1;
	int y = 2;

	Module bar
	int y = 3;
	int z = 4;
	
then:
	import foo;
	...
	q = y;		// sets q to foo.y
	
and:
	import foo;
	int y = 5;
	q = y;		// local y overrides foo.y
	
and:
	import foo;
	import bar;
	q = y;		// error: foo.y or bar.y?
	
and:
	import foo;
	import bar;
	q = bar.y;	// q set to 3
	
If the import is private, such as:
	module abc;
	private import def;
	
then def is not searched when another module imports abc.

Module Scope Operator

Sometimes, it's necessary to override the usual lexical scoping rules to access a name hidden by a local name. This is done with the global scope operator, which is a leading '.':
	int x;

	int foo(int x)
	{
	    if (y)
		return x;		// returns foo.x, not global x
	    else
		return .x;		// returns global x
	}
	
The leading '.' means look up the name at the module scope level.

Static Construction and Destruction

Static constructors are code that gets executed to initialize a module or a class before the main() function gets called. Static destructors are code that gets executed after the main() function returns, and are normally used for releasing system resources.

Order of Static Construction

The order of static initialization is implicitly determined by the import declarations in each module. Each module is assumed to depend on any imported modules being statically constructed first. Other than following that rule, there is no imposed order on executing the module static constructors.

Cycles (circular dependencies) in the import declarations are allowed as long as not both of the modules contain static constructors or static destructors. Violation of this rule will result in a runtime exception.

Order of Static Construction within a Module

Within a module, the static construction occurs in the lexical order in which they appear.

Order of Static Destruction

It is defined to be exactly the reverse order that static construction was performed in. Static destructors for individual modules will only be run if the corresponding static constructor successfully completed.

Feedback and Comments

Add feedback and comments regarding this page.
Copyright (c) 1999-2004 by Digital Mars, All Rights Reserved