Method Declaration | |||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Methods are declared as members of classes and interfaces. The declaration is similar to a declaration in the Java programming language, with the following differences:
The Java Language Specification allows a declaration for a method that returns an array to place some or all of the empty bracket pairs of the return type after the parameter list, as in
String getNames() [] {...}
As the Java Language Specification says, this feature should not be used in new code. The XL programming language does not allow the placing of bracket pairs after the parameter list, it would be confused with transformation blocks.
Generator method declarations are indicated by an asterisk after the result type. Generator methods successively yield values to their invoker, instead of returning just a single value.
Operator method declarations
are indicated by the identifier operator
, followed
by the token of one of the overloadable operators. It is a compile-time
error if an operator token follows an identifier which is not equal to
the character sequence operator
.
Instancing method declarations
are allowed in classes, they are indicated by the arrow ==>
as the first token of their body. They are useful
for the implementation of object instancing which is common in
3D computer graphics.
Generator method declarations are possible within classes and interfaces. A generator method declaration is indicated by an asterisk after the result type as in the following example:
char* chars(CharSequence s) { for (int i = 0; i < s.length(); i++) { yield s.charAt(i); } }
Generator methods successively yield values to their invoker via
the yield
-statement
(Section 15.5, “The yield
Statement”, Section 16.2.2, “Generator Method Invocations”),
in contrast to normal (non-generator) methods which return a single value
via the return
-statement. The asterisk can be seen
as meaning "zero or more values" as in regular expressions.
The body of a generator method must not contain any
return
-statement that returns a value.
The declaration of a generator method is not as difficult as it may seem:
Basically, it is syntactic sugar. A declaration of a generator method
is equivalent to the declaration of a normal method, where
its header is the header of the generator method,
plus an additional parameter c
inserted at
the beginning of the formal parameter list. The type of
c
is a consumer class in the package
de.grogra.xl.lang
: If T
is the result type of the generator method, let S
be the type affix (Section 6.1, “Type Affixes and Type Letters”) of
T
, then the consumer class is
S
Consumer. For the example, the
equivalent method header is
char chars(CharConsumer c, CharSequence s)
,
and a complete and equivalent method declaration looks as follows:
char chars(CharConsumer c, CharSequence s) { for (int i = 0; i < s.length(); i++) { c.consume(s.charAt(i)); } return 0; }
In fact, when this specification refers to the signature of a method, the signature of this equivalent method declaration has to be used in the case of a generator method declaration.
Operator method declarations are possible within
classes and interfaces. An operator method declaration is indicated
by the identifier operator
, followed
by the token (or tokens in case of []
)
of one of the overloadable operators as in the following example:
Complex operator+ (Complex b) { return new Complex(this.real + b.real, this.imag + b.imag); }
Note that regarding the lexical structure,
operator
is an identifier, not a keyword.
However, it is the only identifier for a method declaration
which is allowed to be followed by the token of an overloadable
operator. Thus, it is a compile-time
error if an operator token follows an identifier which is not equal to
the character sequence operator
.
The declaration of an operator method is equivalent to the declaration of a normal method, its name being derived from the operator by the following rules. At first, the arity of the method declaration is determined as follows: If the declared method is static, the arity is the number of its parameters. Otherwise, the arity is the number of its parameters plus one. An operator method declaration whose arity is one is called a unary method declaration, a declaration whose arity is two is called a binary method declaration.
For unary method declarations, the equivalent method name is derived as defined by the following table. If no identifier for the operator token is defined, a compile-time error occurs.
Table 11.1. Names of unary operator methods
Operator token | Derived name |
---|---|
! | operator$not |
~ | operator$com |
+ | operator$pos |
- | operator$neg |
++ | operator$inc |
-- | operator$dec |
For binary method declarations, the equivalent method name is derived as defined by the following table. If no identifier for the operator token is defined, a compile-time error occurs.
Table 11.2. Names of binary operator methods
Operator token | Derived name |
---|---|
+ | operator$add |
- | operator$sub |
* | operator$mul |
/ | operator$div |
% | operator$rem |
<< | operator$shl |
>> | operator$shr |
>>> | operator$ushr |
^ | operator$xor |
| | operator$or |
& | operator$and |
|| | operator$cor |
&& | operator$cand |
op = where
op is one of the preceding tokens | derived name of op ,
suffixed by the character sequence Assign |
** | operator$pow |
== | operator$eq |
!= | operator$neq |
> | operator$gt |
>= | operator$ge |
< | operator$lt |
<= | operator$le |
<=> | operator$cmp |
in | operator$in |
:: | operator$guard |
: | operator$range |
[] | operator$index |
++ | operator$postInc |
-- | operator$postDec |
The last parameter of binary method declarations for the operators
++
and --
must have type
int
, or a compile-time error occurs.
If the arity is greater than two and the operator tokens
are []
, the equivalent method name is
operator$index
. Any case which is not handled
by the previous definitions leads to a compile-time error.
Instancing method declarations are possible
within classes. Such a declaration provides syntactic sugar for the
implementation of object instancing, which is a common technique
in 3D computer graphics (but this specification
makes no reference to this concrete usage). An instancing method
declaration is indicated by the arrow ==>
, the
result type has to be void
.
At class level,
a declaration of an instancing method is equivalent to a declaration
of a normal (non-instancing) method, where its header is the header
of the instancing method, plus an additional parameter
s
inserted at the beginning of the
formal parameter list. The type of
s
is the type returned by the method
getInstantiationStateClass
of the current
compile-time model (Section 3.1, “Compile-Time Model”). The compile-time
model has to return a subclass of
de.grogra.xl.lang.InstantiationState
.
In fact, when this specification refers to the signature of methods, the signature of this equivalent method declaration has to be used in the case of an instancing method declaration.