[back] [Abstract] [Copyright Notice] [Contents] [next]

Sather - A Language Manual - Chapter 7
Operator Redefinition


7.1 Method Names for Operators

It is possible to define operators such as + and * to work with objects of arbitrary classes. These operators are transformed into standard routine calls in the class. Thus, if a class defines the routine 'plus' you can then apply the + operator to objects from that class. For instance, the complex number class POINT could define the plus routine to mean pairwise addition

class POINT is
   readonly attr x,y:INT;
   create(x,y:INT):SAME is ... -- same as before
   plus(s:POINT):POINT is
      return #POINT(x + s.x, y + s.y);
   end;

we can now use the plus routine on two points

p1:POINT := #POINT(3,5);
p2:POINT := #POINT(4,6);
p3:POINT := p1 + p2;  --  p3 is set to the point 7,11

Most of the standard operators may be redefined; in some cases, redefining one operator such as the < operator implicitly redefines the associated >, >= and <= operators. These operators are meant to be used together in a consistent manner to indicate the mathematical notion of complete or partial ordering. They are not intended to be used as a convenient short-hand for other purposes.


7.2 Operator expressions

The following table shows how the standard operators are directly converted into routine calls.

Operator          Routine
------------------------------------
expr1 + expr2     expr1.plus(expr2)
expr1 - expr2     expr1.minus(expr2)
expr1 * expr2     expr1.times(expr2)
expr1 / expr2     expr1.div(expr2)
expr1 ^ expr2     expr1.pow(expr2)
expr1 % expr2     expr1.mod(expr2)
expr1 < expr2     expr1.is_lt(expr2)
expr1 = expr2     expr1.is_eq(expr2)
- expr            expr.negate
~ expr            expr.not

In addition to the unary and binary operators, there are additional operators that are defined in terms of a combination of the unary and binary operators

Operator         Translation
---------------------------------------
expr1 <= expr2   expr2.is_lt(expr1).not
expr1 >= expr2   expr1.is_lt(expr2).not
expr1 /= expr2   expr1.is_eq(expr2).not
expr1 > expr2    expr2.is_lt(expr1)
[14]

The form '[expression list]' is translated into a call on the routine aget. For instance,

a := [3,5];   -- Equivalent to a := aget(3,5); Used in the array class
f := arr[2];  -- Equivalent to f := arr.aget(2); Used outside the array

This is described in more detail later.

Grouping

In addition to the above mentioned operators, it is possible to group expressions using plain parentheses, which have the highest precedence.


7.2.1 Operator precedence

The precedence ordering shown below determines the grouping of the syntactic sugar forms. Symbols of the same precedence associate left to right and parentheses may be used for explicit grouping. Evaluation order obeys explicit parenthesis in all cases.

Strongest |  .  ::  []  ()
          |  ^
          |  ~   unary -
          |  *  /  %
          |  +   binary -
          |  <  <=  =  /=  >=  >
Weakest   |  and     or

Points to note

Syntactic sugar example

Here's a formula written with syntactic sugar and the calls it is textually equivalent to. It doesn't matter what the types of the variables are; the sugar ignores types.

-- Written using syntactic sugar
r := (x^2 + y^2).sqrt;

-- Written without sugar
r := (x.pow(2).plus(y.pow(2))).sqrt


7.3 Array Access Routines

Sather supports the standard array access syntax of square brackets. For instance:

a:ARRAY{INT} := |1,2,3|;
a[2] := 5;             -- Sets the third element of the array to 5
#OUT + a[0];           -- Prints out '1'
c:ARRAY2{INT} := ||1,2,3|,|4,5,6|,|7,8,9||;
#OUT + c[2,2];         -- Prints out '9'

However, the array bracket notation is not built into the array class. It is just a short hand for the routines aget and aset

a[2] := 5;   -- equivalent to a.aset(2,5);
#OUT + a[1]; -- equivalent to #OUT+a.aget(1);

Thus, classes which are not arrays can make use of the array notation as they please:

class INT is
   -- The standard integer class
   aget(i:INT):BOOL is -- returns the 'i'th bit of the integer
end;

In order for a class to actually have an array portion, it must inherit from AREF{T} (if it is a reference class) or AVAL{T} if it is a value class. The array setting notation is not as useful for immutable classes, since any modification of an immutable class must return a whole new object.


[back] [Abstract] [Copyright Notice] [Contents] [next]
Sather - A Language Manual
4 November 1999
B. Gomes, D. Stoutamire, B. Vaysman and H. Klawitter
Norbert Nemec nobbi@gnu.org