[Next] [Previous] [Up] [Top] [Contents] [Index]

2 Dynamically-Typed Core

2.3 Fields

Object state, such as instance variables and class variables, is supported in Cecil through fields and associated accessor methods. To define a mutable instance variable x for a particular object obj, the programmer can declare a field of the following form:

var field x(@obj);

This declaration allocates space for an object reference in the obj object and constructs two real methods attached to the obj object that provide the only access to the variable:

method x(v@obj) { prim rtl { <v.x> } } -- the get accessor method
method set_x(v@obj, value) { prim rtl { <v.x> := value; } } -- the set accessor method

The get accessor method returns the contents of the hidden variable. The set accessor method mutates the contents of the hidden variable to refer to a new object, and returns void. Accessor methods are specialized on the object containing the variable, thus establishing the link between the accessor methods and the object. For example, sending the x message to the obj object will find and invoke the get accessor method and return the contents of the hidden variable, thus acting like a reference to obj's x instance variable. (Section 5 describes how these accessor methods can be encapsulated within the data abstraction implementation and protected from external manipulation.)

To illustrate, the following declarations define a standard list inheritance hierarchy:

object list isa ordered_collection;
	method is_empty(l@list) { l.length = 0 }
	method prepend(x, l@list) { -- dispatch on second argument
		object isa cons { head := x, tail := l } }

object nil isa list; -- empty list
	method length(@nil) { 0 }
	method do(@nil, ) {} -- iterating over all elements of the empty list: do nothing
	method pair_do(@nil, , ) {}
	method pair_do(, @nil, ) {}
	method pair_do(@nil, @nil, ) {}

object cons isa list; -- non-empty lists
	var field head(@cons); -- defines head(@cons) and set_head(@cons, ) accessor methods
	var field tail(@cons); -- defines tail(@cons) and set_tail(@cons, ) accessor methods
	method length(c@cons) { 1 + c.tail.length }
	method do(c@cons, block) {
		eval(block, c.head); -- call block on head of list
		do(c.tail, block); } -- recur down tail of list
	method pair_do(c1@cons, c2@cons, block) {
		eval(block, c1.head, c2.head);
		pair_do(c1.tail, c2.tail, block); }

The cons object has two fields, only accessible through the automatically-generated accessor methods.

The syntax of field declarations, excluding static typing aspects and encapsulation, is as follows:

field_decl	::=	["shared"] ["var"] "field" method_name "(" formal ")"
		    {pragma} [":=" expr] ";"