Overview
Expressions are almost identical to those found in C or Java. The same operator precedence rules apply:
Accessors | . ?. () [] |
Unary | - ! ~ ++ -- (cast) |
Multiplicative | * / % |
Additive | + - |
Bitwise Shift | >> << |
Elvis | ?: |
Relational | < <= > >= |
Equality | == != |
Bitwise AND | & |
Bitwise XOR | ^ |
Bitwise OR | | |
Logical AND | && |
Logical OR | || |
Ternary | ? : |
Assignment | = += -= *= /= |= ^= &= >>= <<= |
Arithmetic Operators
The following arithmetic operators may be used with numeric primitives:
Name | Operator |
---|---|
Multiplication | x * y |
Division | x / y |
Modulus (remainder) | x % y |
Addition | x + y |
Subtraction | x - y |
Negation | -x |
Prefix Increment | ++x |
Prefix Decrement | --x |
Postfix Increment | x++ |
Postfix Decrement | x-- |
The Modulus operator is only available for integer types, it may not be used with floats or doubles.
The prefix/postfix operators work just like C and Java. If using the prefix operator the result of the expression is the new value. If using the postfix operator the result is the old value:
int x = 4 // x == 4 int y = ++x // x == 5, y == 5 int z = x++ // x == 6, z == 5
Bitwise Operators
The following bitwise operators may be used with integer primitives (byte, short, int, long):
Name | Operator |
---|---|
Or | x | y |
Xor | x ^ y |
And | x & y |
Left Shift | x << y |
Right Shift | x >> y |
Not | ~x |
Logical Operators
The following logical operators may be used with booleans:
Name | Operator |
---|---|
Or | x || y |
And | x && y |
Not | !x |
Both the Or and And operators are short circuiting. If the first term of Or evaluates to true, then the second term is not evaluated. If the first term of And evaluates to false, then the second term is not evaluated.
Comparison
The following operators are used for comparison:
Name | Operator |
---|---|
Equal | x == y |
Not Equal | x != y |
Greater Than | x > y |
Greater Than or Equal | x >= y |
Less Than | x < y |
Less Than or Equal | x <= y |
Non-numeric types may only use the equality (==
and
!=
) operators. Reference types compare identity (pointer
address).
Assignment
The =
operator is used to assign the right hand side
expression to the left hand side. The left hand side must be
assignable. Assignable expressions are local variables,
fields, and array indices.
The compound assignment operators += -= *= /= |= ^= &= >>= <<=
can be used to combine an arithmetic or bitwise operator with
assignment:
int x = 5 // x == 5 x += 3 // x == 8
Assigning to Properties
If the left hand side of an assignment expression is a component property then you must use the := assignment operator instead of =. This highlights the fact that assigning a new value to a property results in more than just the storage of the new value; it also has potential side effects that may not always be visible to the user.
Note that there are no compound property assignment operators; increment, decrement, etc must be spelled out explicitly in the expression.
// Property px property int px // Non-property field ix int ix void myfunc() { // Use := when lhs is a property px := 3 // Use = when lhs is a non-property ix = px // No compound assignment operators px := px + 1 }
Casting
Sedona uses a syntax just like C or Java to perform a cast. Casts
are required when the compiler cannot perform a static type check.
For example, if you need to assign an Obj to a Component, then you
must use a cast: c = (Component)obj
. This type of cast is for
compile time checking only, at runtime it is basically a no-op like C.
Casts are also used with numeric types to perform a type conversion.
For example to convert an int into a float: f = (float)i
.
Note that unlike C and Java, upcasts such as from an int to a long are
not implicit - you must be explicitly use a cast.
Safe Navigation
Sedona supports Groovy's safe navigation operator: x?.slot
.
You can use the safe nav operator to access fields or call methods.
If the target expression of a slot access is null, then the whole expression
short circuits to evaluate to null. If the field or method returns a
primitive then it short circuits to false/zero. Using the safe nav
operator is a convenient and more efficient way than manually checking
for null:
// hard way DeviceNetwork net = null if (point != null) { Device dev = point.getDevice() if (dev != null) net = dev.getNetwork() } // easy way DeviceNetwork net = point?.getDevice()?.getNetwork()
Elvis
Sedona supports Groovy's elvis operator: lhs ?: rhs
.
If lhs evaluates to null, then the whole expression evaluates to
rhs. If lhs is non-null, then the rhs is short circuited and the
whole expression evaluates to lhs. The elvis operator is a convenient
and more efficient way to write code where you might use the
ternary operator:
// hard way name != null ? name : "unknown" // easy way name ?: "unknown"
Ternary
Sedona supports the C/Java ternary operator: c ? t : f
.
The boolean expression c
is evaluated. If true
then the ternary expression evaluates to t
, otherwise
it evaluates to f
:
bool x = true Str msg = x ? "On" : "Off" // msg == "On" x = false msg = x ? "On" : "Off" // msg == "Off"
Str Interpolation
Sedona supports string interpolation, which allows for concise
string formatting. String interpolation can be used with any method
that has one Str
parameter and returns an OutStream
.
You may use the "+"
operator to concatenate multiple
expressions to a string literal:
// using the + operator int x = 77 Sys.out.print("x=" + x) // is equivalent to this statement Sys.out.print("x=").printInt(x)
The example above illustrates why interpolation is only used
with methods that take a Str
and return an
OutStream
. The compiler doesn't actually create
a new string, rather it chains multiple print calls.
Use of the "+" operator is allowed, but the preferred mechanism
for string formatting is to embed the expressions directly into
the string literal itself using the '$'
character. You
can embed any arbitrary expression into a string literal using
the syntax "${expr}"
. If the expression is a simple
variable name or a variable name followed by a dot field access,
then you can omit the curly braces. Use the '\$'
escape sequence to print the dollar sign itself. Some examples:
// example from above Sys.out.print("x=${x}") // same but omitting the braces Sys.out.print("x=$x") // embedded expressions Sys.out.print("x=0x${Sys.hexStr(x)}")
The following types are supported with string interpolation:
Type | Print Method |
---|---|
Str | OutStream.print |
bool | OutStream.printBool |
int | OutStream.printInt |
long | OutStream.printLong |
float | OutStream.printFloat |
double | OutStream.printDouble |