The ICI Programming Lanaguage: Contents Previous chapter

CHAPTER 10 Obsolete features and mistakes

OBSOLETE: Method Calls ###

In addition to the above ICI has a simple mechanism for calling methods -- functions contained within an object (typically a struct ) that accept that object as their first parameter. The method call mechanism is enabled via a modification to the call operator, "()", to add semantics for calling a pointer object and through the addition of a new operator, binary-@, to form a pointer object from an object and a key. ICI pointers, described below, consist of an object and a key. To indirect though the pointer the object is indexed by the key and the resulting object used as the result. This is the same operation used in dynamic dispatch in languages such as Smalltalk and Objective-C.

The call operator now accepts a pointer as its first operand (we may think of the call operator as an n-ary operator that takes a function or pointer object as its first operand and the function parameters as the remaining operands). When a pointer is "called", the key is used to index the pointer's container object and the result, which must be a function object, is called. In addition the container object within the pointer is passed as an implicit first parameter to the function (thus passing the actual object used to invoke the method to the method). Apart from the calling semantics the functions used to implemented methods are in all respects normal ICI functions.

Struct objects are typically used as the "container" for objects used with methods. The super mechanism provides the hierarchial search needed to allow class objects to be shared by multiple instances and provide a natural means of encapsulating information.

A typical way of using methods is,

/*
 * Define a "class" object representing our
 * class and containing the class methods.
 */
static MyClass = [struct

    doubleX = [func (self)
    {
        return self.x * 2;
    }]

];

...

static a;
a = struct(@MyClass);
a.x = 21;
printf("%d\n", a@doubleX());

We first define a class by using a literal struct to contain our named methods. You could also define class variables in this struct as it is shared by all instances of that class. In our class we've got a single method, doubleX, that doubles the value of an instance variable called x.

Later in the program we create an instance of a MyClass object by making a new struct object and setting its super struct to the class struct. The super is made atomic which ensures all instances share the same object and makes it read-only for them. Then we create an "instance variable" within the object by assigning 21 to a.x and finally invoke the method. We do not pass any parameters to doubleX. The call through the pointer object formed by the binary-@ operator passes "a" implicitly

event = waitfor(event...)

###waitfor has the same name as the new waitfor statement. But I doubt anybody is using this function. Can we retire it? TML

Blocks (waits) until an event indicated by any of its arguments occurs, then returns that argument. The interpretation of an event depends on the nature of each argument. A file argument is triggered when input is available on the file. A float argument waits for that many seconds to expire, an int for that many millisecond (they then return 0, not the argument given). Other interpretations are implementation dependent. Where several events occur simultaneously, the first as listed in the arguments will be returned.

Note that in some implementations some file types may always appear ready for input, despite the fact that they are not.

argc

The count of the number of elements in argv. Initially equal to nels(argv).

Mistakes

All too often in language design you realise you made an early mistake and it's too late to fix it. This is a place I can write them down. There are a lot more than are written here of course.

 

Contents Previous chapter