Copyright © 1996, 1997 Lucent Technologies Inc. All rights reserved.

6.3 adt declarations

An adt or abstract data type contains data objects and functions that operate on them. The syntax is


adt-declaration: identifier : adt { adt-member-listopt } ; adt-member-list: adt-member adt-member-list adt-member adt-member: identifier-list : cyclicopt data-type ; identifier-list : function-type ;
After an adt-declaration, the identifier becomes the name of the type of that adt. For example, after
	Point: adt {
		x, y: int;
		add: fn (p: Point, q: Point): Point;
		eq: fn (p: Point, q: Point): int;
	};
the name Point is a type name for an adt of two integers and two functions; the fragment
	r, s: Point;
	xcoord: int;
	...
	xcoord = s.x;
	r = r.add(r, s);
makes sense. The first assignment selects one of the data members of s; the second calls one of the function members of r.

As this example indicates, adt members are accessed by mentioning an object with the adt type, a dot, and then the name of the member; the details will be discussed in §8.13 below. A special syntactic indulgence is available for functions declared within an adt: frequently such a function receives as an argument the same object used to access it (that is, the object before the dot). In the example just above, r was both the object being operated on and the first argument to the add function. If the first formal argument of a function declared in an adt is marked with the self keyword, then in any calls to the function, the adt object is implicitly passed to the function, and is not mentioned explicitly in the actual argument list at the call site. For example, in

	Rect: adt {
		min, max: Point;
		contains: fn(r: self Rect, p: Point): int;
	};

	r1: Rect;
	p1: Point;
	...
	if (r1.contains(p1)) ...
because the first argument of the contains function is declared with self, the subsequent call to it automatically passes r1 as its first argument. The contains function itself is defined elsewhere with this first argument explicit. (This mechanism is analogous to the this construct in C++ and other languages, but puts the special-casing at the declaration site and makes it explicit.)

If self is specified in the declaration of a function, it must also be specified in the definition as well. For example, contains would be defined

	Rect.contains(r: self Rect, p: Point)
	{
		. . .
	}

The adt type in Limbo does not provide control over the visibility of its individual members; if any are accessible, all are.

The cyclic modifier will be discussed in §11.1.

05/Jun/97