Fork me on GitHub

Operators

SARL supports a collection of operators. Most of them are infix operators, and several are postfix operators.

1. Assignments

The assignment operators are listed below. Local variables and fields can be assigned using the = operator. Compound assignment operators (+=, -=, *=, /=, and %=) can be used as a shorthand for the assignment of a binary expression. They work automatically when the corresponding infix operator is declared.

Operator Operator Semantic
a = b Set the variable a with the value of b.
a += b Alias to: a = a + b
a -= b Alias to: a = a - b
a *= b Alias to: a = a * b
a /= b Alias to: a = a / b
a %= b Alias to: a = a % b

Note The assignment operator is the only one operator that cannot be overridden yet. See the operator overloading section for details.

2. Arithmetic operators

The arithmetic operators are listed below and take numbers as operands. There are either unary (one operand) or binary (two operands).

Operator Function Name Operator Semantic
a + b operator_plus Add a and b.
a - b operator_minus Subtract b to a. Binary operator.
a * b operator_multiply Multiply a by b.
a / b operator_divide Divide a by b.
a % b operator_modulo Modulo of the division of a by b.
a ** b operator_power Compute the power b of a.
- a operator_minus Negate the value of a. Unary operator.
a ++ operator_plusPlus Increment a by 1, reply the value before the incrementation.
a – operator_moinsMoins Decrement a by 1, reply the value before the decrementation.

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section.

3. Comparison operators

3.1. Comparison operators on primitive types

The comparison operators on primitive types are listed below.

Operator Function Name Operator Semantic
a == b operator_equals Test if a and b are equal.
a != b operator_notEquals Test if a and b are not equal.
a === b operator_tripleEquals Test if a and b are equal.
a !== b operator_tripleNotEquals Test if a and b are not equal.
a < b operator_lessThan Test if a is lower than b (a, b cannot be boolean).
a > b operator_greaterThan Test if a is greater than b (a, b cannot be boolean).
a <= b operator_lessEqualsThan Test if a is lower than or equal to b (a, b cannot be boolean).
a >= b operator_greaterEqualsThan Test if a is greater than or equal to b (a, b cannot be boolean).
a <=> b operator_spaceship Replies a negative value if a < b, a positive value if a > b, otherwise 0.

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section](#operator-overloading).

3.2. Comparison operators on objects

The comparison operators on objects are listed below.

Operator Function Name Operator Semantic
a == b operator_equals Test if a and b are equal.
a != b operator_notEquals Test if a and b are not equal.
a === b operator_tripleEquals Test if a and b are equal.
a !== b operator_tripleNotEquals Test if a and b are not equal.
a < b operator_lessThan Test if a is lower than b (a must be Comparable).
a > b operator_greaterThan Test if a is greater than b (a must be Comparable).
a <= b operator_lessEqualsThan Test if a is lower than or equal to b (a must be Comparable).
a >= b operator_greaterEqualsThan Test if a is greater than or equal to b (a must be Comparable).
a <=> b operator_spaceship Replies a negative value if a < b, a positive value if a > b, otherwise 0.

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section](#operator-overloading).

4. Boolean Operators

The boolean operators are listed below. Each operator takes one or two boolean values as operands, and replies the boolean value resulting from the operational semantic of the operator.

Operator Function Name Operator Semantic
a || b operator_or If a then true else b.
a && b operator_and If a then b else false.
! a operator_not If a then false else true.

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section.

5. Bitwise Operators

The bit operators are listed below. The bit operators apply operations on the bits that represent a numeric value.

Operator Function Name Operator Semantic
a << b operator_doubleLessThan Shift the signed bit representation of a to the left by b units.
a >> b operator_doubleGreaterThan Shift the signed bit representation of a to the left by b units.
a <<< b operator_tripleLessThan Not supported.
a >>> b operator_tripleGreaterThan Shift the unsigned bit representation of a to the left by b units

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section.

Additional bitwise operators are available into the SARL library, but not associated to any operator:

Operator Operator Semantic
a.bitwiseAnd(b) Do a bit-per-bit AND operation.
a.bitwiseOr(b) Do a bit-per-bit OR operation.
a.bitwiseXor(b) Do a bit-per-bit XOR operation.
a.bitwiseNot Do a bit-per-bit NEGATION operation.

6. String Operators

The string operators are listed below. These operators are dedicated to strings of characters.

Operator Function Name Operator Semantic
a + b operator_plus Concatenate the string representations of a and b.

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section.

7. Number Range operators

This section presents a collection of operators that define ranges of values.

Operator Function Name Operator Semantic
a .. b operator_upTo Create a list of integer values from a (inclusive) to b (inclusive). 1..5 is the range from 1 to 5 with 1 <= x <= 5. 5..1 is the range from 5 to 1 with 5 >= x >= 1. The type of this expression is IntegerRange.
a >.. b operator_greaterThanDoubleDot Create a list of integer values from a (exclusive) to b (inclusive). 5&gt;..1 is the range from 4 to 1 with 5 > x >= 1. 1&gt;..5 is the empty range since the constraint is wrong 1 > x >= 5. See Xtext for discussion on the operational semantics of this operator. The type of this expression is ExclusiveRange.
a ..< b operator_doubleDotLessThan Create a list of integer values from a (inclusive) to b (exclusive). 1..&lt;5 is the range from 1 to 5 with 1 <= x < 5. 5..&lt;1 is the empty range since the constraint is wrong 5 <= x < 1. See Xtext for discussion on the operational semantics of this operator. The type of this expression is ExclusiveRange.

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section.

8. Collection Operators

The collection operators are listed below. These operators are dedicated to the collections (lists, sets, maps…) Most of the time, the first operand is the collection on which the operator must be applied.

Operator Function Name Operator Semantic
c += e operator_add Equivalent to: c.add(e)
c -= e operator_remove Equivalent to: c.remove(e)
c1 + c2 operator_plus Create a collection that is containing the elements of the collections c1 and c2.
m + p operator_plus Create a map of type Map<A,B> that is containing the elements of the map m and the new pair p of type Pair<A,B>.
m - p operator_moins Create a map of type Map<A,B> that is containing the elements of the map m, except the pair p of type Pair<A,B>.
a -> b operator_mappedTo Create an instance of Pair<A,B> where A and B are the types of a and b respectively.

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section.

9. Other operators

This section presents a collection of operators that are not related to the categories in the previous sections.

Operator Function Name Operator Semantic
a ?: b operator_elvis If a is not null then a else b.
a => b operator_doubleArrow Used as a ‘with’- or ‘let’-operation. It allows you to bind an object to a local scope in order to do something on it. b must be a lambda expression.
a <> b operator_diamond Not yet supported.

Each operator has an associated function name. This function contains the concrete implementation of the operational semantic of the operator. This function can be redefined as explained in the operator overloading section.

For an example of the =&gt; operator, consider the class Person with two attributes inside: firstName and lastName. The creation of an instance of Person could be done with:

new Person => [
	firstName = 'Han';
	lastName = 'Solo'
]

Note Note how the ; allows two expressions on one line.

In this example, the instance of Person is created and passed to the lambda expression. Inside this expression, the new Person instance is accessible with the it reserved pseudo-variable, which does not need to be typed out since it is the default object in lambda expression. The lambda expression replies the value of it.

10. Operator Precedence

The following table lists the precedence and associativity of SARL operators. Operators are listed top to bottom, in ascending precedence, i.e. from the lower priority to the higher priority.

Operators Associativity    
= right to left    
      left to right
&& left to right    
==, !=, ===, !== left to right    
>=, <=, <, > left to right    
instanceof not associative    
<=>, <>, .., >.., ..<, ->, =>, ?:, », «, »>, «< left to right    
+, - left to right    
*, /, % left to right    
as left to right    
** left to right    
!, - (unary), + (unrary) right to left    
++, – not associative    
feature, literal, closure, structure expressions not associative    

When parsing an expression, an operator which is listed on some row of the table above with a precedence will be bound tighter (as if by parentheses) to its arguments than any operator that is listed on a row further above it with a lower precedence.

For example, the expressions c << a == b and -p++ are parsed as (c << a) == b and -(p++), and not as c << (a == b) or (-p)++.

Operators that have the same precedence are bound to their arguments in the direction of their associativity. For example, the expression a = b = c is parsed as a = (b = c), and not as (a = b) = c because of right-to-left associativity of assignment, but a + b - c is parsed (a + b) - c and not a + (b - c) because of left-to-right associativity of addition and subtraction. Associativity specification is redundant for unary operators and is only shown for completeness: unary postfix operators always associate left-to-right. Note that the associativity is meaningful for member access operators, even though they are grouped with unary postfix operators: a.b++ is parsed (a.b)++ and not a.(b++). Operator precedence is unaffected by operator overloading.

Another example of operator precedence could be related to the extension method and the expression -125.abs. This expression means that the function abs is invoked with the value that is mentioned before the dot character as first argument. According to the precedence table above, this expression must be interpreted as -abs(125. Indeed, the feature call to the function abs has a higher precedence than the minus unary operator.

11. Operator Overloading

In SARL, it is easy to overload or re-define an existing operator.

You should define the operator mapping function (see the previous sections for a comprehensive list of them).

The following example, the addition operator [:plusop] for two Pair objects is defined. The function that is defining the operator must be named with the operator_ prefix, and have one parameter for each operand associated with the operator. In the example, the addition of two pairs 1 -> 3 and 4 -> 5. gives the pair (a,d).

def operator_plus(
			a : Pair<Integer,Integer>,
			b : Pair<Integer,Integer>) : Pair<Integer,Integer> {
	return new Pair(a.key, b.value)
}
def example {
	var x = 1 -> 3
	var y = 4 -> 5
	
	// Old-fashion-style call to the overloaded operator
	var z1 = operator_plus(x, y)
	
	// Operator-style call to the overloaded operator
	var z2 = x + y 
	
	// z1 == (1 -> 5)
	println(z1.toString)
	
	// z2 == (1 -> 5)
	println(z2.toString)
}

In addition to the overloading of the operators that are described on this page, it is possible to overload the casting operator. See details.

12. Acknowledgements

This documentation is inspired by the documentations from the Xtext and Xtend projects.

Copyright © 2014-2023 SARL.io, the Original Authors and Main Authors.

Documentation text and medias are licensed under the Creative Common CC-BY-SA-4.0; you may not use this file except in compliance with CC-BY-SA-4.0. You may obtain a copy of CC-BY-4.0.

Examples of SARL code are licensed under the Apache License, Version 2.0; you may not use this file except in compliance with the Apache License. You may obtain a copy of the Apache License.

You are free to reproduce the content of this page on copyleft websites such as Wikipedia.

Generated with the translator docs.generator 0.14.0-SNAPSHOT.