Subsections

Flexible names

In the previous section, we declared mutliple names. The bounds of the multiple to which the name can refer are included in the generator. In subsequent assignments, the bounds of the new multiple to be assigned must be the same as the bounds given in the generator. In Algol 68, it is possible to declare names which can refer to a multiple of any number of elements (including none) and, at a later time, can refer to a different number of elements. They are called flexible names. Here is an identity declaration for a flexible name:

   REF FLEX[]INT fn = LOC FLEX[1:0]INT

There are several things to note about this declaration. Firstly, the mode of the name is not REF[]INT, but REF FLEX[]INT. The FLEX means that the bounds of the multiple to which the name can refer can differ from one assignment to the next. Secondly, the bounds of the name generated at the time of the declaration are [1:0]. Since the upper bound is less than the lower bound, the multiple is said to be flat; in other words, it has no elements at the time of its declaration6.6. Thirdly, FLEX is present on both sides of the identity declaration (but in the last section of this chapter we shall see a way round that).

We can now assign multiples of integers to fn:

   fn:=(1,2,3,4)

The bounds of the multiple to which fn now refers are [1:4]. Again, we can write

   fn:=(2,3,4)

Now the bounds of the multiple to which fn refers are [1:3]. We can even write

   fn:=7

in which the right-hand side will be rowed to yield a one-dimensional multiple with bounds [1:1], and

   fn:=()

giving bounds of [1:0].

In the original declaration of fn the bounds were [1:0]. The compiler will not ignore any bounds other than [1:0], but will generate a name whose initial bounds are those given. So the declaration

   REF FLEX[]INT fn1 = LOC FLEX[1:4]INT

will cause fn1 to have the bounds [1:4] instead of [1:0].

The lower bound does not have to be 1. In this example,

   REF[]INT m1 = LOC[-1:1]INT;
   FOR i FROM LWB m1 TO UPB m1 DO m1[i]:=i+3 OD;
   REF FLEX[]INT f1 = LOC FLEX[1:0]INT := m1

the bounds of f1 after the initial assignment are [-1:1].

If a flexible name is sliced or trimmed, the resulting name is called a transient name because it can only exist so long as the flexible name stays the same size. Such names have a restricted use to avoid the production of names which could refer to nothing. For example, consider the declaration and assignation

   REF FLEX[]CHAR c1 = LOC FLEX[1:0]INT;
    c1:="abcdef";

Suppose now we have the declaration

   REF[]CHAR lc1=c1[2:4]; #WRONG#

followed by this assignment:

   c1:="z";

It is clear that lc1 no longer refers to anything meaningful. Thus transient names cannot be assigned without being dereferenced, nor given identifiers, nor used as parameters for a routine (whether operator or procedure). However there is nothing to prevent them being used in an assignment. For example,

   REF FLEX[]CHAR s=LOC[1:0]CHAR:=
      "abcdefghijklmnopqrstuvwxyz";
   s[2:7]:=s[9:14]

where the name yielded by s[9:14] is immediately dereferenced. Note that the bounds of a trim are fixed even if the value trimmed is a flexible name. So the assignment

   s[2:7]:="abc"

would produce a run-time fault.


Exercises

5.10
The declaration
   REF FLEX[]CHAR s = LOC FLEX[1:0]CHAR
applies to the following: Ans[*]
(a)
What is the value of s?

(b)
what are the bounds of s?


Sian Mountbatten 2012-01-19