7.3. Method call expressions

Example 7-3. Examples:

a(5,7)
b.a(5,7)
A::a(5,7)
call_expression ==>
        [ expression .  | type_specifier :: ] ( identifier |  iter_name ) [ ( modal_list ) ]
modal_list ==>
        routine_mode expression { , routine_mode expression }

The most common expressions in Sather programs are method calls. The identifier names the method being called. The object to which the method is applied is determined by what precedes the identifier. If nothing precedes it, then the form is syntactic sugar for a call on self (e.g. 'a(5,7)' is short for 'self.a(5,7)'). If the identifier is preceded by an expression and a dot '.', then the method is called on the object returned by the expression. If identifier is preceded by a type specifier and a double colon '::', then the method is taken from the interface of the specified type with self initialized to void as described on See void expressions.

When a method call occurs, the following takes place in strict order:

  1. If it is an iterator call, and this call has not yet been evaluated since entering the enclosing loop, any 'once' arguments are evaluated, left to right.

  2. 'in' and 'inout' arguments are evaluated, left to right. The object to which the method is applied is considered an 'in' argument.

  3. The method call occurs. 'out' arguments are unassigned in the called method. It is a fatal error to use the value of an 'out' argument in the called method before it has been assigned. If the method terminates due to an uncaught exception, the following steps do not take place.

  4. An assignment to each 'out' and 'inout' argument occurs in the caller, left to right. 'out' and 'inout' arguments behave according to the syntactic sugar rules that also apply to the left side of ':=' assignments.

  5. The return value, if any, becomes available to the surrounding context.

If the method defines a return value, it must be used (i.e. the call may not be an expression_statement). Only non-private routines and iters may be called from outside a class, but all routines and iters may be called from inside a class.

Direct calls of a type's routines or iters may be made using the double colon '::' syntax. The type_specifier must specify a reference, immutable, or external class. In such calls self has the void default value described on See void expressions.

7.3.1. Modes

Method arguments each have a mode. Modes are specified by a keyword preceding argument names; if no keyword is given, the argument mode defaults to 'in'.

Table 7-1.

ModeDescription
inAll arguments are 'in' by default; there is no 'in' keyword. 'In' arguments pass a copy of the argument from the caller to the called method. With reference types, this is a copy of the reference to an object; the called method sees the same object as the caller.
outAn 'out' argument is passed from the called method to the caller when the called method returns. It is a fatal error for the called method to examine the value of the 'out' argument before assigning to it. The value of an 'out' argument may only be used after it has appeared on the left side of an assignment.
inoutAn 'inout' argument is passed to the called method and then back to the caller when the method returns. It is not passed by reference; modifications by the called method are not observed until the method returns (value-result).
onceOnly iterators may have 'once' arguments. Such arguments are evaluated exactly once, the first time the iterator is encountered in the containing loop. 'once' arguments otherwise behave as 'in' arguments.

7.3.2. Mode examples

Example 7-4. This routine swaps the values of its arguments. If the arguments were not designated 'inout', calling the routine would have no effect.

swap(inout x, inout y:T) is
   temp::=x;
   x:=y;
   y:=temp
end

Example 7-5. This iterator returns (head, tail) edges of a graph. 'out' arguments are convenient when one wants to return multiple values.

edges!(out head, out tail:V) is ... end

7.3.3. Overloading and dispatch

Sather supports routine and iterator overloading. In addition to the name, the number, types, and modes of arguments in a call and whether a return value is used all contribute to the selection of the method. The modal_list portion of a call must supply an expression corresponding to each declared argument of the method. There must exist a method with the specified name such that:

  1. for each 'in' and 'once' argument, the type of each expression is a subtype of the declared type of the corresponding argument, and

  2. for each 'out' argument, the type of each expression is a supertype of the corresponding argument, and

  3. for each 'inout' argument, the type of each expression is the exact type of the corresponding argument.

If there is more than one such method, there must be a unique one which is most specific, conforming to all others. When argument expressions have the type of a class parameter, the type constraint of that parameter is used to select the most specific method, rather than the realized type of the parameter. Overloading may not occur solely by the type of out arguments or return type; there must be at least one non-out argument of differing type between the most specific method and any others.

Sather also supports dynamic dispatch on the type of self when the expression on which the call is made has an abstract declared type. The method matching the call from the runtime type is actually executed. Because of the fundamental subtyping rule (See Every Sather variable has a declared type. The fundamental typing rule is: An object can only be held by a variable if the object's type is a subtype of the variable's type. It is not possible for a program which compiles to violate this rule (i.e. Sather is statically type-safe).), if the abstract type specifies a conforming method, so will the type of the returned object.