[Contents]
[Prev] [Next] [Limbo Basics] [Limbo Programming] [Language Definition]

Module qualification

A term of the form:

term -> term

denotes module qualification. The first term identifies a module: either it is a module type name, or it is an expression of module type. The second term is a constant name, type, data object, or function specified within that module's declaration. Either the module type name or an object of the module's type suffices to qualify constants and types; functions and objects directly exported by the module or contained within its adt must be qualified by an object of the module's type, initialized with load.

An example using an abridged version of an example given above:

Linear : module {
	setflags : fn (flag : int);
	TRUNCATE : con 1;
	Vector : adt {
		v : array of real;
		add : fn (v1 : self Vector, v2: Vector) : Vector;
		make : fn(v : array of real) : Vector;
	};
};

one might say:

lin := load Linear "/dis/linear.dis";
a : array of real;

v1 : lin -> Vector;
v2 : Linear -> Vector;
lin->setflags (Linear->TRUNCATE);
v1 = lin->(Linear->Vector).make(a);
v1 = lin->v1.make(a);
v1 = lin->v1.add(v1);
v1.v = nil;

Here, the declarations for v1 and v2 are equivalent; either a module type name (here, Linear) or a handle (here, lin) suffices to identify the module. In the call to setflags, a handle is required for the call itself; the type name is sufficient for the constant.

When calling a function associated with an adt of another module, it is necessary to identify both the module and the adt as well as the function. The two calls to the make function illustrate two ways of doing this. In the first,

v1 = lin->(Linear->Vector).make(a);

the module handle lin is specified first, then the type name of the Vector adt within it, and then the function. In the second call:

v1 = lin->v1.make(a);	

instead of using a type name to specify the adt, an instance of an object of the appropriate type is used instead. In the first example, the parentheses are required because the qualification operators associate to the left.

v1 = lin->Vector.make(a);						#Wrong
v1 = lin->Linear->Vector.make(a);						#Wrong

The first is wrong because the same lin can't serve as a qualifier for both the type and the call; the second is wrong because lin->Linear is meaningless.

Using import makes the code less verbose:

lin := load Linear "/dis/linear.dis";
Vector, TRUNCATE, setflags : import lin;	
a : array of real;

v1 : Vector;
v2 : Vector;
setflags (TRUNCATE);
v1 = Vector.make(a);
v1 = v1.make(a);
v1 = v1.add(v1);
v1.v = nil;


Note: You can import from either a module type or a module instance, but in the former case, you cannot use it to import functions and data objects.


[Contents]
[Prev] [Next] [Limbo Basics] [Limbo Programming] [Language Definition]

Copyright © 1998, Lucent Technologies, Inc. All rights reserved.