[[painless-operators]] === Operators The following is a table of the available operators in Painless. Each operator will have further information and examples outside of the table. Many operators will have a promotion table as described by the documentation on promotion [MARK]. [options="header",cols="6,3,2,4"] |==== |Operator|Symbol(s)|Precedence|Associativity |Precedence|()|0|left-to-right |Field Access|.|1|left-to-right |Method Call|. ()|1|left-to-right |Null Safe|?.|1|left-to-right |Function Call|()|1|left-to-right |Array Initialization|[] {}|1|left-to-right |Array Access|[]|1|left-to-right |Array Length|.|1|left-to-right |List Initialization|[]|1|left-to-right |List Access|[]|1|left-to-right |Map Initialization|[:]|1|left-to-right |Map Access|[]|1|left-to-right |Post Increment|++|1|left-to-right |Post Decrement|--|1|left-to-right |Pre Increment|++|2|right-to-left |Pre Decrement|--|2|right-to-left |Unary Positive|+|2|right-to-left |Unary Negative|-|2|right-to-left |Boolean Not|!|2|right-to-left |Bitwise Not|~|2|right-to-left |Cast|()|3|right-to-left |Constructor Call|new ()|3|right-to-left |New Array|new|3|right-to-left |Multiplication|*|4|left-to-right |Division|/|4|left-to-right |Remainder|%|4|left-to-right |String Concatenation|+|5|left-to-right |Addition|+|5|left-to-right |Subtraction|-|5|left-to-right |Left Shift|<<|6|left-to-right |Right Shift|>>|6|left-to-right |Unsigned Right Shift|>>>|6|left-to-right |Greater Than|>|7|left-to-right |Greater Than Or Equal|>=|7|left-to-right |Less Than|<|7|left-to-right |Less Than Or Equal|<=|7|left-to-right |Instance Of|instanceof|8|left-to-right |Equality Equals|==|9|left-to-right |Equality Not Equals|!=|9|left-to-right |Identity Equals|===|9|left-to-right |Identity Not Equals|!==|9|left-to-right |Bitwise And|&|10|left-to-right |Boolean Xor|^|11|left-to-right |Bitwise Xor|^|11|left-to-right |Bitwise Or|\||12|left-to-right |Boolean And|&&|13|left-to-right |Boolean Or|\|\||14|left-to-right |Conditional|? :|15|right-to-left |Elvis|?:|16|right-to-left |Assignment|=|17|right-to-left |Compound Assignment|$=|17|right-to-left |==== [[precedence-operator]] ==== Precedence You group expressions using the precedence operator to guarantee the order of evaluation and override existing precedence relationships between operators. The format is an opening parenthesis, one or more expressions, and a closing parenthesis. For example, `(20+1)*2`. *Grammar:* [source,ANTLR4] ---- precedence: '(' expression ')'; ---- *Examples:* [source,Java] ---- int x = (5+4)*6; // declares the variable int x and sets it to (5+4)*6 // where 5+4 is evaluated first due to the precedence operator int y = 2*(x-4); // declares the variable int y and sets it to 2*(x-4) // where x-4 is evaluated first due to the precedence operator ---- [[dot-operator]] ==== Dot You use the dot operator `.` to access a type's <> and <>. [[field-access]] ===== Accessing Fields You access primitive and reference type members in a reference type using the dot operator '.' followed by the id of the member. The accessed member behaves the same way as the type it represents with one exception: if the reference type is of type `def`, the member is also considered to be of type `def` and resolved at runtime. *Grammar:* [source,ANTLR4] ---- field_access: ID '.' ID; ---- *Examples:* [source,Java] ---- FeatureTest ft = new FeatureTest(); // Declare FeatureTest variable ft and // set it to a newly allocated FeatureTest ft.x = 5; // Access int member x from ft and assign // it the literal int value 5 ft.y = ft.x; // Access int member y from ft and assign // it the value of ft member x int value = ft.x + ft.y; // Declare variable value as an int, // add ft members x and y together, // assign the sum to the variable value ---- [[method-access]] ===== Calling Methods You call reference type methods using the dot operator and the method id: `.method_id(arg1,...,argn)`. The parentheses are required even if there are no arguments. If the reference type is not type `def`, the argument types for the method can be resolved at compile time. An error occurs if appropriate type conversions (casting) cannot be performed. If the reference type is type `def`, the argument types for the method are all considered to be the type `def`. The appropriate type conversions are performed at run-time. Automatic <> is performed when you pass in arguments to a method. Method calls can be overloaded based on arity in Painless. The same method name can be re-used for different methods as long as the number of arguments differs. This differs from Java method overloading, where only the types must differ. This has an effect on some of the provided reference type methods in the <>. Where there are overloaded methods with the same arity for a reference type in Java, Painless chooses a single method to be provided. *Grammar:* [source,ANTLR4] ---- method_call: ID '.' ID '(' (expression (',' expression)*)? ')'; ---- *Examples:* [source,Java] ---- Map m = new HashMap(); // Declare Map variable m and set it a newly // allocated HashMap x.put(1, 2); // Call the put method on variable x to add key 1 // with the value 2 to the Map int z = x.get(1); // Declare int variable z, call the get method to // retrieve the value of key 1, and assign the // return value of the method call to variable z def d = new ArrayList(); // Declare def variable m and set it a newly // allocated ArrayList d.add(1); // Call the add method on variable d and add the // literal int 1 to the ArrayList. Note that // the argument type is considered to be of // type def since the reference type is also def int i = Integer.parseInt('2'); // Declare int variable i and set it to the // value returned by the static method parseInt ---- ************************** Painless describes the Map method arguments using the `def` type: [source,Java] ---- put(def, def) get(def) ---- When you call `x.put(1, 2)`, the key and value are implicitly converted from the int type to the def type. Assume for a minute that the Map method arguments were described as Integers: [source,Java] ---- put(Integer, Integer) get(Integer) ---- In this case, the key and value would implicitly be _boxed_ from the primitive int type to the Integer reference type. For more information about how Painless casts between primitive types and reference types, see <>. ************************** ==== Null Safe The null safe operator `?.` can be used in place of the dot operator to check if a reference type instance is `null` before attempting to access a field or make a method call against it. When using the null safe operator, if the instance is `null`, the returned value is `null`. If the reference type instance is non-null, it returns the value of the field or result of the method call normally. // REVIEWER NOTE: The following paragraph doesn't make sense to me. Do you All resultant types must be a reference type or be able to be implicitly cast to a reference type or an error will occur. *Grammar:* [source,ANTLR4] ---- null_safe: null_safe_field_access | null_safe_method_call; null_safe_field_access: ID '?.' ID; null_safe_method_call: ID '?.' ID '(' (expression (',' expression)*)? ')'; ---- *Examples:* [source,Java] ---- Map x = new HashMap(); // Declare the Map variable x and set it to a newly // allocated HashMap Map y = null; // Declare the Map variable y and set it to null def z = new HashMap(); // Declares the def variable z and set it to a newly // allocated HashMap x.put(1, 2); // Put the key-value pair 1 and 2 into x z.put(5, 6); // Put the key-value pair 5 and 6 into z def value = x?.get(1); // Declare the def variable value and set it to the // result of .get(1) since x is not null value = y?.get(3); // Sets value to null since y is null value = z?.get(5); // Sets value to the result of .get(5) since z is not null ---- ==== Parenthesis User-defined function calls can be made in Painless using the parenthesis operator. See Function Calls [MARK] for more information. ==== Brackets and Braces The brackets operator `[]` is used to create and access arrays, lists, and maps. The braces operator `{}` is used to intialize arrays. [[array-initialization]] ===== Creating and Initializing Arrays You create and initialize arrays using the brackets `[]` and braces `{}` operators. Each set of brackets represents a dimension. The values you want to initialize each dimension with are specified as a comma-separated list enclosed in braces. For example, `new int[] {1, 2, 3}` creates a one dimensional `int` array with a size of 3 and the values 1, 2, and 3. To allocate an array, you use the `new` keyword followed by the type and a set of brackets for each dimension. You can explicitly define the size of each dimension by specifying an expression within the brackets, or initialize each dimension with the desired number of values. The allocated size of each dimension is its permanent size. To initialize an array, specify the values you want to initialize each dimension with as a comma-separated list of expressions enclosed in braces. For example, `new int[] {1, 2, 3}` creates a one-dimensional `int` array with a size of 3 and the values 1, 2, and 3. When you initialize an array, the order of the expressions is maintained. Each expression used as part of the initialization is converted to the array's type. An error occurs if the types do not match. *Grammar:* [source,ANTLR4] ---- declare_array: TYPE ('[' ']')+; array_initialization: 'new' TYPE '[' ']' '{' expression (',' expression) '}' | 'new' TYPE '[' ']' '{' '}'; ---- *Examples:* [source,Java] ---- int[] x = new int[5]; // Declare int array x and assign it a newly // allocated int array with a size of 5 def[][] y = new def[5][5]; // Declare the 2-dimensional def array y and // assign it a newly allocated 2-dimensional // array where both dimensions have a size of 5 int[] x = new int[] {1, 2, 3}; // Declare int array x and set it to an int // array with values 1, 2, 3 and a size of 3 int i = 1; long l = 2L; float f = 3.0F; double d = 4.0; String s = "5"; def[] da = new def[] {i, l, f*d, s}; // Declare def array da and set it to // a def array with a size of 4 and the // values i, l, f*d, and s ---- [[array-access]] ===== Accessing Array Elements Elements in an array are stored and accessed using the brackets `[]` operator. Elements are referenced by an expression enclosed in brackets. An error occurs if the expression used to reference an element cannot be implicitly cast to an `int`. The range of elements within an array that can be accessed is `[0, size)` where size is the originally allocated size of the array. To access elements relative to the last element in an array, you can use a negative numeric value from `[-size, -1]`. An error occurs if you attempt to reference an element outside of the array's range. *Grammar:* [source,ANTLR4] ---- brace_access: '[' expression ']' ---- *Examples:* [source,Java] ---- int[] x = new int[2]; // Declare int array x and set it to a newly allocated // array with a size of 2 x[0] = 2; // Set the 0th element of array x to 2 x[1] = 5; // Set the 1st element of array x to 5 int y = x[0] + x[1]; // Declare the int variable y and set it to the sum // of the first two elements of array x int z = 1; // Declare the int variable z and set it to 1 return x[z]; // Access the 1st element of array x using the // variable z as an expression and return the value def d = new int[2]; // Declare def variable d and set it to a newly // allocated array with a size of 2 d[0] = 2; // Set the 0th element of array d to 2 d[1] = 5; // Set the 1st element of array d to 2 def y = d[0] + d[1]; // Declare def variable y and set it to the sum // of the first two elements of array d def z = 1; // Declare def variable z and set it to 1 return d[z]; // Access the 1st element of array d using the // variable z as an expression and return the value ---- NOTE: The use of the `def` type in the second example means that the types cannot be resolved until runtime. [[array-length]] ===== Array Length Arrays contain a special member known as 'length' that is a read-only value that contains the size of the array. This member can be accessed from an array using the dot operator. *Examples:* [source,Java] ---- int[] x = new int[10]; // declares an int array variable x and sets it to a newly allocated array with a size of 10 int l = x.length; // declares and int variable l and sets it to the field length of variable x ---- ===== Creating and Initializing Lists You create and initialize lists using the brackets `[]` operator. The values you want to initialize the list with are specified as a comma-separated list of expressions enclosed in brackets. For example, `List l = [1, 2, 3]` creates a new three item list. Each expression used to initialize the list is converted a `def` type when the value is inserted into the list. The order of the expressions is maintained. *Grammar:* [source,ANTLR4] ---- list_initialization: '[' expression (',' expression)* ']' | '[' ']'; ---- *Examples:* [source,Java] ---- List empty = []; // declares the List variable empty and sets it to a newly initialized empty List List l0 = [1, 2, 3]; // declares the List variable l0 and sets it to a newly initialized List with the values 1, 2, and 3 int i = 1; long l = 2L; float f = 3.0F; double d = 4.0; String s = "5"; List l1 = [i, l, f*d, s]; // declares the List variable l1 and sets it to a newly initialized List with the values of i, l, and f*d and s ---- ===== Accessing List Elements Elements in a List are stored or accessed using the brackets operator. The format begins with an opening bracket, followed by an expression, and finishes with a closing bracket. Storing elements in a List is equivalent to invoking a List's set method. Accessing elements in a List is equivalent to invoking a List's get method. Using this operator is strictly a shortcut for the previously mentioned methods. The range of elements within a List that can be accessed is [0, size) where size is the number of elements currently in the List. Elements may also be accessed from the last element in a List using a negative numeric value from [-size, -1]. The expression used to determine which element is accessed must be able to be implicitly cast to an int. An error will occur if the expression is outside of the legal range or is not of type int. *Grammar:* [source,ANTLR4] ---- list_access: '[' expression ']' ---- *Examples:* [source,Java] ---- List x = new ArrayList(); // declares a List variable x and sets it to a newly allocated ArrayList x.add(1); // invokes the add method on the variable x and adds the constant int 1 to the List x.add(2); // invokes the add method on the variable x and adds the constant int 2 to the List x.add(3); // invokes the add method on the variable x and adds the constant int 3 to the List x[0] = 2; // sets the 0th element of the variable x to the constant int 2 x[1] = 5; // sets the 1st element of the variable x to the constant int 2 int y = x[0] + x[1]; // declares the int variable y and sets it to the sum of the first two elements of the variable x int z = 1; // declares the int variable z and sets it to the constant int 1 return x[z]; // accesses the 1st element of the variable x using the variable z as an expression and returns the value def d = new ArrayList(); // declares a def variable d and sets it to a newly allocated ArrayList d.add(1); // invokes the add method on the variable d and adds the constant int 1 to the List d.add(2); // invokes the add method on the variable d and adds the constant int 2 to the List d.add(3); // invokes the add method on the variable d and adds the constant int 3 to the List d[0] = 2; // sets the 0th element of the variable d to the constant int 2 d[1] = 5; // sets the 1st element of the variable d to the constant int 2 def y = d[0] + d[1]; // declares the def variable y and sets it to the sum of the first two elements of the variable d def z = 1; // declares the def variable z and sets it to the constant int 1 return d[z]; // accesses the 1st element of the variable d using the variable z as an expression and returns the value ---- Note in the first example above all types can be resolved at compile-time, while in the second example all types must wait to be resolved until run-time. ===== Creating and Initializing Maps A Map can be created and initialized using the brackets operator. The format begins with a bracket, followed by an arbitrary number of key-value pairs delimited with commas (except the last), and ends with a closing bracket. Each key-value pair is a set of two expressions separate by a colon. If there is only a single colon with no expressions, a new empty Map is created. *Grammar:* [source,ANTLR4] ---- map_initialization: '[' key_pair (',' key_pair)* ']' | '[' ':' ']'; key_pair: expression ':' expression ---- Each expression used as part of the initialization is converted to a `def` type for insertion into the map. *Examples:* [source,Java] ---- Map empty = [:]; // declares the Map variable empty and sets it to a newly initialized empty Map Map m0 = [1:2, 3:4, 5:6]; // declares the Map variable m0 and sets it to a newly initialized Map with the keys 1, 3, 5 and values 2, 4, 6, respectively byte b = 0; int i = 1; long l = 2L; float f = 3.0F; double d = 4.0; String s = "5"; Map m1 = [b:i, l:f*d, d:s]; // declares the Map variable m1 and sets it to a newly initialized Map with the keys b, l, d and values i, f*d, s, respectively ---- ===== Accessing Map Elements Elements in a Map can be stored or accessed using the brackets operator. The format begins with an opening bracket, followed by an expression, and finishes with a closing bracket. Storing values in a Map is equivalent to invoking a Map's put method. Accessing values in a Map is equivalent to invoking a Map's get method. Using this operator is strictly a shortcut for the previously mentioned methods. Any element from a Map can be stored/accessed where the expression is the key. If a key has no corresponding value when accessing a Map then the value will be null. *Grammar:* [source,ANTLR4] ---- map_access: '[' expression ']' ---- *Examples:* [source,Java] ---- Map x = new HashMap(); // declares a Map variable x and sets it to a newly allocated HashMap x['value2'] = 2; // puts the value of the key constant String value2 of the variable x to the constant int 2 x['value5'] = 5; // puts the value of the key constant String value5 of the variable x to the constant int 5 int y = x['value2'] + x['value5']; // declares the int variable y and sets it to the sum of the two values of the variable x String z = 'value5'; // declares the String variable z and sets it to the constant String value5 return x[z]; // accesses the value for the key value5 of the variable x using the variable z as an expression and returns the value def d = new HashMap(); // declares a def variable d and sets it to a newly allocated HashMap d['value2'] = 2; // puts the value of the key constant String value2 of the variable d to the constant int 2 d['value5'] = 5; // puts the value of the key constant String value5 of the variable d to the constant int 5 int y = d['value2'] + d['value5']; // declares the int variable y and sets it to the sum of the two values of the variable d String z = 'value5'; // declares the String variable z and sets it to the constant String value5 return d[z]; // accesses the value for the key value5 of the variable x using the variable z as an expression and returns the value ---- Note in the first example above all types can be resolved at compile-time, while in the second example all types must wait to be resolved until run-time. ==== Post Increment A variable/field representing a numerical value can be possibly evaluated as part of an expression, and then increased by 1 for its respective type. The format starts with a variable name followed by a plus and ends with a plus. *Grammar:* [source,ANTLR4] ---- post_increment: ( variable | member ) '++' ---- A numeric promotion may occur during a post-increment followed by a downcast if necessary. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. A downcast may be required after the type promotion to assign the appropriate value back into the variable/field. Non-numeric variables/members will result in an error. Promotion Table: |==== |from|to|downcast |byte|int|byte |short|int|short |char|int|char |int|int| |long|long| |float|float| |double|double| |def|def| |==== Examples(s): [source,Java] ---- int i = 0; // declares the int variable i and sets it to the constant 0 i++; // increments the int variable i by 1 to a value of 1 long l = 1; // declares the long variable l and set it the constant 1 long k; // declares the long variable k k = l++; // sets the long variable k to the value of l (1), and then increments the long variable l by 1 to a value of 2 ---- ==== Post Decrement A variable/field representing a numerical value can be possibly evaluated as part of an expression, and then increased by 1 for its respective type. The format starts with a variable name followed by a minus and ends with a minus. *Grammar:* [source,ANTLR4] ---- post_increment: ( variable | member ) '--' ---- A numeric promotion may occur during a post-decrement followed by a downcast if necessary. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. A downcast may be required after the type promotion to assign the appropriate value back into the variable/field. Non-numeric variables/members will result in an error. Promotion Table: |==== |from|to|downcast |byte|int|byte |short|int|short |char|int|char |int|int| |long|long| |float|float| |double|double| |def|def| |==== Examples(s): [source,Java] ---- short i = 0; // declares the short variable i and sets it to the constant short 0 i--; // decrements the short variable i by 1 to a value of -1 (promoted to int and downcast to short) float l = 1.0f; // declares the float variable l and sets it the constant float 1.0f float k; // declares the float variable k k = l--; // sets the float variable k to the value of l (1.0f), and then decrements the float variable l by 1.0 to a value of 0.0 ---- ==== Pre Increment A variable/field representing a numerical value can be increased by 1 for its respective type, and then possibly evaluated as part of an expression. The format starts with a plus followed by a plus and ends with a variable name. *Grammar:* [source,ANTLR4] ---- pre_increment: '++' ( variable | member ) ---- A numeric promotion may occur during a pre-increment followed by a downcast if necessary. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. A downcast may be required after the type promotion to assign the appropriate value back into the variable/field. Non-numeric variables/members will result in an error. Promotion Table: |==== |from|to|downcast |byte|int|byte |short|int|short |char|int|char |int|int| |long|long| |float|float| |double|double| |def|def| |==== Examples(s): [source,Java] ---- int i = 0; // declares the int variable i and sets it to the constant int 0 ++i; // increments the int variable i by 1 to a value of 1 long l = 1; // declares the long variable l and sets it to the constant long 1 long k; // declares the long variable k k = ++l; // increments the long variable l by 1 to a value of 2, and then sets the long variable k to the value of l (2) ---- ==== Pre Decrement A variable/field representing a numerical value can be decreased by 1 for its respective type, and then possibly evaluated as part of an expression. The format starts with a minus followed by a minus and ends with a variable name. *Grammar:* [source,ANTLR4] ---- pre_decrement: '--' ( variable | member ) ---- A numeric promotion may occur during a pre-decrement followed by a downcast if necessary. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. A downcast may be required after the type promotion to assign the appropriate value back into the variable/field. Non-numeric variables/members will result in an error. Promotion Table: |==== |from|to|downcast |byte|int|byte |short|int|short |char|int|char |int|int| |long|long| |float|float| |double|double| |def|def| |==== Examples(s): [source,Java] ---- byte i = 1; // declares the byte variable i and sets it to the constant int 1 --i; // decrements the byte variable i by 1 to a value of 0 (promoted to int and downcast to byte) double l = 1.0; // declares the double variable l and sets it to the constant double 1.0 double k; // declares the double variable k k = --l; // decrements the double variable l by 1.0 to a value of 0.0, and then sets the double variable k to the value of l (0.0) ---- ==== Unary Positive Unary positive gives the identity of a numerical value using the plus operator. In practice this is usually a no-op, but will cause some numeric types to be promoted. Format starts with a plus operator followed by a numerical expression. *Grammar:* [source,ANTLR4] ---- unary_positive: '+' expression ---- A numeric promotion may occur during a unary positive operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== |from|to |byte|int |short|int |char|int |int|int |long|long |float|float |double|double |def|def |==== *Examples:* [source,Java] ---- int x = +1; // declares the int variable x and sets it to positive 1 long y = +x; // declares the long variable y and sets it to positive x (promoted to long from int) def z = +y; // declares the def variable z and sets it to positive y byte z = +2; //ERROR: cannot implicitly downcast an int to a byte ---- ==== Unary Negative Unary negative negates a numeric value using the minus operator. Format starts with a minus followed by a numerical expression. *Grammar:* [source,ANTLR4] ---- unary_negative: '-' expression ---- A numeric promotion may occur during a unary negative operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== |from|to |byte|int |short|int |char|int |int|int |long|long |float|float |double|double |def|def |==== *Examples:* [source,Java] ---- int x = -1; // declares the int variable x and sets it to negative 1 long y = -x; // declares the long variable y and sets it to negative x (promoted to long from int) def z = -y; // declares the def variable z and sets it to negative y byte z = -2; //ERROR: cannot implicitly downcast an int to a byte ---- ==== Boolean Not Boolean not will flip a boolean value from true to false or false to true using the bang operator. The format is a bang operator followed by an expression. *Grammar:* [source,ANTLR4] ---- boolean_not: '!' expression; ---- Note that def types will be assumed to be of the boolean type. Any def type evaluated at run-time that does not represent a boolean will result in an error. Non-boolean expressions will result in an error. *Examples:* [source,Java] ---- boolean x = !false; // declares the boolean variable x and sets it to the opposite of the false value boolean y = !x; // declares the boolean variable y and sets it to the opposite of the boolean variable x def z = !y; // declares the def variable z and sets it to the opposite of the boolean variable y ---- ==== Bitwise Not Bitwise not will flip each bit of an integer type expression. The format is the tilde operator followed by an expression. *Grammar:* [source,ANTLR4] ---- bitwise_not: '~' expression; ---- A numeric promotion may occur during unary positive operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-integer expressions will result in an error. Promotion Table: |==== |from|to |byte|int |short|int |char|int |int|int |long|long |def|def |==== *Examples:* [source,Java] ---- byte x = 1; // declares the byte variable x and sets it to a constant int 1 int y = ~x; // declares the int variable y and sets it to the negation of x long z = ~y; // declares the long variable z and sets it the negation of y def d = ~z; // declares the def variable d and sets it the negation of z def e; // declares the def variable e e = ~d; // sets e the negation of d ---- ==== Cast The cast operator can be used to explicitly convert one type to another. See casting [MARK] for more information. [[constructor-call]] ==== Constructor Call A constructor call is a special type of method call [MARK] used to allocate a reference type instance using the new operator. The format is the new operator followed by a type, an opening parenthesis, arguments if any, and a closing parenthesis. Arguments are a series of zero-to-many expressions delimited by commas. Auto-boxing and auto-unboxing will be applied automatically for arguments passed into a constructor call. See boxing and unboxing [MARK] for more information on this topic. Constructor argument types can always be resolved at run-time; if appropriate type conversions (casting) cannot be applied an error will occur. Once a reference type instance has been allocated, its members may be used as part of other expressions. Constructor calls may be overloaded based on arity in Painless. This means the same reference type may have multiple constructors as long as the number of arguments differs for each one. This does have an effect on some of the provided reference type constructors in the Painless API [MARK]. When there are overloaded constructors with the same arity for a reference type in Java a single constructor must be chosen to be provided in Painless. *Grammar:* [source,ANTLR4] ---- constructor_call: 'new' TYPE '(' (expression (',' expression)*)? ')'; ---- *Examples:* [source,Java] ---- Map m = new HashMap(); // declares the Map variable m and sets it to a newly allocated HashMap using an empty constructor m.put(3, 3); // invokes the method call member put and adds the key-value pair of 3 to Map variable m def d = new ArrayList(); // declares the def variable d and sets it to a newly allocated ArrayList using an empty constructor def e; // declares the def variable e e = new HashMap(m); // sets e to a newly allocated HashMap using the constructor with a single argument m ---- [[new-array]] ==== New Array An array type instance can be allocated using the new operator. The format starts with the new operator followed by the type followed by a series of opening and closing braces each containing an expression for the size of the dimension. *Grammar:* [source,ANTLR4] ---- new_array: 'new' TYPE ('[' expression ']')+; ---- *Examples:* [source,Java] ---- int[] x = new int[5]; // declares an int array variable x and sets it to a newly allocated array with a size of 5 x = new int[10]; // sets the int array variable x to a newly allocated array with a size of 10 def[][] y = new def[5][5]; // declares a 2-dimensional def array variable y and set it to a newly // allocated 2-dimensional array where both dimensions have a size of 5 ---- ==== Multiplication Multiplies two numerical expressions. Rules for resultant overflow and NaN values follow the Java specification. The format is an expression, followed by the star operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- multiplication: expression '*' expression; ---- A numeric promotion may occur during a multiplication operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric numbers will result in an error. Promotion Table: |==== ||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:* [source,Java] ---- int x = 5*4; // declares the int variable x and sets it to the result of 5 multiplied by 4 double y = x*7.0; // declares the double variable y and sets it to the result of x multiplied by 7.0 (x is promoted to a double) def z = x*y; // declares the def variable z and sets it to the result of x multiplied by y (x is promoted to a double) def a = z*x; // declares the def variable a and sets it to the result of z multiplied by x (x is promoted to def at compile-time and double at run-time) ---- ==== Division Divides two numerical expressions. Rules for NaN values and division by zero follow the Java specification. Integer division will drop the remainder of the resultant value. The format is an expression, followed by the slash operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- division: expression '/' expression; ---- A numeric promotion may occur during a division operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== ||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:* [source,Java] ---- int x = 5/4; // declares the int variable x and sets it to the result of 5 divided by 4 double y = x/7.0; // declares the double variable y and sets it to the result of x divided by 7.0 (x is promoted to a double) def z = x/y; // declares the def variable z and sets it to the result of x divided by y (x is promoted to a double) def a = z/x; // declares the def variable a and sets it to the result of z divided by x (x is promoted to def at compile-time and double at run-time) ---- ==== Remainder Calculates the remainder for division between two numerical expressions. Rules for NaN values and division by zero follow the Java specification. The format is an expression, followed by the percent operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- remainder: expression '%' expression; ---- A numeric promotion may occur during a remainder operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== ||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:* [source,Java] ---- int x = 5%4; // declares the int variable x and sets it to the remainder of 5 divided by 4 double y = x%7.0; // declares the double variable y and sets it to the remainder of x divided by 7.0 (x is promoted to a double) def z = x%y; // declares the def variable z and sets it to the remainder of x divided by y (x is promoted to a double) def a = z%x; // declares the def variable a and sets it to the remainder of z divided by x (x is promoted to def at compile-time and double at run-time) ---- ==== String Concatenation Concatenates two expressions together as a single String where at least of one of the expressions is a String to begin with. The format is an expression, followed by a plus operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- concatenate: expression '+' expression; ---- *Examples:* [source,Java] ---- String x = "con"; // declares the String variable x and sets it to the String constant "con" String y = x + "cat"; // declares the String variable y and sets it to the concatenation of the String variable x and the String constant "cat" String z = 4 + x; // declares the String variable z and sets it to the concatenation of the int constant 4 and the String variable x (4 is implicitly cast to a String) def d = 2; // declares the def variable d and sets it to the int constant 2 z = z + d; // sets the String variable z to the concatenation of the String variable z d = "con" + x + y + "cat"; // sets the def variable d to the concatenation of String constant "con", x, y, and the String constant "cat" ---- ==== Addition Adds two numerical expressions. Rules for resultant overflow and NaN values follow the Java specification. The format is an expression, followed by the plus operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- addition: expression '+' expression; ---- A numeric promotion may occur during a addition operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error, except in the case of String which then implies the operation is string concatenation [MARK] rather than addition. Promotion Table: |==== ||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:* [source,Java] ---- int x = 5 + 4; // declares the int variable x and sets it to the result of 5 added to 4 double y = x + 7.0; // declares the double variable y and sets it to the result of x added to 7.0 (x is promoted to a double) def z = x + y; // declares the def variable z and sets it to the result of x added to y (x is promoted to a double) def a = z + x; // declares the def variable a and sets it to the result of z added to x (x is promoted to def at compile-time and double at run-time) ---- ==== Subtraction Subtracts two numerical expressions. Rules for resultant overflow and NaN values follow the Java specification. The format is an expression, followed by the minus operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- subtraction: expression '-' expression; ---- A numeric promotion may occur during a subtraction operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== ||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:* [source,Java] ---- int x = 5-4; // declares the int variable x and sets it to the result of 4 subtracted from 5 double y = x-7.0; // declares the double variable y and sets it to the result of 7.0 subtracted from x (x is promoted to a double) def z = x-y; // declares the def variable z and sets it to the result of y subtracted from x (x is promoted to a double) def a = z-x; // declares the def variable a and sets it to the result of x subtracted from z (x is promoted to def at compile-time and double at run-time) ---- ==== Left Shift Shifts lower order bits to higher order bits in the left-side expression by the distance specified in the right-side expression. The format is an expression followed by two left-carrots, and a closing expression. *Grammar:* [source,ANTLR4] ---- left_shift: expression '<<' expression; ---- A numeric promotion may occur during a left shift operation to the left-side expression. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric and floating point expressions will result in an error. Promotion Table: |==== |from|to |byte|int |short|int |char|int |int|int |long|long |def|def |==== The right-side expression will be explicitly cast to an int value and truncated based on the promoted type of the left-side expression. If the left-side expression is of type int then the lowest order 5-bits will be taken as the distance to shift from the right-side expression (0-31). If the left-side expression is of type long then the lowest order 6-bits will be taken as the distance to shift from the right-side expression (0-63). Non-numeric and floating point expressions will result in an error. *Examples:* [source,Java] ---- int x = 5 << 4; // declares the int variable x and sets it to the result of 5 left shifted by 4 long y = x << 7; // declares the long variable y and sets it to the result of x left shifted by 7 (x is promoted to a long) def z = x << y; // declares the def variable z and sets it to the result of x left shifted by y def a = z << x; // declares the def variable a and sets it to the result of z left shifted by x ---- ==== Right Shift Shifts higher order bits to lower order bits in the left-side expression by the distance specified in the right-side expression. Right shift will preserve the signed bit (highest order bit) as part of the result. The format is an expression followed by two right-carrots, and a closing expression. *Grammar:* [source,ANTLR4] ---- right_shift: expression '>>' expression; ---- A numeric promotion may occur during a right shift operation to the left-side expression. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric and floating point expressions will result in an error. Promotion Table: |==== |from|to |byte|int |short|int |char|int |int|int |long|long |def|def |==== The right-side expression will be explicitly cast to an int value and truncated based on the promoted type of the left-side expression. If the left-side expression is of type int then the lowest order 5-bits will be taken as the distance to shift from the right-side expression (0-31). If the left-side expression is of type long then the lowest order 6-bits will be taken as the distance to shift from the right-side expression (0-63). Non-numeric and floating point expressions will result in an error. *Examples:* [source,Java] ---- int x = 5 >> 4; // declares the int variable x and sets it to the result of 5 right shifted by 4 long y = x >> 7; // declares the long variable y and sets it to the result of x right shifted by 7 (x is promoted to a long) def z = x >> y; // declares the def variable z and sets it to the result of x right shifted by y def a = z >> x; // declares the def variable a and sets it to the result of z right shifted by x ---- ==== Unsigned Right Shift Shifts higher order bits to lower order bits in the left-side expression by the distance specified in the right-side expression. Unsigned right shift will not preserve the signed bit (highest order bit) as part of the result. The format is an expression followed by three right-carrots, and a closing expression. *Grammar:* [source,ANTLR4] ---- unsigned_right_shift: expression '>>>' expression; ---- A numeric promotion may occur during an unsigned right shift operation to the left-side expression. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric and floating point expressions will result in an error. Promotion Table: |==== |from|to |byte|int |short|int |char|int |int|int |long|long |def|def |==== The right-side expression will be explicitly cast to an int value and truncated based on the promoted type of the left-side expression. If the left-side expression is of type int then the lowest order 5-bits will be taken as the distance to shift from the right-side expression (0-31). If the left-side expression is of type long then the lowest order 6-bits will be taken as the distance to shift from the right-side expression (0-63). Non-numeric and floating point expressions will result in an error. *Examples:* [source,Java] ---- int x = 5 >> 4; // declares the int variable x and sets it to the result of 5 unsigned right shifted by 4 long y = x >> 7; // declares the long variable y and sets it to the result of x unsigned right shifted by 7 (x is promoted to a long) def z = x >> y; // declares the def variable z and sets it to the result of x unsigned right shifted by y def a = z >> x; // declares the def variable a and sets it to the result of z unsigned right shifted by x ---- ==== Greater Than Greater than compares two numerical expressions where a resultant boolean value will be true if the left-side expression is a larger value than the right-side expression otherwise false. The format is an expression, followed by the right angle operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- greater_than: expression '>' expression; ---- A numeric promotion may occur during a greater than operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== ||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:* [source,Java] ---- boolean x = 5 > 4; // declares the int variable x and sets it to the result of 5 greater than 4 double y = 7.0; // declares the double variable y and sets it to the double constant 7.0 def z = y > 6.5; // declares the def variable z and sets it to the result of y greater than 6.5 def a = y > x; // declares the def variable a and sets it to the result of y greater than z (x is promoted to double at compile-time) ---- ==== Greater Than Or Equal Greater than or equal compares two numerical expressions where a resultant boolean value will be true if the left-side expression is a larger value than or equal to the right-side expression otherwise false. The format is an expression, followed by the right angle and equals operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- greater_than_or_equal: expression '>=' expression; ---- A numeric promotion may occur during a greater than or equal operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== ||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:* [source,Java] ---- boolean x = 5 >= 4; // declares the int variable x and sets it to the result of 5 greater than or equal to 4 double y = 7.0; // declares the double variable y and sets it to the double constant 7.0 def z = y >= 6.5; // declares the def variable z and sets it to the result of y greater than or equal to 6.5 def a = y >= x; // declares the def variable a and sets it to the result of y greater than or equal to z (x is promoted to double at compile-time) ---- ==== Less Than Less than compares two numerical expressions where a resultant boolean value will be true if the left-side expression is a smaller value than the right-side expression otherwise false. The format is an expression, followed by the left angle operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- less_than: expression '<' expression; ---- A numeric promotion may occur during a less than operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== ||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:* [source,Java] ---- boolean x = 5 < 4; // declares the int variable x and sets it to the result of 5 less than 4 double y = 7.0; // declares the double variable y and sets it to the double constant 7.0 def z = y < 6.5; // declares the def variable z and sets it to the result of y less than 6.5 def a = y < x; // declares the def variable a and sets it to the result of y less than z (x is promoted to double at compile-time) ---- ==== Less Than Or Equal Less than or equal compares two numerical expressions where a resultant boolean value will be true if the left-side expression is a larger value than or equal to the right-side expression otherwise false. The format is an expression, followed by the left angle and equals operator, and a closing expression. *Grammar:* [source,ANTLR4] ---- less_than_or_equal: expression '<=' expression; ---- A numeric promotion may occur during a less than or equal operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-numeric expressions will result in an error. Promotion Table: |==== ||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:* [source,Java] ---- boolean x = 5 <= 4; // declares the int variable x and sets it to the result of 5 less than or equal to 4 double y = 7.0; // declares the double variable y and sets it to the double constant 7.0 def z = y <= 6.5; // declares the def variable z and sets it to the result of y less than or equal to 6.5 def a = y <= x; // declares the def variable a and sets it to the result of y less than or equal to z (x is promoted to double at compile-time) ---- ==== Instance Of The instanceof operator can be used to compare a variable's type to a specified reference type where a resultant boolean value is true if the variable type is the same as or a descendant of the specified reference type and false otherwise. The format is an id, followed by the instanceof operator, and finished with a type. *Grammar:* [source,ANTLR4] ---- instance_of: ID 'instanceof' TYPE; ---- *Examples:* [source,Java] ---- Map x = new HashMap(); // declares the Map variable x and sets it to a newly allocated HashMap List y = new ArrayList(); // declares the List variable y and sets it to a newly allocated ArrayList def z = y; // declares the def variable z and sets it to y boolean a = x instanceof HashMap; // declares the boolean variable a and sets it to true since x's type is the same type as HashMap boolean b = y instanceof Map; // declares the boolean variable b and sets it to false since y's type is not the same type as Map or a descendant of Map boolean c = z instanceof List; // declares the boolean variable c and sets it to true since z's type is a descendant of the type List ---- ==== Equality Equals Equality equals compares two expressions where a resultant boolean value is true if the two expressions are equal and false otherwise. When reference types are compared using this operator the equivalent of the equals member method will be called against the first expression, where the second expression is the argument. Though the equals member method is used for reference types, this operation will always be null-safe. Valid comparisons are between boolean types, primitive numeric types, and reference types. If a comparison is made that is not listed as one of the valid comparisons an error will occur. The format is an expression, followed by the equals-equals operator, and finished with an expression. *Grammar:* [source,ANTLR4] ---- equality_equals: expression '==' expression; ---- A numeric type promotion may occur during a primitive numeric comparison. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Promotion Table: |==== ||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:* [source,Java] ---- boolean b0 = true; // declares the boolean variable b0 and sets it the constant boolean true boolean b1 = false; // declares the boolean variable b1 and sets it the constant boolean false int i = 2; // declares the int variable i and sets it the constant int 2 float f = 2.0f; // declares the float variable f and sets it the constant float 2.0 List l0 = new ArrayList(); // declares the List variable l0 and sets it to a newly allocated ArrayList ArrayList l1 = new ArrayList(); // declares the ArrayList variable l1 and sets it to a newly allocated ArrayList def di0 = 2; // declares the def variable di0 and sets it the constant int 2 def di1 = 3; // declares the def variable di1 and sets it the constant int 3 def dl = new ArrayList(); // declares the def variable dl and sets it to a newly allocated ArrayList boolean result; // declares the boolean variable result result = b0 == b1; // compares b0 to b1 and has a boolean result of false result = i == f; // compares i to f where i is promoted to float and has a boolean result of true result = b0 == i; // ERROR: a comparison between a boolean and a primitive numeric type is illegal result = i == l0; // ERROR: a comparison between a primitive numeric type and a reference type is illegal l0.add(1); // adds a constant int 1 to the List l0 l1.add(1); // adds a constant int 1 to the ArrayList l1 result = l0 == l1; // compares l0 to l1 using l0.equals(l1) and has a boolean result of true l0.add(1); // adds a constant int 1 to the List l0 result = l0 == l1; // compares l0 to l1 using l0.equals(l1) and has a boolean result of false result = di0 == di1; // compares di0 to di1 and has a boolean result of false result = di0 == i; // compares di0 to i where i is promoted to def and has a boolean result of true dl.add(1); // adds a constant int 1 to the def ArrayList dl result = dl == l0; // compares dl to l0 using dl.equals(l0) with a boolean result of true result = null == dl; // compares null to dl with a boolean result of false result = l1 == null; // compares l1 to null with a boolean result of false ---- ==== Equality Not Equals Equality not equals compares two expressions where a resultant boolean value is true if the two expressions are not equal and false otherwise. When reference types are compared using this operator the equivalent of the equals member method will be called against the first expression, where the second expression is the argument, with the resultant boolean being reversed. Though the equals member method is used for reference types, this operation will always be null-safe. Valid comparisons are between boolean types, primitive numeric types, and reference types. If a comparison is made that is not listed as one of the valid comparisons an error will occur. The format is an expression, followed by the bang-equals operator, and finished with an expression. *Grammar:* [source,ANTLR4] ---- equality_not_equals: expression '!=' expression; ---- A numeric type promotion may occur during a primitive numeric comparison. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Promotion Table: |==== ||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:* [source,Java] ---- boolean b0 = true; // declares the boolean variable b0 and sets it the constant boolean true boolean b1 = false; // declares the boolean variable b1 and sets it the constant boolean false int i = 2; // declares the int variable i and sets it the constant int 2 float f = 2.0f; // declares the float variable f and sets it the constant float 2.0 List l0 = new ArrayList(); // declares the List variable l0 and sets it to a newly allocated ArrayList ArrayList l1 = new ArrayList(); // declares the ArrayList variable l1 and sets it to a newly allocated ArrayList def di0 = 2; // declares the def variable di0 and sets it the constant int 2 def di1 = 3; // declares the def variable di1 and sets it the constant int 3 def dl = new ArrayList(); // declares the def variable dl and sets it to a newly allocated ArrayList boolean result; // declares the boolean variable result result = b0 != b1; // compares b0 to b1 and has a boolean result of true result = i != f; // compares i to f where i is promoted to float and has a boolean result of false result = b0 != i; // ERROR: a comparison between a boolean and a primitive numeric type is illegal result = i != l0; // ERROR: a comparison between a primitive numeric type and a reference type is illegal l0.add(1); // adds a constant int 1 to the List l0 l1.add(1); // adds a constant int 1 to the ArrayList l1 result = l0 != l1; // compares l0 to l1 using l0.equals(l1) and has a boolean result of false l0.add(1); // adds a constant int 1 to the List l0 result = l0 != l1; // compares l0 to l1 using l0.equals(l1) and has a boolean result of true result = di0 != di1; // compares di0 to di1 and has a boolean result of true result = di0 != i; // compares di0 to i where i is promoted to def and has a boolean result of false dl.add(1); // adds a constant int 1 to the def ArrayList dl result = dl != l0; // compares dl to l0 using dl.equals(l0) with a boolean result of false result = null != dl; // compares null to dl with a boolean result of true result = l1 != null; // compares null to l1 with a boolean result of true ---- ==== Identity Equals Identity equals compares two expressions where a resultant boolean value is true if the two expressions are equal and false otherwise. Two primitive types are considered to be equal if they have the same value. Two reference types are considered to be equal if they refer to the exact same instance in memory or are both null. Valid comparisons are between boolean types, primitive numeric types, and reference types. If a comparison is made that is not listed as one of the valid comparisons an error will occur. The format is an expression, followed by the equals-equals-equals operator, and finished with an expression. *Grammar:* [source,ANTLR4] ---- identity_equals: expression '===' expression; ---- A numeric type promotion may occur during a primitive numeric comparison. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Promotion Table: |==== ||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:* [source,Java] ---- boolean b0 = true; // declares the boolean variable b0 and sets it the constant boolean true boolean b1 = false; // declares the boolean variable b1 and sets it the constant boolean false int i = 2; // declares the int variable i and sets it the constant int 2 float f = 2.0f; // declares the float variable f and sets it the constant float 2.0 List l0 = new ArrayList(); // declares the List variable l0 and sets it to a newly allocated ArrayList ArrayList l1 = new ArrayList(); // declares the ArrayList variable l1 and sets it to a newly allocated ArrayList List l2 = l1; // declares the List variable l2 and sets it to l1 def di0 = 2; // declares the def variable di0 and sets it the constant int 2 def di1 = 3; // declares the def variable di1 and sets it the constant int 3 def dl = l0; // declares the def variable dl and sets it to l0 boolean result; // declares the boolean variable result result = b0 === b1; // compares b0 to b1 and has a boolean result of false result = i === f; // compares i to f where i is promoted to float and has a boolean result of true result = b0 === i; // ERROR: a comparison between a boolean and a primitive numeric type is illegal result = i === l0; // ERROR: a comparison between a primitive numeric type and a reference type is illegal l0.add(1); // adds a constant int 1 to the List l0 l1.add(1); // adds a constant int 1 to the ArrayList l1 result = l0 === l1; // compares l0 to l1 and has a boolean result of false l0.add(1); // adds a constant int 1 to the List l0 result = l0 === l1; // compares l0 to l1 and has a boolean result of false result = l1 === l2; // compares l1 to l2 and has a boolean result of true result = di0 === di1; // compares di0 to di1 and has a boolean result of false result = di0 === i; // compares di0 to i where i is promoted to def and has a boolean result of true result = dl === l0; // compares dl to l0 with a boolean result of true result = null === dl; // compares null to dl with a boolean result of false result = l1 === null; // compares null to l1 with a boolean result of false ---- ==== Identity Not Equals Identity not equals compares two expressions where a resultant boolean value is true if the two expressions are not equal and false otherwise. Two primitive types are considered to be not equal if they have different values. Two reference types are considered to be not equal if they refer to the different instances in memory or one is null and the other is not. Valid comparisons are between boolean types, primitive numeric types, and reference types. If a comparison is made that is not listed as one of the valid comparisons an error will occur. The format is an expression, followed by the bang-equals-equals operator, and finished with an expression. *Grammar:* [source,ANTLR4] ---- identity_not_equals: expression '!==' expression; ---- A numeric type promotion may occur during a primitive numeric comparison. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Promotion Table: |==== ||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:* [source,Java] ---- boolean b0 = true; // declares the boolean variable b0 and sets it the constant boolean true boolean b1 = false; // declares the boolean variable b1 and sets it the constant boolean false int i = 2; // declares the int variable i and sets it the constant int 2 float f = 2.0f; // declares the float variable f and sets it the constant float 2.0 List l0 = new ArrayList(); // declares the List variable l0 and sets it to a newly allocated ArrayList ArrayList l1 = new ArrayList(); // declares the ArrayList variable l1 and sets it to a newly allocated ArrayList List l2 = l1; // declares the List variable l2 and sets it to l1 def di0 = 2; // declares the def variable di0 and sets it the constant int 2 def di1 = 3; // declares the def variable di1 and sets it the constant int 3 def dl = l0; // declares the def variable dl and sets it to l0 boolean result; // declares the boolean variable result result = b0 !== b1; // compares b0 to b1 and has a boolean result of true result = i !== f; // compares i to f where i is promoted to float and has a boolean result of false result = b0 !== i; // ERROR: a comparison between a boolean and a primitive numeric type is illegal result = i !== l0; // ERROR: a comparison between a primitive numeric type and a reference type is illegal l0.add(1); // adds a constant int 1 to the List l0 l1.add(1); // adds a constant int 1 to the ArrayList l1 result = l0 !== l1; // compares l0 to l1 and has a boolean result of true l0.add(1); // adds a constant int 1 to the List l0 result = l0 !== l1; // compares l0 to l1 and has a boolean result of true result = l1 !== l2; // compares l1 to l2 and has a boolean result of false result = di0 !== di1; // compares di0 to di1 and has a boolean result of true result = di0 !== i; // compares di0 to i where i is promoted to def and has a boolean result of false result = dl !== l0; // compares dl to l0 with a boolean result of false result = null !== dl; // compares null to dl with a boolean result of true result = l1 !== null; // compares null to l1 with a boolean result of true ---- ==== Bitwise And Bitwise and will and together two integer type expressions. The table below shows what each resultant bit will in the resultant integer type value be based on the corresponding bit in each integer type expression. |==== ||1|0 |1|1|0 |0|0|0 |==== The format starts with an expression, follows with the ampersand operator, and finishes with an expression. *Grammar:* [source,ANTLR4] ---- bitwise_and: expression '&' expression; ---- A numeric promotion may occur during a bitwise and operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-integer expressions will result in an error. Promotion Table: |==== ||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|def|def |==== *Examples:* [source,Java] ---- byte x = 16; // declares the byte variable x and sets it to a constant int 1 int y = x & 4; // declares the int variable y and sets it to the result of x and 4 long z = y & x; // declares the long variable z and sets it the result of y and x def d = z & 2; // declares the def variable d and sets it the result of z and 2 def e; // declares the def variable e e = d & z; // sets e to the result of d and z ---- ==== Boolean Xor Boolean xor will xor together two boolean expressions. The table below shows what the resultant boolean value will be based on the two boolean expressions. |==== ||true|false |true|false|true |false|true|false |==== The format starts with an expression, follows with the carrot operator, and finishes with an expression. *Grammar:* [source,ANTLR4] ---- boolean_xor: expression '^' expression; ---- Note that def types will be assumed to be of the boolean type. Any def type evaluated at run-time that does not represent a boolean will result in an error. Non-boolean expressions will result in an error. *Examples:* [source,Java] ---- boolean x = false; // declares the boolean variable x and sets the constant boolean false boolean y = x ^ true; // declares the boolean variable y and sets it the result of x xor true def z = y ^ x; // declares the def variable z and sets it to the result of y xor x ---- ==== Bitwise Xor Bitwise xor will xor together two integer type expressions. The table below shows what each resultant bit will in the resultant integer type value be based on the corresponding bit in each integer type expression. |==== ||1|0 |1|0|1 |0|1|0 |==== The format starts with an expression, follows with the carrot operator, and finishes with an expression. *Grammar:* [source,ANTLR4] ---- bitwise_xor: expression '^' expression; ---- A numeric promotion may occur during a bitwise xor operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-integer expressions will result in an error. Promotion Table: |==== ||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|def|def |==== *Examples:* [source,Java] ---- byte x = 16; // declares the byte variable x and sets it to a constant int 1 int y = x ^ 4; // declares the int variable y and sets it to the result of x xor 4 long z = y ^ x; // declares the long variable z and sets it the result of y xor x def d = z ^ 2; // declares the def variable d and sets it the result of z xor 2 def e; // declares the def variable e e = d ^ z; // sets e to the result of d xor z ---- ==== Bitwise Or Bitwise or will or together two integer type expressions. The table below shows what each resultant bit will in the resultant integer type value be based on the corresponding bit in each integer type expression. |==== ||1|0 |1|1|1 |0|1|0 |==== The format starts with an expression, follows with the pipe operator, and finishes with an expression. *Grammar:* [source,ANTLR4] ---- bitwise_or: expression '|' expression; ---- A numeric promotion may occur during a bitwise xor operation. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Non-integer expressions will result in an error. Promotion Table: |==== ||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|def|def |==== *Examples:* [source,Java] ---- byte x = 16; // declares the byte variable x and sets it to a constant int 1 int y = x | 4; // declares the int variable y and sets it to the result of x or 4 long z = y | x; // declares the long variable z and sets it the result of y or x def d = z | 2; // declares the def variable d and sets it the result of z or 2 def e; // declares the def variable e e = d | z; // sets e to the result of d or z ---- ==== Boolean And Boolean and will and together two boolean expressions. If the first expression is found to be false then it is known that the result will also be false, so evaluation of the second expression will be skipped. The table below shows what the resultant boolean value will be based on the two boolean expressions. ||true|false |true|true|false |false|false|false The format starts with an expression, follows with the ampersand-ampersand operator, and finishes with an expression. *Grammar:* [source,ANTLR4] ---- boolean_and: expression '&&' expression; ---- Note that def types will be assumed to be of the boolean type. Any def type evaluated at run-time that does not represent a boolean will result in an error. Non-boolean expressions will result in an error. *Examples:* [source,Java] ---- boolean x = false; // declares the boolean variable x and sets the constant boolean false boolean y = x && true; // declares the boolean variable y and sets it the result of x and true def z = y && x; // declares the def variable z and sets it to the result of y and x ---- ==== Boolean Or Boolean or will or together two boolean expressions. If the first expression is found to be true then it is known that the result will also be true, so evaluation of the second expression will be skipped. The table below shows what the resultant boolean value will be based on the two boolean expressions. |==== ||true|false |true|true|true |false|true|false |==== The format starts with an expression, follows with the pipe-pipe operator, and finishes with an expression. *Grammar:* [source,ANTLR4] ---- boolean_and: expression '||' expression; ---- Note that def types will be assumed to be of the boolean type. Any def type evaluated at run-time that does not represent a boolean will result in an error. Non-boolean expressions will result in an error. *Examples:* [source,Java] ---- boolean x = false; // declares the boolean variable x and sets the constant boolean false boolean y = x || true; // declares the boolean variable y and sets it the result of x or true def z = y || x; // declares the def variable z and sets it to the result of y or x ---- ==== Conditional A conditional operation consists of three expressions. The first expression is evaluated with an expected boolean result type. If the first expression evaluates to true then the second expression will be evaluated. If the first expression evaluates to false then the third expression will be evaluated. This can be used as a shortcut many different operations without requiring a full if/else branch. Errors will occur if the first expression does not evaluate to a boolean type or if one of the second or third expression cannot be converted to a type appropriate for the expected result. The format is an expression followed by a question-mark operator, another expression, a colon operator, and finishes with a final expression. *Grammar:* [source,ANTLR4] ---- conditional: expression '?' expression ':' expression; ---- A numeric type promotion may occur during the evaluation of a conditional with the second and third expressions if the expected result is a numeric type. A def type evaluated at run-time will follow the same promotion table at run-time following whatever type def represents. Promotion Table: |==== ||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:* [source,Java] ---- boolean b = true; // declares the boolean variable b and sets it the constant boolean true int x = b ? 1 : 2; // declares the int variable x and sets it to the int constant 1 // since the first expression of the conditional evaluates to true // so the second expression is evaluated for a result List y = x > 1 ? new ArrayList() : null; // declares the List variable y and sets it to null // since the first expression of the conditional evaluates to false // so the third expression is evaluated for a result def z = x < 2 ? true : false; // declares the def variable z and sets it to the boolean constant true // since the first expression of the conditional evaluates to true // so the second expression is evaluated for a result ---- ==== Elvis The elvis operator consists of two expressions. If the first expression is a non-null value then the resultant value will be the evaluated first expression otherwise the resultant value will be the evaluated second expression. This is typically used as a shortcut for a null check in a conditional. An error will occur if the expected result is a primitive type. The format is an expression, followed by the question-mark-colon operator, and finishes with an expression. *Grammar:* [source,ANTLR4] ---- elvis: expression '?:' expression; ---- *Examples:* [source,Java] ---- List l = new ArrayList(); // declares the List variable l and sets it to a newly allocated ArrayList List y = l ?: new ArrayList(); // declares the List variable y and sets it to l since l is not null y = null; // sets y to null def z = y ?: new HashMap(); // declares the def variable z and sets it to a newly allocated HashMap since y is null ---- ==== Assignment Assignment can be used to assign a value to a variable. See Variable Assignment [MARK] for more information. ==== Compound Assignment Compound assignment can be used as a shortcut for an assignment where a binary operation would occur between the variable/field as the left-side expression and a separate right-side expression. The variable/field and right-side expression must be of appropriate types for the specific operation or an error will occur. A downcast may be necessary for certain operations to be able to assign the result back into the variable/field and will happen implicitly. The format is a variable/field, followed by one of the compound assignment operators, finished with an expression. *Grammar:* [source,ANTLR4] ---- compund_assignment: ID (. ID)? '$=' expression; // $ is a placeholder for the operation symbol ---- A compound assignment is equivalent to the expression below where V is the variable/field and T is the type of variable/member. [source,Java] ---- V = (T)(V op expression); ---- The table below shows all available operators for compound assignment. All operators follow any casting/promotion rules according to their regular definition. |==== |Operator|Compound Symbol |Multiplication|*= |Division|/= |Remainder|%= |String Concatenation|+= |Addition|+= |Subtraction|-= |Left Shift|<<= |Right Shift|>>= |Unsigned Right Shift|>>>= |Bitwise And|&= |Boolean And|&= |Bitwise Xor|^= |Boolean Xor|^= |Bitwise Or|\|= |Boolean Or|\|= |==== *Examples:* [source,Java] ---- int i = 10; // declares the variable i and sets it to constant int 10 i *= 2; // multiplies i by 2 -- i = (int)(i * 2) i /= 5; // divides i by 5 -- i = (int)(i / 5) i %= 3; // gives the remainder for i/3 -- i = (int)(i % 3) i += 5; // adds 5 to i -- i = (int)(i + 5) i -= 5; // subtracts 5 from i -- i = (int)(i - 5) i <<= 2; // left shifts i by 2 -- i = (int)(i << 2) i >>= 1; // right shifts i by 1 -- i = (int)(i >> 1) i >>>= 1; // unsigned right shifts i by 1 -- i = (int)(i >>> 1) i &= 15; // ands i with 15 -- i = (int)(i & 15) i ^= 12; // xors i with 12 -- i = (int)(i ^ 2) i |= 4; // ors i with 4 -- i = (int)(i | 4) boolean b = true; // declares the boolean variable b and sets it to the constant boolean true b &= false; // ands b with false -- b = (boolean)(b & false) b ^= false; // xors b with false -- b = (boolean)(b & false) b |= true; // ors be with true -- b = (boolean)(b & false) def x = 'compound'; // declares the def variable x and sets it to the constant String 'compound' x += ' assignment'; // string concatenates ' assignment' to x -- x = (String)(x + ' assignment') ----