mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-08 05:58:44 +00:00
Drops the inline callouts from the painless reference book. These callouts are incompatible with Asciidoctor and we'd very much like to switch to Asciidoctor for building this book, partially because Asciidoctor is actively developed and AsciiDoc is not, and partially because it builds the book three times faster.
1339 lines
32 KiB
Plaintext
1339 lines
32 KiB
Plaintext
[[painless-operators-numeric]]
|
|
=== Operators: Numeric
|
|
|
|
[[post-increment-operator]]
|
|
==== Post Increment
|
|
|
|
Use the `post increment operator '++'` to INCREASE the value of a numeric type
|
|
variable/field by `1`. An extra implicit cast is necessary to return the
|
|
promoted numeric type value to the original numeric type value of the
|
|
variable/field for the following types: `byte`, `short`, and `char`. If a
|
|
variable/field is read as part of an expression the value is loaded prior to the
|
|
increment.
|
|
|
|
*Errors*
|
|
|
|
* If the variable/field is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
post_increment: ( variable | field ) '++';
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[options="header",cols="<1,<1,<1"]
|
|
|====
|
|
| original | promoted | implicit
|
|
| byte | int | byte
|
|
| short | int | short
|
|
| char | int | char
|
|
| int | int |
|
|
| long | long |
|
|
| float | float |
|
|
| double | double |
|
|
| def | def |
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Post increment with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
short i = 0; <1>
|
|
i++; <2>
|
|
long j = 1; <3>
|
|
long k; <4>
|
|
k = j++; <5>
|
|
----
|
|
+
|
|
<1> declare `short i`;
|
|
store `short 0` to `i`
|
|
<2> load from `i` -> `short 0`;
|
|
promote `short 0`: result `int`;
|
|
add `int 0` and `int 1` -> `int 1`;
|
|
implicit cast `int 1` to `short 1`;
|
|
store `short 1` to `i`
|
|
<3> declare `long j`;
|
|
implicit cast `int 1` to `long 1` -> `long 1`;
|
|
store `long 1` to `j`
|
|
<4> declare `long k`;
|
|
store default `long 0` to `k`
|
|
<5> load from `j` -> `long 1`;
|
|
store `long 1` to `k`;
|
|
add `long 1` and `long 1` -> `long 2`;
|
|
store `long 2` to `j`
|
|
+
|
|
* Post increment with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 1; <1>
|
|
x++; <2>
|
|
----
|
|
+
|
|
<1> declare `def x`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` to `x`
|
|
<2> load from `x` -> `def`;
|
|
implicit cast `def` to `int 1`;
|
|
add `int 1` and `int 1` -> `int 2`;
|
|
implicit cast `int 2` to `def`;
|
|
store `def` to `x`
|
|
|
|
[[post-decrement-operator]]
|
|
==== Post Decrement
|
|
|
|
Use the `post decrement operator '--'` to DECREASE the value of a numeric type
|
|
variable/field by `1`. An extra implicit cast is necessary to return the
|
|
promoted numeric type value to the original numeric type value of the
|
|
variable/field for the following types: `byte`, `short`, and `char`. If a
|
|
variable/field is read as part of an expression the value is loaded prior to
|
|
the decrement.
|
|
|
|
*Errors*
|
|
|
|
* If the variable/field is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
post_decrement: ( variable | field ) '--';
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[options="header",cols="<1,<1,<1"]
|
|
|====
|
|
| original | promoted | implicit
|
|
| byte | int | byte
|
|
| short | int | short
|
|
| char | int | char
|
|
| int | int |
|
|
| long | long |
|
|
| float | float |
|
|
| double | double |
|
|
| def | def |
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Post decrement with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
short i = 0; <1>
|
|
i--; <2>
|
|
long j = 1; <3>
|
|
long k; <4>
|
|
k = j--; <5>
|
|
----
|
|
+
|
|
<1> declare `short i`;
|
|
store `short 0` to `i`
|
|
<2> load from `i` -> `short 0`;
|
|
promote `short 0`: result `int`;
|
|
subtract `int 1` from `int 0` -> `int -1`;
|
|
implicit cast `int -1` to `short -1`;
|
|
store `short -1` to `i`
|
|
<3> declare `long j`;
|
|
implicit cast `int 1` to `long 1` -> `long 1`;
|
|
store `long 1` to `j`
|
|
<4> declare `long k`;
|
|
store default `long 0` to `k`
|
|
<5> load from `j` -> `long 1`;
|
|
store `long 1` to `k`;
|
|
subtract `long 1` from `long 1` -> `long 0`;
|
|
store `long 0` to `j`
|
|
+
|
|
* Post decrement with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 1; <1>
|
|
x--; <2>
|
|
----
|
|
+
|
|
<1> declare `def x`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` to `x`
|
|
<2> load from `x` -> `def`;
|
|
implicit cast `def` to `int 1`;
|
|
subtract `int 1` from `int 1` -> `int 0`;
|
|
implicit cast `int 0` to `def`;
|
|
store `def` to `x`
|
|
|
|
[[pre-increment-operator]]
|
|
==== Pre Increment
|
|
|
|
Use the `pre increment operator '++'` to INCREASE the value of a numeric type
|
|
variable/field by `1`. An extra implicit cast is necessary to return the
|
|
promoted numeric type value to the original numeric type value of the
|
|
variable/field for the following types: `byte`, `short`, and `char`. If a
|
|
variable/field is read as part of an expression the value is loaded after the
|
|
increment.
|
|
|
|
*Errors*
|
|
|
|
* If the variable/field is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
pre_increment: '++' ( variable | field );
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[options="header",cols="<1,<1,<1"]
|
|
|====
|
|
| original | promoted | implicit
|
|
| byte | int | byte
|
|
| short | int | short
|
|
| char | int | char
|
|
| int | int |
|
|
| long | long |
|
|
| float | float |
|
|
| double | double |
|
|
| def | def |
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Pre increment with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
short i = 0; <1>
|
|
++i; <2>
|
|
long j = 1; <3>
|
|
long k; <4>
|
|
k = ++j; <5>
|
|
----
|
|
+
|
|
<1> declare `short i`;
|
|
store `short 0` to `i`
|
|
<2> load from `i` -> `short 0`;
|
|
promote `short 0`: result `int`;
|
|
add `int 0` and `int 1` -> `int 1`;
|
|
implicit cast `int 1` to `short 1`;
|
|
store `short 1` to `i`
|
|
<3> declare `long j`;
|
|
implicit cast `int 1` to `long 1` -> `long 1`;
|
|
store `long 1` to `j`
|
|
<4> declare `long k`;
|
|
store default `long 0` to `k`
|
|
<5> load from `j` -> `long 1`;
|
|
add `long 1` and `long 1` -> `long 2`;
|
|
store `long 2` to `j`;
|
|
store `long 2` to `k`
|
|
+
|
|
* Pre increment with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 1; <1>
|
|
++x; <2>
|
|
----
|
|
+
|
|
<1> declare `def x`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` to `x`
|
|
<2> load from `x` -> `def`;
|
|
implicit cast `def` to `int 1`;
|
|
add `int 1` and `int 1` -> `int 2`;
|
|
implicit cast `int 2` to `def`;
|
|
store `def` to `x`
|
|
|
|
[[pre-decrement-operator]]
|
|
==== Pre Decrement
|
|
|
|
Use the `pre decrement operator '--'` to DECREASE the value of a numeric type
|
|
variable/field by `1`. An extra implicit cast is necessary to return the
|
|
promoted numeric type value to the original numeric type value of the
|
|
variable/field for the following types: `byte`, `short`, and `char`. If a
|
|
variable/field is read as part of an expression the value is loaded after the
|
|
decrement.
|
|
|
|
*Errors*
|
|
|
|
* If the variable/field is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
pre_increment: '--' ( variable | field );
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[options="header",cols="<1,<1,<1"]
|
|
|====
|
|
| original | promoted | implicit
|
|
| byte | int | byte
|
|
| short | int | short
|
|
| char | int | char
|
|
| int | int |
|
|
| long | long |
|
|
| float | float |
|
|
| double | double |
|
|
| def | def |
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Pre decrement with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
short i = 0; <1>
|
|
--i; <2>
|
|
long j = 1; <3>
|
|
long k; <4>
|
|
k = --j; <5>
|
|
----
|
|
+
|
|
<1> declare `short i`;
|
|
store `short 0` to `i`
|
|
<2> load from `i` -> `short 0`;
|
|
promote `short 0`: result `int`;
|
|
subtract `int 1` from `int 0` -> `int -1`;
|
|
implicit cast `int -1` to `short -1`;
|
|
store `short -1` to `i`
|
|
<3> declare `long j`;
|
|
implicit cast `int 1` to `long 1` -> `long 1`;
|
|
store `long 1` to `j`
|
|
<4> declare `long k`;
|
|
store default `long 0` to `k`
|
|
<5> load from `j` -> `long 1`;
|
|
subtract `long 1` from `long 1` -> `long 0`;
|
|
store `long 0` to `j`
|
|
store `long 0` to `k`;
|
|
+
|
|
* Pre decrement operator with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 1; <1>
|
|
--x; <2>
|
|
----
|
|
+
|
|
<1> declare `def x`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` to `x`
|
|
<2> load from `x` -> `def`;
|
|
implicit cast `def` to `int 1`;
|
|
subtract `int 1` from `int 1` -> `int 0`;
|
|
implicit cast `int 0` to `def`;
|
|
store `def` to `x`
|
|
|
|
[[unary-positive-operator]]
|
|
==== Unary Positive
|
|
|
|
Use the `unary positive operator '+'` to the preserve the IDENTITY of a
|
|
numeric type value.
|
|
|
|
*Errors*
|
|
|
|
* If the value is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
unary_positive: '+' expression;
|
|
----
|
|
|
|
*Examples*
|
|
|
|
* Unary positive with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int x = +1; <1>
|
|
long y = +x; <2>
|
|
----
|
|
+
|
|
<1> declare `int x`;
|
|
identity `int 1` -> `int 1`;
|
|
store `int 1` to `x`
|
|
<2> declare `long y`;
|
|
load from `x` -> `int 1`;
|
|
identity `int 1` -> `int 1`;
|
|
implicit cast `int 1` to `long 1` -> `long 1`;
|
|
store `long 1` to `y`
|
|
+
|
|
* Unary positive with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def z = +1; <1>
|
|
int i = +z; <2>
|
|
----
|
|
<1> declare `def z`;
|
|
identity `int 1` -> `int 1`;
|
|
implicit cast `int 1` to `def`;
|
|
store `def` to `z`
|
|
<2> declare `int i`;
|
|
load from `z` -> `def`;
|
|
implicit cast `def` to `int 1`;
|
|
identity `int 1` -> `int 1`;
|
|
store `int 1` to `i`;
|
|
|
|
[[unary-negative-operator]]
|
|
==== Unary Negative
|
|
|
|
Use the `unary negative operator '-'` to NEGATE a numeric type value.
|
|
|
|
*Errors*
|
|
|
|
* If the value is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
unary_negative: '-' expression;
|
|
----
|
|
|
|
*Examples*
|
|
|
|
* Unary negative with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int x = -1; <1>
|
|
long y = -x; <2>
|
|
----
|
|
+
|
|
<1> declare `int x`;
|
|
negate `int 1` -> `int -1`;
|
|
store `int -1` to `x`
|
|
<2> declare `long y`;
|
|
load from `x` -> `int 1`;
|
|
negate `int -1` -> `int 1`;
|
|
implicit cast `int 1` to `long 1` -> `long 1`;
|
|
store `long 1` to `y`
|
|
+
|
|
* Unary negative with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def z = -1; <1>
|
|
int i = -z; <2>
|
|
----
|
|
<1> declare `def z`;
|
|
negate `int 1` -> `int -1`;
|
|
implicit cast `int -1` to `def`;
|
|
store `def` to `z`
|
|
<2> declare `int i`;
|
|
load from `z` -> `def`;
|
|
implicit cast `def` to `int -1`;
|
|
negate `int -1` -> `int 1`;
|
|
store `int 1` to `i`;
|
|
|
|
[[bitwise-not-operator]]
|
|
==== Bitwise Not
|
|
|
|
Use the `bitwise not operator '~'` to NOT each bit in an integer type value
|
|
where a `1-bit` is flipped to a resultant `0-bit` and a `0-bit` is flipped to a
|
|
resultant `1-bit`.
|
|
|
|
*Errors*
|
|
|
|
* If the value is a non-integer type.
|
|
|
|
*Bits*
|
|
|
|
[options="header",cols="<1,<1"]
|
|
|====
|
|
| original | result
|
|
| 1 | 0
|
|
| 0 | 1
|
|
|====
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
bitwise_not: '~' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[options="header",cols="<1,<1"]
|
|
|====
|
|
| original | promoted
|
|
| byte | int
|
|
| short | int
|
|
| char | int
|
|
| int | int
|
|
| long | long
|
|
| def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Bitwise not with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
byte b = 1; <1>
|
|
int i = ~b; <2>
|
|
long l = ~i; <3>
|
|
----
|
|
+
|
|
<1> declare `byte x`;
|
|
store `byte 1` to b
|
|
<2> declare `int i`;
|
|
load from `b` -> `byte 1`;
|
|
implicit cast `byte 1` to `int 1` -> `int 1`;
|
|
bitwise not `int 1` -> `int -2`;
|
|
store `int -2` to `i`
|
|
<3> declare `long l`;
|
|
load from `i` -> `int -2`;
|
|
implicit cast `int -2` to `long -2` -> `long -2`;
|
|
bitwise not `long -2` -> `long 1`;
|
|
store `long 1` to `l`
|
|
+
|
|
* Bitwise not with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def d = 1; <1>
|
|
def e = ~d; <2>
|
|
----
|
|
+
|
|
<1> declare `def d`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` to `d`;
|
|
<2> declare `def e`;
|
|
load from `d` -> `def`;
|
|
implicit cast `def` to `int 1` -> `int 1`;
|
|
bitwise not `int 1` -> `int -2`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` to `e`
|
|
|
|
[[multiplication-operator]]
|
|
==== Multiplication
|
|
|
|
Use the `multiplication operator '*'` to MULTIPLY together two numeric type
|
|
values. Rules for resultant overflow and NaN values follow the JVM
|
|
specification.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
multiplication: expression '*' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|
|
|====
|
|
| | byte | short | char | int | long | float | double | def
|
|
| byte | int | int | int | int | long | float | double | def
|
|
| short | int | int | int | int | long | float | double | def
|
|
| char | int | int | int | int | long | float | double | def
|
|
| int | int | int | int | int | long | float | double | def
|
|
| long | long | long | long | long | long | float | double | def
|
|
| float | float | float | float | float | float | float | double | def
|
|
| double | double | double | double | double | double | double | double | def
|
|
| def | def | def | def | def | def | def | def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Multiplication with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 5*4; <1>
|
|
double d = i*7.0; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
multiply `int 4` by `int 5` -> `int 20`;
|
|
store `int 20` in `i`
|
|
<2> declare `double d`;
|
|
load from `int i` -> `int 20`;
|
|
promote `int 20` and `double 7.0`: result `double`;
|
|
implicit cast `int 20` to `double 20.0` -> `double 20.0`;
|
|
multiply `double 20.0` by `double 7.0` -> `double 140.0`;
|
|
store `double 140.0` to `d`
|
|
+
|
|
* Multiplication with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 5*4; <1>
|
|
def y = x*2; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
multiply `int 5` by `int 4` -> `int 20`;
|
|
implicit cast `int 20` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 20`;
|
|
multiply `int 20` by `int 2` -> `int 40`;
|
|
implicit cast `int 40` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[division-operator]]
|
|
==== Division
|
|
|
|
Use the `division operator '/'` to DIVIDE one numeric type value by another.
|
|
Rules for NaN values and division by zero follow the JVM specification. Division
|
|
with integer values drops the remainder of the resultant value.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-numeric type.
|
|
* If a left-hand side integer type value is divided by a right-hand side integer
|
|
type value of `0`.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
division: expression '/' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|
|
|====
|
|
| | byte | short | char | int | long | float | double | def
|
|
| byte | int | int | int | int | long | float | double | def
|
|
| short | int | int | int | int | long | float | double | def
|
|
| char | int | int | int | int | long | float | double | def
|
|
| int | int | int | int | int | long | float | double | def
|
|
| long | long | long | long | long | long | float | double | def
|
|
| float | float | float | float | float | float | float | double | def
|
|
| double | double | double | double | double | double | double | double | def
|
|
| def | def | def | def | def | def | def | def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Division with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 29/4; <1>
|
|
double d = i/7.0; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
divide `int 29` by `int 4` -> `int 7`;
|
|
store `int 7` in `i`
|
|
<2> declare `double d`;
|
|
load from `int i` -> `int 7`;
|
|
promote `int 7` and `double 7.0`: result `double`;
|
|
implicit cast `int 7` to `double 7.0` -> `double 7.0`;
|
|
divide `double 7.0` by `double 7.0` -> `double 1.0`;
|
|
store `double 1.0` to `d`
|
|
+
|
|
* Division with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 5/4; <1>
|
|
def y = x/2; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
divide `int 5` by `int 4` -> `int 1`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 1`;
|
|
divide `int 1` by `int 2` -> `int 0`;
|
|
implicit cast `int 0` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[remainder-operator]]
|
|
==== Remainder
|
|
|
|
Use the `remainder operator '%'` to calculate the REMAINDER for division
|
|
between two numeric type values. Rules for NaN values and division by zero follow the JVM
|
|
specification.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
remainder: expression '%' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|
|
|====
|
|
| | byte | short | char | int | long | float | double | def
|
|
| byte | int | int | int | int | long | float | double | def
|
|
| short | int | int | int | int | long | float | double | def
|
|
| char | int | int | int | int | long | float | double | def
|
|
| int | int | int | int | int | long | float | double | def
|
|
| long | long | long | long | long | long | float | double | def
|
|
| float | float | float | float | float | float | float | double | def
|
|
| double | double | double | double | double | double | double | double | def
|
|
| def | def | def | def | def | def | def | def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Remainder with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 29%4; <1>
|
|
double d = i%7.0; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
remainder `int 29` by `int 4` -> `int 1`;
|
|
store `int 7` in `i`
|
|
<2> declare `double d`;
|
|
load from `int i` -> `int 1`;
|
|
promote `int 1` and `double 7.0`: result `double`;
|
|
implicit cast `int 1` to `double 1.0` -> `double 1.0`;
|
|
remainder `double 1.0` by `double 7.0` -> `double 1.0`;
|
|
store `double 1.0` to `d`
|
|
+
|
|
* Remainder with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 5%4; <1>
|
|
def y = x%2; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
remainder `int 5` by `int 4` -> `int 1`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 1`;
|
|
remainder `int 1` by `int 2` -> `int 1`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[addition-operator]]
|
|
==== Addition
|
|
|
|
Use the `addition operator '+'` to ADD together two numeric type values. Rules
|
|
for resultant overflow and NaN values follow the JVM specification.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
addition: expression '+' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|
|
|====
|
|
| | byte | short | char | int | long | float | double | def
|
|
| byte | int | int | int | int | long | float | double | def
|
|
| short | int | int | int | int | long | float | double | def
|
|
| char | int | int | int | int | long | float | double | def
|
|
| int | int | int | int | int | long | float | double | def
|
|
| long | long | long | long | long | long | float | double | def
|
|
| float | float | float | float | float | float | float | double | def
|
|
| double | double | double | double | double | double | double | double | def
|
|
| def | def | def | def | def | def | def | def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Addition operator with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 29+4; <1>
|
|
double d = i+7.0; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
add `int 29` and `int 4` -> `int 33`;
|
|
store `int 33` in `i`
|
|
<2> declare `double d`;
|
|
load from `int i` -> `int 33`;
|
|
promote `int 33` and `double 7.0`: result `double`;
|
|
implicit cast `int 33` to `double 33.0` -> `double 33.0`;
|
|
add `double 33.0` and `double 7.0` -> `double 40.0`;
|
|
store `double 40.0` to `d`
|
|
+
|
|
* Addition with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 5+4; <1>
|
|
def y = x+2; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
add `int 5` and `int 4` -> `int 9`;
|
|
implicit cast `int 9` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 9`;
|
|
add `int 9` and `int 2` -> `int 11`;
|
|
implicit cast `int 11` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[subtraction-operator]]
|
|
==== Subtraction
|
|
|
|
Use the `subtraction operator '-'` to SUBTRACT a right-hand side numeric type
|
|
value from a left-hand side numeric type value. Rules for resultant overflow
|
|
and NaN values follow the JVM specification.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-numeric type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
subtraction: expression '-' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|
|
|====
|
|
| | byte | short | char | int | long | float | double | def
|
|
| byte | int | int | int | int | long | float | double | def
|
|
| short | int | int | int | int | long | float | double | def
|
|
| char | int | int | int | int | long | float | double | def
|
|
| int | int | int | int | int | long | float | double | def
|
|
| long | long | long | long | long | long | float | double | def
|
|
| float | float | float | float | float | float | float | double | def
|
|
| double | double | double | double | double | double | double | double | def
|
|
| def | def | def | def | def | def | def | def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Subtraction with different numeric types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 29-4; <1>
|
|
double d = i-7.5; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
subtract `int 4` from `int 29` -> `int 25`;
|
|
store `int 25` in `i`
|
|
<2> declare `double d`
|
|
load from `int i` -> `int 25`;
|
|
promote `int 25` and `double 7.5`: result `double`;
|
|
implicit cast `int 25` to `double 25.0` -> `double 25.0`;
|
|
subtract `double 33.0` by `double 7.5` -> `double 25.5`;
|
|
store `double 25.5` to `d`
|
|
+
|
|
* Subtraction with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 5-4; <1>
|
|
def y = x-2; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
subtract `int 4` and `int 5` -> `int 1`;
|
|
implicit cast `int 1` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 1`;
|
|
subtract `int 2` from `int 1` -> `int -1`;
|
|
implicit cast `int -1` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[left-shift-operator]]
|
|
==== Left Shift
|
|
|
|
Use the `left shift operator '<<'` to SHIFT lower order bits to higher order
|
|
bits in a left-hand side integer type value by the distance specified in a
|
|
right-hand side integer type value.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-integer type.
|
|
* If the right-hand side value cannot be cast to an int type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
left_shift: expression '<<' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
The left-hand side integer type value is promoted as specified in the table
|
|
below. The right-hand side integer type value is always implicitly cast to an
|
|
`int` type value and truncated to the number of bits of the promoted type value.
|
|
|
|
[options="header",cols="<1,<1"]
|
|
|====
|
|
| original | promoted
|
|
| byte | int
|
|
| short | int
|
|
| char | int
|
|
| int | int
|
|
| long | long
|
|
| def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Left shift with different integer types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 4 << 1; <1>
|
|
long l = i << 2L; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
left shift `int 4` by `int 1` -> `int 8`;
|
|
store `int 8` in `i`
|
|
<2> declare `long l`
|
|
load from `int i` -> `int 8`;
|
|
implicit cast `long 2` to `int 2` -> `int 2`;
|
|
left shift `int 8` by `int 2` -> `int 32`;
|
|
implicit cast `int 32` to `long 32` -> `long 32`;
|
|
store `long 32` to `l`
|
|
+
|
|
* Left shift with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 4 << 2; <1>
|
|
def y = x << 1; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
left shift `int 4` by `int 2` -> `int 16`;
|
|
implicit cast `int 16` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 16`;
|
|
left shift `int 16` by `int 1` -> `int 32`;
|
|
implicit cast `int 32` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[right-shift-operator]]
|
|
==== Right Shift
|
|
|
|
Use the `right shift operator '>>'` to SHIFT higher order bits to lower order
|
|
bits in a left-hand side integer type value by the distance specified in a
|
|
right-hand side integer type value. The highest order bit of the left-hand side
|
|
integer type value is preserved.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-integer type.
|
|
* If the right-hand side value cannot be cast to an int type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
right_shift: expression '>>' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
The left-hand side integer type value is promoted as specified in the table
|
|
below. The right-hand side integer type value is always implicitly cast to an
|
|
`int` type value and truncated to the number of bits of the promoted type value.
|
|
|
|
[options="header",cols="<1,<1"]
|
|
|====
|
|
| original | promoted
|
|
| byte | int
|
|
| short | int
|
|
| char | int
|
|
| int | int
|
|
| long | long
|
|
| def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Right shift with different integer types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 32 >> 1; <1>
|
|
long l = i >> 2L; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
right shift `int 32` by `int 1` -> `int 16`;
|
|
store `int 16` in `i`
|
|
<2> declare `long l`
|
|
load from `int i` -> `int 16`;
|
|
implicit cast `long 2` to `int 2` -> `int 2`;
|
|
right shift `int 16` by `int 2` -> `int 4`;
|
|
implicit cast `int 4` to `long 4` -> `long 4`;
|
|
store `long 4` to `l`
|
|
+
|
|
* Right shift with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 16 >> 2; <1>
|
|
def y = x >> 1; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
right shift `int 16` by `int 2` -> `int 4`;
|
|
implicit cast `int 4` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 4`;
|
|
right shift `int 4` by `int 1` -> `int 2`;
|
|
implicit cast `int 2` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[unsigned-right-shift-operator]]
|
|
==== Unsigned Right Shift
|
|
|
|
Use the `unsigned right shift operator '>>>'` to SHIFT higher order bits to
|
|
lower order bits in a left-hand side integer type value by the distance
|
|
specified in a right-hand side type integer value. The highest order bit of the
|
|
left-hand side integer type value is *not* preserved.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-integer type.
|
|
* If the right-hand side value cannot be cast to an int type.
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
unsigned_right_shift: expression '>>>' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
The left-hand side integer type value is promoted as specified in the table
|
|
below. The right-hand side integer type value is always implicitly cast to an
|
|
`int` type value and truncated to the number of bits of the promoted type value.
|
|
|
|
[options="header",cols="<1,<1"]
|
|
|====
|
|
| original | promoted
|
|
| byte | int
|
|
| short | int
|
|
| char | int
|
|
| int | int
|
|
| long | long
|
|
| def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Unsigned right shift with different integer types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = -1 >>> 29; <1>
|
|
long l = i >>> 2L; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
unsigned right shift `int -1` by `int 29` -> `int 7`;
|
|
store `int 7` in `i`
|
|
<2> declare `long l`
|
|
load from `int i` -> `int 7`;
|
|
implicit cast `long 2` to `int 2` -> `int 2`;
|
|
unsigned right shift `int 7` by `int 2` -> `int 3`;
|
|
implicit cast `int 3` to `long 3` -> `long 3`;
|
|
store `long 3` to `l`
|
|
+
|
|
* Unsigned right shift with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 16 >>> 2; <1>
|
|
def y = x >>> 1; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
unsigned right shift `int 16` by `int 2` -> `int 4`;
|
|
implicit cast `int 4` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 4`;
|
|
unsigned right shift `int 4` by `int 1` -> `int 2`;
|
|
implicit cast `int 2` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[bitwise-and-operator]]
|
|
==== Bitwise And
|
|
|
|
Use the `bitwise and operator '&'` to AND together each bit within two
|
|
integer type values where if both bits at the same index are `1` the resultant
|
|
bit is `1` and `0` otherwise.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-integer type.
|
|
|
|
*Bits*
|
|
|
|
[cols="^1,^1,^1"]
|
|
|====
|
|
| | 1 | 0
|
|
| 1 | 1 | 0
|
|
| 0 | 0 | 0
|
|
|====
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
bitwise_and: expression '&' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[cols="<1,^1,^1,^1,^1,^1,^1"]
|
|
|====
|
|
| | byte | short | char | int | long | def
|
|
| byte | int | int | int | int | long | def
|
|
| short | int | int | int | int | long | def
|
|
| char | int | int | int | int | long | def
|
|
| int | int | int | int | int | long | def
|
|
| long | long | long | long | long | long | def
|
|
| def | def | def | def | def | def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Bitwise and with different integer types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 5 & 6; <1>
|
|
long l = i & 5L; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
bitwise and `int 5` and `int 6` -> `int 4`;
|
|
store `int 4` in `i`
|
|
<2> declare `long l`
|
|
load from `int i` -> `int 4`;
|
|
promote `int 4` and `long 5`: result `long`;
|
|
implicit cast `int 4` to `long 4` -> `long 4`;
|
|
bitwise and `long 4` and `long 5` -> `long 4`;
|
|
store `long 4` to `l`
|
|
+
|
|
* Bitwise and with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 15 & 6; <1>
|
|
def y = x & 5; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
bitwise and `int 15` and `int 6` -> `int 6`;
|
|
implicit cast `int 6` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 6`;
|
|
bitwise and `int 6` and `int 5` -> `int 4`;
|
|
implicit cast `int 4` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[bitwise-xor-operator]]
|
|
==== Bitwise Xor
|
|
|
|
Use the `bitwise xor operator '^'` to XOR together each bit within two integer
|
|
type values where if one bit is a `1` and the other bit is a `0` at the same
|
|
index the resultant bit is `1` otherwise the resultant bit is `0`.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-integer type.
|
|
|
|
*Bits*
|
|
|
|
The following table illustrates the resultant bit from the xoring of two bits.
|
|
|
|
[cols="^1,^1,^1"]
|
|
|====
|
|
| | 1 | 0
|
|
| 1 | 0 | 1
|
|
| 0 | 1 | 0
|
|
|====
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
bitwise_and: expression '^' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[cols="<1,^1,^1,^1,^1,^1,^1"]
|
|
|====
|
|
| | byte | short | char | int | long | def
|
|
| byte | int | int | int | int | long | def
|
|
| short | int | int | int | int | long | def
|
|
| char | int | int | int | int | long | def
|
|
| int | int | int | int | int | long | def
|
|
| long | long | long | long | long | long | def
|
|
| def | def | def | def | def | def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Bitwise xor with different integer types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 5 ^ 6; <1>
|
|
long l = i ^ 5L; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
bitwise xor `int 5` and `int 6` -> `int 3`;
|
|
store `int 3` in `i`
|
|
<2> declare `long l`
|
|
load from `int i` -> `int 4`;
|
|
promote `int 3` and `long 5`: result `long`;
|
|
implicit cast `int 3` to `long 3` -> `long 3`;
|
|
bitwise xor `long 3` and `long 5` -> `long 6`;
|
|
store `long 6` to `l`
|
|
+
|
|
* Bitwise xor with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 15 ^ 6; <1>
|
|
def y = x ^ 5; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
bitwise xor `int 15` and `int 6` -> `int 9`;
|
|
implicit cast `int 9` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 9`;
|
|
bitwise xor `int 9` and `int 5` -> `int 12`;
|
|
implicit cast `int 12` to `def` -> `def`;
|
|
store `def` to `y`
|
|
|
|
[[bitwise-or-operator]]
|
|
==== Bitwise Or
|
|
|
|
Use the `bitwise or operator '|'` to OR together each bit within two integer
|
|
type values where if at least one bit is a `1` at the same index the resultant
|
|
bit is `1` otherwise the resultant bit is `0`.
|
|
|
|
*Errors*
|
|
|
|
* If either of the values is a non-integer type.
|
|
|
|
*Bits*
|
|
|
|
The following table illustrates the resultant bit from the oring of two bits.
|
|
|
|
[cols="^1,^1,^1"]
|
|
|====
|
|
| | 1 | 0
|
|
| 1 | 1 | 1
|
|
| 0 | 1 | 0
|
|
|====
|
|
|
|
*Grammar*
|
|
|
|
[source,ANTLR4]
|
|
----
|
|
bitwise_and: expression '|' expression;
|
|
----
|
|
|
|
*Promotion*
|
|
|
|
[cols="<1,^1,^1,^1,^1,^1,^1"]
|
|
|====
|
|
| | byte | short | char | int | long | def
|
|
| byte | int | int | int | int | long | def
|
|
| short | int | int | int | int | long | def
|
|
| char | int | int | int | int | long | def
|
|
| int | int | int | int | int | long | def
|
|
| long | long | long | long | long | long | def
|
|
| def | def | def | def | def | def | def
|
|
|====
|
|
|
|
*Examples*
|
|
|
|
* Bitwise or with different integer types.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
int i = 5 | 6; <1>
|
|
long l = i | 8L; <2>
|
|
----
|
|
+
|
|
<1> declare `int i`;
|
|
bitwise or `int 5` and `int 6` -> `int 7`;
|
|
store `int 7` in `i`
|
|
<2> declare `long l`
|
|
load from `int i` -> `int 7`;
|
|
promote `int 7` and `long 8`: result `long`;
|
|
implicit cast `int 7` to `long 7` -> `long 7`;
|
|
bitwise or `long 7` and `long 8` -> `long 15`;
|
|
store `long 15` to `l`
|
|
+
|
|
* Bitwise or with the `def` type.
|
|
+
|
|
[source,Painless]
|
|
----
|
|
def x = 5 ^ 6; <1>
|
|
def y = x ^ 8; <2>
|
|
----
|
|
<1> declare `def x`;
|
|
bitwise or `int 5` and `int 6` -> `int 7`;
|
|
implicit cast `int 7` to `def` -> `def`;
|
|
store `def` in `x`
|
|
<2> declare `def y`;
|
|
load from `x` -> `def`;
|
|
implicit cast `def` to `int 7`;
|
|
bitwise or `int 7` and `int 8` -> `int 15`;
|
|
implicit cast `int 15` to `def` -> `def`;
|
|
store `def` to `y` |