6.2. Support for Arrays

Arrays (and, in fact, most container classes) are realized using parametrized classes in Sather. There is language support for the main array class ARRAY{T} in the form of a literal expressions of the form
a:ARRAY{INT} := |1,2,3|;

In addition to the standard accessing function, arrays provide many operations, ranging from trivial routines that return the size of the array to routines that will sort arbitrary arrays. See the array class in the container library for more details. There are several aspects to supporting arrays:

6.2.1. Array Access

The form 'a[4]:=..' is syntactic sugar for a call of a routine named aset' with the array index expressions and the right hand side of the assignment as arguments. In the class TRIO below we have three elements which can be accessed using array notation
class TRIO is
   private attr a,b,c:FLT;

   create:SAME is
      return new
   end;

   aget(i:INT):FLT is
      case i
      when 0 then return a
      when 1 then return b
      when 2 then return c
      else raise "Bad array index!\n";
      end;
   end;

   aset(i:INT, val:FLT) is
      case i
      when 0 then a := val;
      when 1 then b := val;
      when 2 then c := val;
      end;
   end;
end;

The array notation can then be used with objects of type TRIO
trio:TRIO := #TRIO;  -- Calls TRIO::create
trio[2] := 1;
#OUT + trio[2];        -- Prints out 1

See unnamedlink for more details on the section on operator redefinition.

6.2.2. Array Classes: Including AREF and calling new();

Sather permits the user to define array classes which support an array portion whose size is determined when the array is created. An object can have an array portion by including AREF{T}.
class POLYGON is
   private include AREF{POINT}
      aget->private old_aget, aset->private old_aset;
         -- Rename aget and aset

   create(n_points:INT):SAME  is
      -- Create a new polygon with a 'n_points' points
      res:SAME := new(n_points);  -- Note that the new takes
      -- as argument of the size of the array
   end;

   aget(i:INT):POINT is
      if i > asize then raise "Not enough polygon points!" end;
      return old_aget(i);
   end;

   aset(i:INT, val:POINT) is
      if i > asize then raise "Not enough polygon points!" end;
      old_aset(i,val);
   end;
end;

Since AREF{T} already defines 'aget' and 'aset' to do the right thing, we can provide wrappers around these routines to, for instance, provide an additional warning message. The above example makes use of the POINT class from unnamedlink. We could have also used the PAIR class defined on unnamedlink. The following example uses the polygon class to define a triangle.
poly:POLYGON := #POLYGON(3);
poly[0] := #POINT(3,4);
poly[1] := #POINT(5,6);
poly[2] := #POINT(0,0);

AREF defines several useful routines:
asize:INT                        -- Returns the size of the array
aelt!:T;                         -- Yields successive array elements
aelt!(once beg:INT):T;           -- Yields elements from index 'beg'
aelt!(once beg,once num:INT):T;  -- Yields 'num' elts from index 'beg'
aelt!(once beg,once num,once step:INT):T;
   -- Yields 'num' elements, starting at index 'beg' with a 'step'
... Analgous versions of aset! ..
acopy(src:SAME);                  -- Copy what fits from 'src' to self
acopy(beg:INT,src:SAME);          -- Start copying into index 'beg'
acopy(beg:INT,num:INT,src:SAME);
   -- Copy 'num' elements into self starting at index 'beg' of self
aind!:INT;                         -- Yields successive array indices

When possible, use the above iterators since they are built-in and can be more efficient than other iterators.

6.2.3. Standard Arrays: ARRAY{T}

The class ARRAY{T} in the standard library is not a primitive data type. It is based on a built-in class AREF{T} which provides objects with an array portion. ARRAY obtains this functionality using an include, but chooses to modify the visibility of some of the methods. It also defines additional methods such a contains, sort etc. The methods aget, aset and asize are defined as private in AREF, but ARRAY redefines them to be public.
class ARRAY{T} is
   private include AREF{T}
      -- Make these public.
      aget->aget,
      aset->aset,
      asize->asize;
   ...

   contains(e:T):BOOL is ... end
   ...
end;

The array portion appears if there is an include path from the type to AREF for reference types or to AVAL for immutable types.

Array Literals

Sather provides support for directly creating arrays from literal expressions
a:ARRAY{INT} := |2,4,6,8|;
b:ARRAY{STR} := |"apple","orange"|;

.

The type is taken to be the declared type of the context in which it appears and it must be ARRAY{T} for some type T. An array creation expression may not appear

The types of each expression in the array literal must be subtypes of T. The size of the created array is equal to the number of specified expressions. The expressions in the literal are evaluated left to right and the results are assigned to successive array elements.

6.2.4. Multi-dimensional Arrays

Special support is neither present nor needed for multi-dimensional arrays. The 'aget' and 'aset' routines can take multiple arguments, thus permitting multiple indices. The library does provide ARRAY2 and ARRAY3 classes, which provide the necesary index computation. All standard array classes are addressed in row-major order. However, the MAT class is addressed in column major order for compatibility with external FORTRAN routines[1]. Multi-dimensonal array literals may be expressed by nesting of standard array literals
a:ARRAY{ARRAY{INT}} := ||1,2,3|,|3,4,5|,|5,6,7||;

[1] Efficiency in converting to FORTRAN was more important for mathematical entitites which will be used with existing mathematical libraries such as BLAS and LAPACK, most of which are in FORTRAN.