From 153d37694a4938b2f9e6c4f7015a43913ce84c8a Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 17 Apr 2018 16:45:49 -0700 Subject: [PATCH 01/55] Separate identifiers into its own section. Clean up variables. --- docs/painless/painless-identifiers.asciidoc | 29 ++++ docs/painless/painless-keywords.asciidoc | 4 +- docs/painless/painless-lang-spec.asciidoc | 2 + docs/painless/painless-literals.asciidoc | 22 +-- docs/painless/painless-operators.asciidoc | 1 + docs/painless/painless-variables.asciidoc | 170 +++++++++++--------- 6 files changed, 136 insertions(+), 92 deletions(-) create mode 100644 docs/painless/painless-identifiers.asciidoc diff --git a/docs/painless/painless-identifiers.asciidoc b/docs/painless/painless-identifiers.asciidoc new file mode 100644 index 0000000000000..4b61b4f3d62ee --- /dev/null +++ b/docs/painless/painless-identifiers.asciidoc @@ -0,0 +1,29 @@ +[[painless-identifiers]] +=== Identifiers + +Specify identifiers to <>, <>, and +<> variables, <>, and +<>. <> and +<> cannot be used as identifiers. + +*Grammar* +[source,ANTLR4] +---- +ID: [_a-zA-Z] [_a-zA-Z-0-9]*; +---- + +*Examples* + +Variations of identifiers. + +[source,Painless] +---- +a +Z +id +list +list0 +MAP25 +_map25 +Map_25 +---- diff --git a/docs/painless/painless-keywords.asciidoc b/docs/painless/painless-keywords.asciidoc index 99b5b4060d24e..cb3bafbd20f13 100644 --- a/docs/painless/painless-keywords.asciidoc +++ b/docs/painless/painless-keywords.asciidoc @@ -2,8 +2,8 @@ === Keywords The keywords in the table below are reserved for built-in language -features. These keywords cannot be used as <> or -<>. +features. These keywords cannot be used as +<> or <>. [cols="^1,^1,^1,^1,^1"] |==== diff --git a/docs/painless/painless-lang-spec.asciidoc b/docs/painless/painless-lang-spec.asciidoc index b324ad301141c..ba6595000ae2f 100644 --- a/docs/painless/painless-lang-spec.asciidoc +++ b/docs/painless/painless-lang-spec.asciidoc @@ -23,6 +23,8 @@ include::painless-keywords.asciidoc[] include::painless-literals.asciidoc[] +include::painless-identifiers.asciidoc[] + include::painless-variables.asciidoc[] include::painless-types.asciidoc[] diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index 3f91c9299c0ad..191f3adb0c923 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -28,12 +28,12 @@ Integer literals. [source,Painless] ---- -0 <1> -0D <2> -1234L <3> --90f <4> --022 <5> -0xF2A <6> +<1> 0 +<2> 0D +<3> 1234L +<4> -90f +<5> -022 +<6> 0xF2A ---- <1> `int 0` @@ -65,11 +65,11 @@ Floating point literals. [source,Painless] ---- -0.0 <1> -1E6 <2> -0.977777 <3> --126.34 <4> -89.9F <5> +<1> 0.0 +<2> 1E6 +<3> 0.977777 +<4> -126.34 +<5> 89.9F ---- <1> `double 0.0` diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index 11ee97def66ba..915d811fa441b 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -704,6 +704,7 @@ e = ~d; // sets e the negation of d 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. diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 08725b328a3c2..b63558f9a25ec 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -1,122 +1,134 @@ [[painless-variables]] === Variables -Variables in Painless must be declared and can be -statically or <>. - -[[identifiers]] -==== Identifiers - -Specify variable identifiers using the following grammar. Variable identifiers -must start with a letter or underscore. You cannot use -<> or <> as identifiers. - -*Grammar:* -[source,ANTLR4] ----- -ID: [_a-zA-Z] [_a-zA-Z-0-9]*; ----- - -*Examples:* -[source,Java] ----- -a -Z -id -list -list0 -MAP25 -_map25 ----- +<> variables to <> values for +<> in expressions. Specify variables as a +<>, <>, or +<> type. [[declaration]] ==== Declaration -Variables must be declared before you use them. The format is `type-name -identifier-name`. To declare multiple variables of the same type, specify a -comma-separated list of identifier names. You can immediately assign a value to -a variable when you declare it. +Declare variables before use with the format of <> +<>. Specify a comma-separated list of +<> following the <> +to declare multiple variables in a single statement. Use +<> combined with a declaration statement to immediately +assign a value to a variable. Variables not immediately assigned a value will +have a default value assigned implicitly based on the <>. -*Grammar:* +*Grammar* [source,ANTLR4] ---- +declaration : type ID assignment? (',' ID assignment?)*; type: ID ('[' ']')*; -declaration : type ID (',' ID)*; +assignment: '=' expression; ---- -*Examples:* -[source,Java] +*Examples* + +Different variations of variable declaration. + +[source,Painless] ---- -int x; // Declare a variable with type int and id x -List y; // Declare a variable with type List and id y -int x, y, z; // Declare variables with type int and ids x, y, and z -def[] d; // Declare the variable d with type def[] -int i = 10; // Declare the int variable i and set it to the int literal 10 +<1> int x; +<2> List y; +<3> int x, y, z; +<4> def[] d; +<5> int i = 10; ---- -[[variable-assignment]] -==== Assignment +<1> declare a variable of type `int` and identifier `x` +<2> declare a variable of type `List` and identifier `y` +<3> declare three variables of type `int` and identifiers `x`, `y`, `z` +<4> declare a variable of type `def[]` and identifier `d` +<5> declare a variable of type `int` and identifier `i`; + assign the integer literal `10` to `i` -Use the equals operator (`=`) to assign a value to a variable. The format is -`identifier-name = value`. Any value expression can be assigned to any variable -as long as the types match or the expression's type can be implicitly cast to -the variable's type. An error occurs if the types do not match. +[[assignment]] +==== Assignment -*Grammar:* +Use the `equals` operator (`=`) to assign a value to a variable. Any expression +that produces a value can be assigned to any variable as long as the +<> are the same or the resultant +<> can be implicitly <> to +the variable <>. Otherwise, an error will occur. + +Assignment of <> will cause the value to be +copied. Assignment of <> will cause the +value to be referred to with the exception of the <> +which is copied. Assignment of <> will +cause the value to be copied or referred to based on what the +<> represents. All types of assignment follow +the standard Java memory model. + +*Grammar* [source,ANTLR4] ---- assignment: ID '=' expression ---- +*Examples* -*Examples:* +Variable assignment with an <>. -Assigning a literal of the appropriate type directly to a declared variable. - -[source,Java] +[source,Painless] ---- -int i;   // Declare an int i -i = 10;  // Set the int i to the int literal 10 +<1> int i; +<2> i = 10; ---- -Immediately assigning a value when declaring a variable. +<1> declare `int i` +<2> assign a copy of `10` to `i` + +<> combined with immediate variable assignment. -[source,Java] +[source,Painless] ---- -int i = 10; // Declare the int variable i and set it the int literal 1 -double j = 2.0; // Declare the double variable j and set it to the double - // literal 2.0 +<1> int i = 10; +<2> double j = 2.0; ---- -Assigning a variable of one primitive type to another variable of the same -type. +<1> declare `int i`; assign a copy of `10` to `i` +<2> declare `double j`; assign a copy of `2.0` to `j` -[source,Java] +Assignment of one variable to another using +<>. + +[source,Painless] ---- -int i = 10; // Declare the int variable i and set it to the int literal 10 -int j = i;  // Declare the int variable j and set it to the int variable i +<1> int i = 10; +<2> int j = i; ---- -Assigning a reference type to a new heap allocation with the `new` operator. +<1> declare `int i`; assign a copy of `10` to `i` +<2> declare `int j`; assign a copy of `j` to `i` + +Assignment with reference types using the <>. -[source,Java] +[source,Painless] ---- -ArrayList l = new ArrayList();  // Declare an ArrayList variable l and set it - // to a newly allocated ArrayList -Map m = new HashMap(); // Declare a Map variable m and set it - // to a newly allocated HashMap +<1> ArrayList l = new ArrayList(); +<2> Map m = new HashMap(); ---- -Assigning a variable of one reference type to another variable of the same type. +<1> declare `ArrayList l`; assign a newly-allocated `Arraylist` to `l` +<2> declare `Map m`; assign a newly-allocated `HashMap` to `m` + with an implicit downcast -[source,Java] +Assignment of one variable to another using +<>. + +[source,Painless] ---- -List l = new ArrayList(); // Declare List variable l and set it a newly - // allocated ArrayList -List k = l;  // Declare List variable k and set it to the - // value of the List variable l -List m;                   // Declare List variable m and set it the - // default value null -m = k;                    // Set the value of List variable m to the value - // of List variable k +<1> List l = new ArrayList(); +<2> List k = l; +<3> List m; +<4> m = k; ---- + +<1> declare `List l`; assign a newly-allocated `Arraylist` to `l` + with an implicit downcast +<2> declare `List k`; assign a reference of `l` to `k` +<3> declare `List m`; +<4> assign a reference of `k` to `m` From 6729d5f821361bcccc3d9909cc7417159bb3cf23 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 18 Apr 2018 08:57:02 -0700 Subject: [PATCH 02/55] More docs. --- docs/painless/painless-comments.asciidoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/painless/painless-comments.asciidoc b/docs/painless/painless-comments.asciidoc index d1d2e47a143a6..04fec002a746f 100644 --- a/docs/painless/painless-comments.asciidoc +++ b/docs/painless/painless-comments.asciidoc @@ -1,12 +1,12 @@ [[painless-comments]] === Comments -Painless supports both single-line and multi-line comments. Comments can be -included anywhere within a script. Use the `//` token anywhere on a line to -specify a single-line comment. All characters from the `//` token to the end -of the line are ignored. Use an opening `/*` token and a closing `*/` token -to specify a multi-line comment. Multi-line comments can start anywhere on a -line, and all characters in between the `/*` token and `*/` token are ignored. +Use the `//` token anywhere on a line to specify a single-line comment. All +characters from the `//` token to the end of the line are ignored. Use an +opening `/*` token and a closing `*/` token to specify a multi-line comment. +Multi-line comments can start anywhere on a line, and all characters in between +the `/*` token and `*/` token are ignored. Comments can be included anywhere +within a script. *Grammar* [source,ANTLR4] From c2c34484efd9c811e1c0ff0a9aec7cc23378286d Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 18 Apr 2018 17:10:00 -0700 Subject: [PATCH 03/55] Modify language used to describe shallow copies. --- docs/painless/painless-variables.asciidoc | 41 ++++++++++------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index b63558f9a25ec..bf3c5437638d6 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -3,8 +3,9 @@ <> variables to <> values for <> in expressions. Specify variables as a -<>, <>, or -<> type. +<>, <>, or +<>. Variable operations follow the structure of a +standard JVM in relation to instruction execution and memory usage. [[declaration]] ==== Declaration @@ -12,10 +13,11 @@ Declare variables before use with the format of <> <>. Specify a comma-separated list of <> following the <> -to declare multiple variables in a single statement. Use -<> combined with a declaration statement to immediately -assign a value to a variable. Variables not immediately assigned a value will -have a default value assigned implicitly based on the <>. +to declare multiple variables in a single statement. Use an +<> statement combined with a declaration statement to +immediately assign a value to a variable. Variables not immediately assigned a +value will have a default value assigned implicitly based on the +<>. *Grammar* [source,ANTLR4] @@ -53,14 +55,7 @@ that produces a value can be assigned to any variable as long as the <> are the same or the resultant <> can be implicitly <> to the variable <>. Otherwise, an error will occur. - -Assignment of <> will cause the value to be -copied. Assignment of <> will cause the -value to be referred to with the exception of the <> -which is copied. Assignment of <> will -cause the value to be copied or referred to based on what the -<> represents. All types of assignment follow -the standard Java memory model. +<> values are shallow-copied when assigned. *Grammar* [source,ANTLR4] @@ -79,7 +74,7 @@ Variable assignment with an <>. ---- <1> declare `int i` -<2> assign a copy of `10` to `i` +<2> assign `10` to `i` <> combined with immediate variable assignment. @@ -89,8 +84,8 @@ Variable assignment with an <>. <2> double j = 2.0; ---- -<1> declare `int i`; assign a copy of `10` to `i` -<2> declare `double j`; assign a copy of `2.0` to `j` +<1> declare `int i`; assign `10` to `i` +<2> declare `double j`; assign `2.0` to `j` Assignment of one variable to another using <>. @@ -101,8 +96,8 @@ Assignment of one variable to another using <2> int j = i; ---- -<1> declare `int i`; assign a copy of `10` to `i` -<2> declare `int j`; assign a copy of `j` to `i` +<1> declare `int i`; assign `10` to `i` +<2> declare `int j`; assign `j` to `i` Assignment with reference types using the <>. @@ -114,7 +109,7 @@ Assignment with reference types using the <>. <1> declare `ArrayList l`; assign a newly-allocated `Arraylist` to `l` <2> declare `Map m`; assign a newly-allocated `HashMap` to `m` - with an implicit downcast + with an implicit cast to `Map` Assignment of one variable to another using <>. @@ -128,7 +123,7 @@ Assignment of one variable to another using ---- <1> declare `List l`; assign a newly-allocated `Arraylist` to `l` - with an implicit downcast -<2> declare `List k`; assign a reference of `l` to `k` + with an implicit cast to `List` +<2> declare `List k`; assign a shallow-copy of `l` to `k` <3> declare `List m`; -<4> assign a reference of `k` to `m` +<4> assign a shallow-copy of `k` to `m` From 1cdf013388f127bf8ed13ed1f891f96377a31cc6 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 18 Apr 2018 18:05:37 -0700 Subject: [PATCH 04/55] Move examples into lists to make sections flow better when multiple examples are used. --- docs/painless/painless-comments.asciidoc | 10 ++-- docs/painless/painless-identifiers.asciidoc | 4 +- docs/painless/painless-literals.asciidoc | 51 ++++++++++----------- docs/painless/painless-variables.asciidoc | 45 +++++++++--------- 4 files changed, 55 insertions(+), 55 deletions(-) diff --git a/docs/painless/painless-comments.asciidoc b/docs/painless/painless-comments.asciidoc index 04fec002a746f..588e464d97f78 100644 --- a/docs/painless/painless-comments.asciidoc +++ b/docs/painless/painless-comments.asciidoc @@ -17,17 +17,17 @@ MULTI_LINE_COMMENT: '/*' .*? '*/'; *Examples* -Single-line comments. - +* Single-line comments. ++ [source,Painless] ---- // single-line comment int value; // single-line comment ---- - -Multi-line comments. - ++ +* Multi-line comments. ++ [source,Painless] ---- /* multi- diff --git a/docs/painless/painless-identifiers.asciidoc b/docs/painless/painless-identifiers.asciidoc index 4b61b4f3d62ee..17073e3d4c415 100644 --- a/docs/painless/painless-identifiers.asciidoc +++ b/docs/painless/painless-identifiers.asciidoc @@ -14,8 +14,8 @@ ID: [_a-zA-Z] [_a-zA-Z-0-9]*; *Examples* -Variations of identifiers. - +* Variations of identifiers. ++ [source,Painless] ---- a diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index 191f3adb0c923..441cb264f1e15 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -24,8 +24,8 @@ HEX: '-'? '0' [xX] [0-9a-fA-F]+ [lL]?; *Examples* -Integer literals. - +* Integer literals. ++ [source,Painless] ---- <1> 0 @@ -35,7 +35,7 @@ Integer literals. <5> -022 <6> 0xF2A ---- - ++ <1> `int 0` <2> `double 0.0` <3> `long 1234` @@ -61,8 +61,8 @@ EXPONENT: ( [eE] [+\-]? [0-9]+ ); *Examples* -Floating point literals. - +* Floating point literals. ++ [source,Painless] ---- <1> 0.0 @@ -71,7 +71,7 @@ Floating point literals. <4> -126.34 <5> 89.9F ---- - ++ <1> `double 0.0` <2> `double 1000000.0` in exponent notation <3> `double 0.977777` @@ -81,12 +81,11 @@ Floating point literals. [[strings]] ==== Strings -Use string literals to specify string values of the -<> with either single-quotes or double-quotes. -Use a `\"` token to include a double-quote as part of a double-quoted string -literal. Use a `\'` token to include a single-quote as part of a single-quoted -string literal. Use a `\\` token to include a backslash as part of any string -literal. +Use string literals to specify <> values with +either single-quotes or double-quotes. Use a `\"` token to include a +double-quote as part of a double-quoted string literal. Use a `\'` token to +include a single-quote as part of a single-quoted string literal. Use a `\\` +token to include a backslash as part of any string literal. *Grammar* [source,ANTLR4] @@ -97,22 +96,22 @@ STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) *Examples* -String literals using single-quotes. - +* String literals using single-quotes. ++ [source,Painless] ---- 'single-quoted string literal' -'\'single-quoted string with escaped single-quotes\' and backslash \\' -'single-quoted string with non-escaped "double-quotes"' +'\'single-quoted with escaped single-quotes\' and backslash \\' +'single-quoted with non-escaped "double-quotes"' ---- - -String literals using double-quotes. - ++ +* String literals using double-quotes. ++ [source,Painless] ---- "double-quoted string literal" -"\"double-quoted string with escaped double-quotes\" and backslash: \\" -"double-quoted string with non-escaped 'single-quotes'" +"\"double-quoted with escaped double-quotes\" and backslash: \\" +"double-quoted with non-escaped 'single-quotes'" ---- [[characters]] @@ -126,16 +125,16 @@ or an error will occur. *Examples* -Casting string literals into <> values. - +* Casting string literals into <> values. ++ [source,Painless] ---- (char)"C" (char)'c' ---- - -Casting a <> value into a <> value. - ++ +* Casting a <> value into a <> value. ++ [source,Painless] ---- String s = "s"; diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index bf3c5437638d6..9756676a08b5b 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -29,8 +29,8 @@ assignment: '=' expression; *Examples* -Different variations of variable declaration. - +* Different variations of variable declaration. ++ [source,Painless] ---- <1> int x; @@ -39,7 +39,7 @@ Different variations of variable declaration. <4> def[] d; <5> int i = 10; ---- - ++ <1> declare a variable of type `int` and identifier `x` <2> declare a variable of type `List` and identifier `y` <3> declare three variables of type `int` and identifiers `x`, `y`, `z` @@ -65,55 +65,56 @@ assignment: ID '=' expression *Examples* -Variable assignment with an <>. - +* Variable assignment with an <>. ++ [source,Painless] ---- <1> int i; <2> i = 10; ---- - ++ <1> declare `int i` <2> assign `10` to `i` - -<> combined with immediate variable assignment. - ++ +* <> combined with immediate variable assignment. ++ [source,Painless] ---- <1> int i = 10; <2> double j = 2.0; ---- - ++ <1> declare `int i`; assign `10` to `i` <2> declare `double j`; assign `2.0` to `j` - -Assignment of one variable to another using ++ +* Assignment of one variable to another using <>. - ++ [source,Painless] ---- <1> int i = 10; <2> int j = i; ---- - ++ <1> declare `int i`; assign `10` to `i` <2> declare `int j`; assign `j` to `i` - -Assignment with reference types using the <>. - ++ +* Assignment with <> using the +<>. ++ [source,Painless] ---- <1> ArrayList l = new ArrayList(); <2> Map m = new HashMap(); ---- - ++ <1> declare `ArrayList l`; assign a newly-allocated `Arraylist` to `l` <2> declare `Map m`; assign a newly-allocated `HashMap` to `m` with an implicit cast to `Map` - -Assignment of one variable to another using ++ +* Assignment of one variable to another using <>. - ++ [source,Painless] ---- <1> List l = new ArrayList(); @@ -121,7 +122,7 @@ Assignment of one variable to another using <3> List m; <4> m = k; ---- - ++ <1> declare `List l`; assign a newly-allocated `Arraylist` to `l` with an implicit cast to `List` <2> declare `List k`; assign a shallow-copy of `l` to `k` From 862962be23ad4c162cd8a69d98d73054cae66781 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 19 Apr 2018 17:31:27 -0700 Subject: [PATCH 05/55] Update primitive types. --- docs/painless/painless-types.asciidoc | 228 ++++++++++++---------- docs/painless/painless-variables.asciidoc | 1 - 2 files changed, 122 insertions(+), 107 deletions(-) diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 9d575a2069ae3..295706729edf2 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -1,124 +1,111 @@ [[painless-types]] === Types -Painless supports both dynamic and static types. Static types are split into -_primitive types_ and _reference types_. - -[[dynamic-types]] -==== Dynamic Types - -Painless supports one dynamic type: `def`. The `def` type can represent any -primitive or reference type. When you use the `def` type, it mimics the exact -behavior of whatever type it represents at runtime. The default value for the -def type is `null.` - -Internally, if the `def` type represents a primitive type, it is converted to the -corresponding reference type. It still behaves like the primitive type, however, -including within the casting model. The `def` type can be assigned to different -types during the course of script execution. - -IMPORTANT: Because a `def` type variable can be assigned to different types -during execution, type conversion errors that occur when using the `def` type -happen at runtime. - -Using the `def` type can have a slight impact on performance. If performance is -critical, it's better to declare static types. - -*Examples:* -[source,Java] ----- -def x = 1; // Declare def variable x and set it to the - // literal int 1 -def l = new ArrayList(); // Declare def variable l and set it a newly - // allocated ArrayList ----- +Types are a classification of data used to describe the properties of values +operated on in expressions and statements. These properties describe what data +the value can represent such as a number, string, or something more complex and +the rules for when a value is operated on. Types are split into the following +categories: <>, +<>, and <>. [[primitive-types]] ==== Primitive Types -Primitive types are allocated directly onto the stack according to the standard -Java memory model. - -Primitive types can behave as their corresponding (<>) -reference type. This means any piece of a reference type can be accessed or -called through the primitive type. Operations performed in this manner convert -the primitive type to its corresponding reference type at runtime and perform -the field access or method call without needing to perform any other -operations. - -Painless supports the following primitive types. - -byte:: -An 8-bit, signed, two's complement integer. -Range: [-128, 127]. -Default value: 0. -Reference type: Byte. - -short:: -A 16-bit, signed, two's complement integer. -Range: [-32768, 32767]. -Default value: 0. -Reference type: Short. - -char:: -A 16-bit Unicode character. -Range: [0, 65535]. -Default value: 0 or `\u0000`. -Reference type: Character. - -int:: -A 32-bit, signed, two's complement integer. -Range: [-2^32, 2^32-1]. -Default value: 0. -Reference type: Integer. - -long:: -A 64-bit, signed, two's complement integer. -Range: [-2^64, 2^64-1]. -Default value: 0. -Reference type: Long. - -float:: -A 32-bit, single-precision, IEEE 754 floating point number. -Range: Depends on multiple factors. -Default value: 0.0. -Reference type: Float. - -double:: -A 64-bit, double-precision, IEEE 754 floating point number. -Range: Depends on multiple factors. -Default value: 0.0. -Reference type: Double. - -boolean:: -A logical quanity with two possible values: true and false. -Range: true/false. -Default value: false. -Reference type: Boolean. - - -*Examples:* -[source,Java] +Primitive types are built directly into the JVM and are allocated to non-heap +memory. Primitive type values are deep-copied when <> +and when passed into <> or function as arguments. + +Primitive types have a corresponding <> (also +known as a <>). Any member of the corresponding +<> can be <> or +<> by executing the appropriate operation on the +primitive type value. Operations performed in this manner convert (box) the +primitive type value to its corresponding <> +value at runtime and execute the specified <> or +<>. + +The following primitive types are available: + +[horizontal] +`byte`:: +8-bit, signed, two's complement integer +* range: [`-128`, `127`] +* default value: `0` +* reference type: `Byte` + +`short`:: +16-bit, signed, two's complement integer +* range: [`-32768`, `32767`] +* default value: `0` +* reference type: `Short` + +`char`:: +16-bit, unsigned, Unicode character +* range: [`0`, `65535`] +* default value: `0` or `\u0000` +* reference type: `Character` + +`int`:: +32-bit, signed, two's complement integer +* range: [`-2^32`, `2^32-1`] +* default value: `0` +* reference type: `Integer` + +`long`:: +64-bit, signed, two's complement integer +* range: [`-2^64`, `2^64-1`] +* default value: `0` +* reference type: `Long` + +`float`:: +32-bit, signed, single-precision, IEEE 754 floating point number +* default value: `0.0` +* reference type: `Float` + +`double`:: +64-bit, signed, double-precision, IEEE 754 floating point number +* default value: `0.0` +* reference type: `Double` + +`boolean`:: +logical quanity with two possible values of `true` and `false` +* default value: `false` +* reference type: `Boolean` + +*Examples* + +* Primitive types used in <> and +<>. ++ +[source,Painless] ---- -int i = 1; // Declare variable i as an int and set it to the - // literal 1 -double d; // Declare variable d as a double and set it to the - // default value of 0.0 -boolean b = true; // Declare variable b as a boolean and set it to true +<1> int i = 1; +<2> double d; +<3> boolean b = true; ---- - -Using methods from the corresponding reference type on a primitive type. - -[source,Java] ++ +<1> declare `int i`; assign `1` to `i` +<2> declare `double d` +<3> declare `boolean b`; assign `true` to `b` ++ +* Method call on a primitive type from the corresponding +<>. ++ +[source,Painless] ---- -int i = 1; // Declare variable i as an int and set it to the - // literal 1 -i.toString(); // Invokes the Integer method toString on variable i +<1> int i = 1; +<2> i.toString(); ---- ++ +<1> declare `int i`; assign `1` to `i` +<2> implicitly convert (box) `i` to the reference type `Integer`; +invoke the `Integer` method `toString` on the converted (boxed) value [[reference-types]] ==== Reference Types +<> values are shallow-copied when assigned. + Reference types are similar to Java classes and can contain multiple pieces known as _members_. However, reference types do not support access modifiers. You allocate reference type instances on the heap using the `new` operator. @@ -184,6 +171,35 @@ Integer.MAX_VALUE // a static field access Long.parseLong("123L") // a static function call ---- +[[dynamic-types]] +==== Dynamic Types + +Painless supports one dynamic type: `def`. The `def` type can represent any +primitive or reference type. When you use the `def` type, it mimics the exact +behavior of whatever type it represents at runtime. The default value for the +def type is `null.` + +Internally, if the `def` type represents a primitive type, it is converted to the +corresponding reference type. It still behaves like the primitive type, however, +including within the casting model. The `def` type can be assigned to different +types during the course of script execution. + +IMPORTANT: Because a `def` type variable can be assigned to different types +during execution, type conversion errors that occur when using the `def` type +happen at runtime. + +Using the `def` type can have a slight impact on performance. If performance is +critical, it's better to declare static types. + +*Examples:* +[source,Java] +---- +def x = 1; // Declare def variable x and set it to the + // literal int 1 +def l = new ArrayList(); // Declare def variable l and set it a newly + // allocated ArrayList +---- + [[string-type]] ==== String Type diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 9756676a08b5b..546e3928f466c 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -55,7 +55,6 @@ that produces a value can be assigned to any variable as long as the <> are the same or the resultant <> can be implicitly <> to the variable <>. Otherwise, an error will occur. -<> values are shallow-copied when assigned. *Grammar* [source,ANTLR4] From 73883ac0f41e9dc3a18b05e7c5e61efbfeb2fc81 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 23 Apr 2018 18:13:51 -0700 Subject: [PATCH 06/55] Cleaned up reference types. --- docs/painless/painless-types.asciidoc | 177 ++++++++++++++-------- docs/painless/painless-variables.asciidoc | 30 ++-- 2 files changed, 134 insertions(+), 73 deletions(-) diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 295706729edf2..1b2948bfc430a 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -11,9 +11,10 @@ categories: <>, [[primitive-types]] ==== Primitive Types -Primitive types are built directly into the JVM and are allocated to non-heap -memory. Primitive type values are deep-copied when <> -and when passed into <> or function as arguments. +Primitive types are built straight into the JVM, directly contain their data, +and are allocated to non-heap memory. Primitive type values are copied when +<> and when passed into a <> or +function as arguments. Primitive types have a corresponding <> (also known as a <>). Any member of the corresponding @@ -85,7 +86,7 @@ logical quanity with two possible values of `true` and `false` ---- + <1> declare `int i`; assign `1` to `i` -<2> declare `double d` +<2> declare `double d`; assign the default value of `0.0` to `d` <3> declare `boolean b`; assign `true` to `b` + * Method call on a primitive type from the corresponding @@ -104,72 +105,124 @@ invoke the `Integer` method `toString` on the converted (boxed) value [[reference-types]] ==== Reference Types -<> values are shallow-copied when assigned. - -Reference types are similar to Java classes and can contain multiple pieces -known as _members_. However, reference types do not support access modifiers. -You allocate reference type instances on the heap using the `new` operator. - -Reference types can have both static and non-static members: - -* Static members are shared by all instances of the same reference type and -can be accessed without allocating an instance of the reference type. For -example `Integer.MAX_VALUE`. -* Non-static members are specific to an instance of the reference type -and can only be accessed through the allocated instance. - -The default value for a reference type is `null`, indicating that no memory has -been allocated for it. When you assign `null` to a reference type, its previous -value is discarded and garbage collected in accordance with the Java memory -model as long as there are no other references to that value. - -A reference type can contain: - -* Zero to many primitive types. Primitive type members can be static or -non-static and read-only or read-write. -* Zero to many reference types. Reference type members can be static or -non-static and read-only or read-write. -* Methods that call an internal function to return a value and/or manipulate -the primitive or reference type members. Method members can be static or -non-static. -* Constructors that call an internal function to return a newly-allocated -reference type instance. Constructors are non-static methods that can -optionally manipulate the primitive and reference type members. - -Reference types support a Java-style inheritance model. Consider types A and B. -Type A is considered to be a parent of B, and B a child of A, if B inherits -(is able to access as its own) all of A's fields and methods. Type B is +Reference types are constructs (objects), potentially representing multiple +pieces of data (member fields) and logic to manipulate that data (member +methods), defined as part of the application programming interface (API) for +use in scripts. + +A reference type instance is a single set of data for one reference type +object allocated to the heap. A reference type instance is allocated using the +<>. + +Reference type values refer to reference type instances, and multiple reference +type values may refer to a single reference type instance. A change to a +reference type instance will affect all reference type values refering to that +instance. Reference type values are shallow-copied when +<> and when passed into a <> or +function as arguments. + +The default value for a <> reference type value is +`null`. <> a <> reference +type instance or <> an existing reference type instance to a +reference type value for <> later in a script. +<> `null` to a reference type value to indicate the +reference type value refers to no reference type instance. A reference type +instance will be garbage collected by the JVM when no reference type values refer +to that reference type instance. + +Reference type objects can contain member fields, member methods, and +constructors. Member fields are named and typed pieces of data that are read +and written to using the <>. Member methods are +functions decicated to a single reference type object that can manipulate +member fields and return values. Call member methods using the +<>. Constructors are a special type of function +used to allocate a reference type instance using the +<>. + +Reference type objects can have both static and non-static members (member +fields and member methods). <> and +<> static members of a reference type object without +allocating a reference type instance using the reference type object name +as the <> in place of a reference type value. +Static members are singletons per reference type object. Non-static members are +specific to a reference type instance. <> and +<> non-static members on a reference type value referring +to an allocated reference type instance. + +A reference type can contain the following: + +* zero to many <> static member fields +* zero to many <> non-static member fields +* zero to many reference type static member fields +* zero to many reference type non-static member fields +* zero to many <> static member fields +* zero to many <> non-static member fields +* zero to many static member methods +* zero to many non-static member methods +* zero to many constructors + +Reference type objects support a basic inheritance model. Consider types A and +B. Type A is considered to be a parent of B, and B a child of A, if B inherits +(is able to access as its own) all of A's non-static members. Type B is considered a descendant of A if there exists a recursive parent-child relationship from B to A with none to many types in between. In this case, B -inherits all of A's fields and methods along with all of the fields and -methods of the types in between. Type B is also considered to be a type A -in both relationships. +inherits all of A's non-static members along with all of the non-static members +of the types in between. Type B is also considered to be a type A in both +relationships. -For the complete list of Painless reference types and their supported methods, -see the https://www.elastic.co/guide/en/elasticsearch/reference/current/painless-api-reference.html[Painless API Reference]. - -For more information about working with reference types, see -<> and <>. +*Examples* -*Examples:* -[source,Java] +* Reference types used in several different <>. ++ +[source,Painless] ---- -ArrayList al = new ArrayList(); // Declare variable al as an ArrayList and - // set it to a newly allocated ArrayList -List l = new ArrayList(); // Declare variable l as a List and set - // it to a newly allocated ArrayList, which is - // allowed because ArrayList inherits from List -Map m; // Declare variable m as a Map and set it - // to the default value of null +<1> List l = new ArrayList(); +<2> l.add(1); +<3> int i = l.get(0) + 2; ---- - -Directly accessing static pieces of a reference type. - -[source,Java] ++ +<1> declare `List l`; + assign a new `ArrayList` to `l` +<2> call non-static member method `add` on l with arguments of `1` +<3> declare `int i`; + call non-static member method `get` on `l` with arguments `0`; + add `1` to `2`; + assign `3` to `i` ++ +* Sharing a reference type instance. ++ +[source,Painless] +---- +<1> List l0 = new ArrayList(); +<2> List l1 = l0; +<3> l0.add(1); +<4> l1.add(2); +<5> int i = l1.get(0) + l0.get(1); +---- ++ +<1> declare `List l0`; + assign a new `ArrayList` to `l0` +<2> declare `List l1`; + assign a shallow-copy of `l0` to `l1` +<3> call non-static member method `add` on l0 with arguments of `1` +<4> call non-static member method `add` on l1 with arguments of `2` +<5> note `l0` and `l1` refer to the same reference type instance; + call non-static member method `get` on `l1` with arguments `0`; + call non-static member method `get` on `l0` with arguments `1`; + add `1` to `2`; + assign `3` to `i`; ++ +* Using the static members of a reference type. ++ +[source,Painless] ---- -Integer.MAX_VALUE // a static field access -Long.parseLong("123L") // a static function call +<1> Integer.MAX_VALUE +<2> Long.parseLong("123L") ---- ++ +<1> access static field `MAX_VALUE` on reference type `Integer` +<2> call static member method `parseLong` on reference type `Long` with + arguments `long 123` [[dynamic-types]] ==== Dynamic Types diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 546e3928f466c..c9461f9c88b5e 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -72,7 +72,8 @@ assignment: ID '=' expression <2> i = 10; ---- + -<1> declare `int i` +<1> declare `int i`; + assign default value `0` to `i` <2> assign `10` to `i` + * <> combined with immediate variable assignment. @@ -83,8 +84,10 @@ assignment: ID '=' expression <2> double j = 2.0; ---- + -<1> declare `int i`; assign `10` to `i` -<2> declare `double j`; assign `2.0` to `j` +<1> declare `int i`; + assign `10` to `i` +<2> declare `double j`; + assign `2.0` to `j` + * Assignment of one variable to another using <>. @@ -95,8 +98,10 @@ assignment: ID '=' expression <2> int j = i; ---- + -<1> declare `int i`; assign `10` to `i` -<2> declare `int j`; assign `j` to `i` +<1> declare `int i`; + assign `10` to `i` +<2> declare `int j`; + assign `j` to `i` + * Assignment with <> using the <>. @@ -107,9 +112,10 @@ assignment: ID '=' expression <2> Map m = new HashMap(); ---- + -<1> declare `ArrayList l`; assign a newly-allocated `Arraylist` to `l` -<2> declare `Map m`; assign a newly-allocated `HashMap` to `m` - with an implicit cast to `Map` +<1> declare `ArrayList l`; + assign a newly-allocated `Arraylist` to `l` +<2> declare `Map m`; + assign a newly-allocated `HashMap` to `m` with an implicit cast to `Map` + * Assignment of one variable to another using <>. @@ -122,8 +128,10 @@ assignment: ID '=' expression <4> m = k; ---- + -<1> declare `List l`; assign a newly-allocated `Arraylist` to `l` - with an implicit cast to `List` -<2> declare `List k`; assign a shallow-copy of `l` to `k` +<1> declare `List l`; + assign a newly-allocated `Arraylist` to `l` with an implicit cast to `List` +<2> declare `List k`; + assign a shallow-copy of `l` to `k` <3> declare `List m`; + assign default value `null` to `m` <4> assign a shallow-copy of `k` to `m` From 7dfb034996bccb635809db0e714550d18fa41737 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 24 Apr 2018 13:35:08 -0700 Subject: [PATCH 07/55] Clean up dynamic types. --- docs/painless/painless-types.asciidoc | 72 ++++++++++++++++----------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 1b2948bfc430a..fe5a399957cce 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -16,14 +16,14 @@ and are allocated to non-heap memory. Primitive type values are copied when <> and when passed into a <> or function as arguments. -Primitive types have a corresponding <> (also +Primitive types have corresponding <> (also known as a <>). Any member of the corresponding <> can be <> or <> by executing the appropriate operation on the -primitive type value. Operations performed in this manner convert (box) the -primitive type value to its corresponding <> -value at runtime and execute the specified <> or -<>. +primitive type value. Operations performed in this manner convert +(<>) the primitive type value to its corresponding +<> value at runtime and execute the specified +<> or <>. The following primitive types are available: @@ -121,14 +121,15 @@ instance. Reference type values are shallow-copied when <> and when passed into a <> or function as arguments. -The default value for a <> reference type value is -`null`. <> a <> reference -type instance or <> an existing reference type instance to a -reference type value for <> later in a script. -<> `null` to a reference type value to indicate the +The default value for a <> reference type +<> is `null`. <> a +<> reference type instance or +<> an existing reference type instance to a reference type +<> for <> later in a +script. <> `null` to a reference type value to indicate the reference type value refers to no reference type instance. A reference type -instance will be garbage collected by the JVM when no reference type values refer -to that reference type instance. +instance will be garbage collected by the JVM when no reference type values +refer to that reference type instance. Reference type objects can contain member fields, member methods, and constructors. Member fields are named and typed pieces of data that are read @@ -227,31 +228,42 @@ relationships. [[dynamic-types]] ==== Dynamic Types -Painless supports one dynamic type: `def`. The `def` type can represent any -primitive or reference type. When you use the `def` type, it mimics the exact -behavior of whatever type it represents at runtime. The default value for the -def type is `null.` +Dynamic types can represent values of any primitive type or reference type +under a single type name `def`. The `def` type mimics the behavior of whatever +value is currently represented. -Internally, if the `def` type represents a primitive type, it is converted to the -corresponding reference type. It still behaves like the primitive type, however, -including within the casting model. The `def` type can be assigned to different -types during the course of script execution. +Internally, if a `def` type value is a primitive type value, the value is +converted (<>) to the corresponding reference type +instance. However, the `def` type still behaves like the primitive type +including within the <>. -IMPORTANT: Because a `def` type variable can be assigned to different types -during execution, type conversion errors that occur when using the `def` type -happen at runtime. +The default value for a <> `def` type +<> is `null`. A `def` type +<> can have different types +<> throughout a script. -Using the `def` type can have a slight impact on performance. If performance is -critical, it's better to declare static types. +<> using the `def` type will generate +errors at *runtime* if an inappropriate type is used. Using the `def` type can +have a slight impact on performance. Use only primitive types and reference +types directly when performance is critical. -*Examples:* +*Examples* + +* General uses of the `def` type. ++ [source,Java] ---- -def x = 1; // Declare def variable x and set it to the - // literal int 1 -def l = new ArrayList(); // Declare def variable l and set it a newly - // allocated ArrayList +<1> def i = 1; +<2> def l = new ArrayList(); +<3> l = i; ---- ++ +<1> declare `def i`; + assign `1` to `i` +<2> declare `def l`; + assign a new `ArrayList` to `l` +<3> assign `i` to `l`; + note the switch in type from `ArrayList` to `int` [[string-type]] ==== String Type From 75f14989df9b1539245e7a555f518b994123959e Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 25 Apr 2018 09:34:20 -0700 Subject: [PATCH 08/55] String and void type clean up. --- docs/painless/painless-types.asciidoc | 71 +++++++++++++++------------ 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index fe5a399957cce..cf08697f00aa3 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -85,9 +85,12 @@ logical quanity with two possible values of `true` and `false` <3> boolean b = true; ---- + -<1> declare `int i`; assign `1` to `i` -<2> declare `double d`; assign the default value of `0.0` to `d` -<3> declare `boolean b`; assign `true` to `b` +<1> declare `int i`; + assign `1` to `i` +<2> declare `double d`; + assign the default value of `0.0` to `d` +<3> declare `boolean b`; + assign `true` to `b` + * Method call on a primitive type from the corresponding <>. @@ -98,9 +101,10 @@ logical quanity with two possible values of `true` and `false` <2> i.toString(); ---- + -<1> declare `int i`; assign `1` to `i` +<1> declare `int i`; + assign `1` to `i` <2> implicitly convert (box) `i` to the reference type `Integer`; -invoke the `Integer` method `toString` on the converted (boxed) value + call the non-static member method `toString` on the converted (boxed) value [[reference-types]] ==== Reference Types @@ -112,7 +116,7 @@ use in scripts. A reference type instance is a single set of data for one reference type object allocated to the heap. A reference type instance is allocated using the -<>. +<>. Reference type values refer to reference type instances, and multiple reference type values may refer to a single reference type instance. A change to a @@ -138,7 +142,7 @@ functions decicated to a single reference type object that can manipulate member fields and return values. Call member methods using the <>. Constructors are a special type of function used to allocate a reference type instance using the -<>. +<>. Reference type objects can have both static and non-static members (member fields and member methods). <> and @@ -184,7 +188,7 @@ relationships. + <1> declare `List l`; assign a new `ArrayList` to `l` -<2> call non-static member method `add` on l with arguments of `1` +<2> call non-static member method `add` on `l` with arguments of `1` <3> declare `int i`; call non-static member method `get` on `l` with arguments `0`; add `1` to `2`; @@ -243,15 +247,15 @@ The default value for a <> `def` type <> throughout a script. <> using the `def` type will generate -errors at *runtime* if an inappropriate type is used. Using the `def` type can -have a slight impact on performance. Use only primitive types and reference -types directly when performance is critical. +errors at runtime if an inappropriate type is represented. Using the `def` +type can have a slight impact on performance. Use only primitive types and +reference types directly when performance is critical. *Examples* * General uses of the `def` type. + -[source,Java] +[source,Painless] ---- <1> def i = 1; <2> def l = new ArrayList(); @@ -268,33 +272,38 @@ types directly when performance is critical. [[string-type]] ==== String Type -A `String` is a specialized reference type that is immutable and does not have -to be explicitly allocated. You can directly assign to a `String` without first -allocating it with the `new` keyword. (Strings can be allocated with the `new` -keyword, but it's not required.) +The `String` type is a specialized reference type that does not require +explicit allocation. Use <> to directly +<> or <> on `String` values. +While not required, the <> can allocate +`String` values. -When assigning a value to a `String`, you must enclose the text in single or -double quotes. Strings are allocated according to the standard Java Memory Model. -The default value for a `String` is `null.` +*Examples* +[source,Painless] -*Examples:* -[source,Java] +* General use of the `String` type. ++ ---- -String r = "some text"; // Declare String r and set it to the - // String "some text" -String s = 'some text'; // Declare String s and set it to the - // String 'some text' -String t = new String("some text"); // Declare String t and set it to the - // String "some text" -String u; // Declare String u and set it to the - // default value null +<1> String r = "some text"; +<2> String s = 'some text'; +<3> String t = new String("some text"); +<4> String u; ---- ++ +<1> declare `String r`; + assign `"some text"` to `r` +<2> declare `String s`; + assign `'some text'` to `s` +<3> declare `String t`; + assign new `String` with arguments `"some text"` to `t` +<4> declare `String u`; + assign the default value of `null` to `u` [[void-type]] ==== void Type -The `void` type represents the concept of no type. In Painless, `void` declares -that a function has no return value. +The `void` type represents the concept of a lack of type. The `void` type is +primarily used to indicate a function will return no value. [[array-type]] ==== Array Type From bce78ed2c9b290ba6d78a142ba2367e1b7c6298a Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sat, 28 Apr 2018 12:40:49 -0700 Subject: [PATCH 09/55] Fixes. --- docs/painless/painless-types.asciidoc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index cf08697f00aa3..3825c13cd407a 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -69,7 +69,7 @@ The following primitive types are available: * reference type: `Double` `boolean`:: -logical quanity with two possible values of `true` and `false` +logical quantity with two possible values of `true` and `false` * default value: `false` * reference type: `Boolean` @@ -308,6 +308,9 @@ primarily used to indicate a function will return no value. [[array-type]] ==== Array Type +Array types are a specialized reference type that contain a series of elements + + Arrays contain a series of elements of the same type that can be allocated simultaneously. Painless supports both single and multi-dimensional arrays for all types except void (including `def`). From e82a1e0eb523ce5d413726ba0023af62fd65cc84 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 30 Apr 2018 17:02:01 -0700 Subject: [PATCH 10/55] Clean up types section. --- docs/painless/painless-operators.asciidoc | 46 ++++++++- docs/painless/painless-types.asciidoc | 114 +++++++++++++--------- docs/painless/painless-variables.asciidoc | 48 +++++++-- 3 files changed, 149 insertions(+), 59 deletions(-) diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index 915d811fa441b..d80a6699680e0 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -240,6 +240,7 @@ operator. See Function Calls [MARK] for more information. 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 `{}` @@ -248,9 +249,49 @@ 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. -For more information about allocating and initializing arrays, see <>. +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. @@ -727,6 +768,7 @@ 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. diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 3825c13cd407a..c936d903ffdf1 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -120,7 +120,7 @@ object allocated to the heap. A reference type instance is allocated using the Reference type values refer to reference type instances, and multiple reference type values may refer to a single reference type instance. A change to a -reference type instance will affect all reference type values refering to that +reference type instance will affect all reference type values referring to that instance. Reference type values are shallow-copied when <> and when passed into a <> or function as arguments. @@ -279,10 +279,10 @@ While not required, the <> can allocate `String` values. *Examples* -[source,Painless] * General use of the `String` type. + +[source,Painless] ---- <1> String r = "some text"; <2> String s = 'some text'; @@ -305,58 +305,76 @@ While not required, the <> can allocate The `void` type represents the concept of a lack of type. The `void` type is primarily used to indicate a function will return no value. -[[array-type]] -==== Array Type - -Array types are a specialized reference type that contain a series of elements - - -Arrays contain a series of elements of the same type that can be allocated -simultaneously. Painless supports both single and multi-dimensional arrays for -all types except void (including `def`). +*Examples* -You declare an array by specifying a type followed by a series of empty brackets, -where each set of brackets represents a dimension. Declared arrays have a default -value of `null` and are themselves a reference type. +* Use of the `void` type in a function. ++ +[source,Painless] +---- +void addToList(List l, def d) { + l.add(d); +} +---- -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. +[[array-type]] +==== Array Type -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. +The array type is a specialized reference type where an array type instance +represents a series of values. All values in an array type instance are of +the same type. Each value is assigned an index from within the range +`[0, length)` where length is the total number of values allocated for the +array type instance. Specify the type of values and the length during an +array allocation. + +Allocate an array type instance using the <> or the +<>. Array type instances are +allocated to the heap. <> and <> +array type variables for <> within scripts. The +default value for newly-declared array instance types is `null`. Array type +values are shallow-copied when <> and when passed into a +<> or function as arguments. Read and write to individual +values within the array type instance using the <>. + +When an array type instance is allocated with multiple dimensions using the +range `[2, d]` where `d >= 2`, each dimension in the range `[1, d-1]` is also +an array type. The array type of each dimension, `n`, is an array type with the +number of dimensions equal to `d-n`. For example, consider `int[][][]` with 3 +dimensions. The 3rd dimension, `d-3`, is the primitive type `int`. The 2nd +dimension, `d-2`, is the array type `int[]`. And the 1st dimension, `d-1` is +the array type `int[][]`. -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. +*Examples* -*Grammar:* -[source,ANTLR4] +* General use of single-dimensional arrays. ++ +[source,Painless] ---- -declare_array: TYPE ('[' ']')+; - -array_initialization: 'new' TYPE '[' ']' '{' expression (',' expression) '}' - | 'new' TYPE '[' ']' '{' '}'; +<1> int[] x; +<2> float[] y = new float[10]; +<3> def z = new float[5]; +<4> y[9] = 1.0F; +<5> z[0] = y[9]; ---- - -*Examples:* -[source,Java] ++ +<1> declare `int[] x` +<2> declare `float[] y`; + assign a newly-allocated array type of `float` to `y` +<3> declare `def z`; + assign a newly-allocated array type of `float` to `z` +<4> assign `1.0F` to the 9th index of `y` +<5> assign the value of 9th index of `y` to the 0th index of `z` ++ +* Use of a multi-dimensional array. ++ +[source,Painless] ---- -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 +<1> int[][][] ia3 = new int[2][3][4]; +<2> ia3[1][2][3] = 99; +<3> int i = ia3[1][2][3]; ---- ++ +<1> declare `int[][][] ia`; + assign a newly-allocated 3-dimensional array type of `int` to `ia3` +<2> assign `99` to the 3rd index of the 2nd index of the 1st index of `ia3` +<3> assign the value of the 3rd index of the 2nd index of the 1st index + of `ia3` to `i` \ No newline at end of file diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index c9461f9c88b5e..08d4f58a82323 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -11,13 +11,15 @@ standard JVM in relation to instruction execution and memory usage. ==== Declaration Declare variables before use with the format of <> -<>. Specify a comma-separated list of -<> following the <> -to declare multiple variables in a single statement. Use an -<> statement combined with a declaration statement to -immediately assign a value to a variable. Variables not immediately assigned a -value will have a default value assigned implicitly based on the -<>. +<>. Declare <> +variables using an opening `[` token and a closing `]` token for each +dimension directly after the <>. Specify a +comma-separated list of <> following the +<> to declare multiple variables in a single statement. +Use an <> statement combined with a declaration +statement to immediately assign a value to a variable. Variables not +immediately assigned a value will have a default value assigned implicitly +based on the <>. *Grammar* [source,ANTLR4] @@ -36,16 +38,20 @@ assignment: '=' expression; <1> int x; <2> List y; <3> int x, y, z; -<4> def[] d; +<4> def d; <5> int i = 10; +<6> float[] f; +<7> Map[][] m; ---- + <1> declare a variable of type `int` and identifier `x` <2> declare a variable of type `List` and identifier `y` <3> declare three variables of type `int` and identifiers `x`, `y`, `z` -<4> declare a variable of type `def[]` and identifier `d` +<4> declare a variable of type `def` and identifier `d` <5> declare a variable of type `int` and identifier `i`; assign the integer literal `10` to `i` +<6> declare a 1-dimensional array type variable of `float` and identifier `f` +<7> declare a 2-dimensional array type variable of `Map` and identifier `m` [[assignment]] ==== Assignment @@ -135,3 +141,27 @@ assignment: ID '=' expression <3> declare `List m`; assign default value `null` to `m` <4> assign a shallow-copy of `k` to `m` ++ +* Assignment with the <> using the +<>. ++ +[source,Painless] +---- +<1> int[] ia1; +<2> ia1 = new int[2]; +<3> ia1[0] = 1; +<4> int[] ib1 = ia1; +<5> int[][] ic2 = new int[2][5]; +<6> ic2[0][0] = 2; +<7> ic2[0] = ia1; +---- ++ +<1> declare `int[] ia1` +<2> assign a newly-allocated 1-dimensional array type of `int` to `ia1` +<3> assign `1` to the 0th index of `ia1` +<4> declare `int[] ib1`; + assign a shallow-copy of `ia1` to `ib1` +<5> declare `int[][] ic2`; + assign a newly-allocated 2-dimensional array type of `int` to `ic2` +<6> assign `2` to the 0th index of the 0th index of `ic2` +<7> assign a shallow-copy of `ia1` to the 0th index of `ic2` \ No newline at end of file From 8bc0c748f0edacbd0d5782bc79cc855136b01f10 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 3 May 2018 17:12:31 -0700 Subject: [PATCH 11/55] Some casting and example clean up. --- docs/painless/painless-casting.asciidoc | 129 +++++++++++++++------- docs/painless/painless-types.asciidoc | 45 ++++---- docs/painless/painless-variables.asciidoc | 65 ++++++----- 3 files changed, 150 insertions(+), 89 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index ec4f9919bd043..e7b90e94c1884 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -1,65 +1,110 @@ [[painless-casting]] === Casting -Casting is the conversion of one type to another. Implicit casts are casts that -occur automatically, such as during an assignment operation. Explicit casts are -casts where you use the casting operator to explicitly convert one type to -another. This is necessary during operations where the cast cannot be inferred. - -To cast to a new type, precede the expression by the new type enclosed in -parentheses, for example -`(int)x`. - -The following sections specify the implicit casts that can be performed and the -explicit casts that are allowed. The only other permitted cast is casting -a single character `String` to a `char`. - -*Grammar:* +A cast is the conversion of the value of one type to the equivalent value of an +inferred or specified type. Implicit casts are an inferred operation that +automatically convert values between types within a statement or +<> when necessary. Explicit casts are a +specified operation that forcefully convert values between types and are +required when an appropriate type for a statement or +<> cannot be inferred. If there exists no +equivalent value for the type converted to during a cast operation an error +will occur. If an implicit cast is given but an explicit cast is required an +error will occur. + +*Grammar* [source,ANTLR4] ---- cast: '(' TYPE ')' expression ---- +*Examples* + +* General casts. ++ +[source,Painless] +---- +<1> int i = (int)5L; +<2> Map m = new HashMap(); +<3> HashMap hm = (HashMap)m; +---- ++ +<1> declare `int i`; + explicitly cast `long 5` to `int`; + assign `5` to `i` +<2> declare `Map m`; + implicit cast new `HashMap` to `Map`; + assign `Map` value to `m` +<3> declare `HashMap hm`; + explicit cast `Map m` to `HashMap`; + assign `Map` value to `hm` + [[numeric-casting]] ==== Numeric Casting -The following table shows the allowed implicit and explicit casts between -numeric types. Read the table by row. To find out if you need to explicitly -cast from type A to type B, find the row for type A and scan across to the -column for type B. +A numeric cast is the conversion of the value of one +<> to the equivalent value of an inferred or +specified <>. Casts between values of +<> will result in data loss when the value of +the type converted from is larger than the equivalent value of the type +converted to can accommodate. Casts between values of integral types and values +of floating point types will result in precision loss when the value of the +integral type converted from is unable to accurately represent the equivalent +value of the floating point type converted to and vice versa. -IMPORTANT: Explicit casts between numeric types can result in some data loss. A -smaller numeric type cannot necessarily accommodate the value from a larger -numeric type. You might also lose precision when casting from integer types -to floating point types. +The table below illustrates legal casts between values of +<> and if the cast must be explicit. Each cast +is read as a conversion of row to column. |==== -| | byte | short | char | int | long | float | double -| byte | | implicit | implicit | implicit | implicit | implicit | implicit -| short | explicit | | explicit | implicit | implicit | implicit | implicit -| char | explicit | explicit | | implicit | implicit | implicit | implicit -| int | explicit | explicit | explicit | | implicit | implicit | implicit -| long | explicit | explicit | explicit | explicit | | implicit | implicit -| float | explicit | explicit | explicit | explicit | explicit | | implicit +| | byte | short | char | int | long | float | double +| byte | | implicit | implicit | implicit | implicit | implicit | implicit +| short | explicit | | explicit | implicit | implicit | implicit | implicit +| char | explicit | explicit | | implicit | implicit | implicit | implicit +| int | explicit | explicit | explicit | | implicit | implicit | implicit +| long | explicit | explicit | explicit | explicit | | implicit | implicit +| float | explicit | explicit | explicit | explicit | explicit | | implicit | double | explicit | explicit | explicit | explicit | explicit | explicit | |==== +*Examples* -Example(s) -[source,Java] +* Valid numeric casts. ++ +[source,Painless] +---- +<1> int a = 1; +<2> long b = a; +<3> short c = (short)b; +<4> double e = (double)a; +---- ++ +<1> declare `int a`; + assign `1` to `a` +<2> declare `long b`; + implicit cast `long b` to `int`; + assign `int` value to `b` +<3> declare `short c`; + explicit cast `long b` to `short`; + assign `short` value to `c` +<4> declare `double e`; + explicit cast `int a` to `double`; + assign `double` value to `e`; + note this cast is extraneous and can be implicit ++ +* Invalid numeric casts resulting in errors. ++ +[source,Painless] ---- -int a = 1; // Declare int variable a and set it to the literal - // value 1 -long b = a; // Declare long variable b and set it to int variable - // a with an implicit cast to convert from int to long -short c = (short)b; // Declare short variable c, explicitly cast b to a - // short, and assign b to c -byte d = a; // ERROR: Casting an int to a byte requires an explicit - // cast -double e = (double)a; // Explicitly cast int variable a to a double and assign - // it to the double variable e. The explicit cast is - // allowed, but it is not necessary. +<1> int a = 1.0; +<2> int b = 2; +<3> byte c = b; ---- ++ +<1> declare `int i`; + *error*: cannot implicitly cast `double 1.0` to `int` +<2> declare `int b`; + assign `int 2` to `b`; [[reference-casting]] ==== Reference Casting diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index c936d903ffdf1..465c53ac1d931 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -17,7 +17,7 @@ and are allocated to non-heap memory. Primitive type values are copied when function as arguments. Primitive types have corresponding <> (also -known as a <>). Any member of the corresponding +known as <>). Any member of the corresponding <> can be <> or <> by executing the appropriate operation on the primitive type value. Operations performed in this manner convert @@ -86,11 +86,11 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign `1` to `i` + assign `int 1` to `i` <2> declare `double d`; - assign the default value of `0.0` to `d` + assign the default value `double 0.0` to `d` <3> declare `boolean b`; - assign `true` to `b` + assign `boolean true` to `b` + * Method call on a primitive type from the corresponding <>. @@ -102,9 +102,9 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign `1` to `i` -<2> implicitly convert (box) `i` to the reference type `Integer`; - call the non-static member method `toString` on the converted (boxed) value + assign `int 1` to `i` +<2> box `i` to `Integer`; + return `String '1'` from call `toString` [[reference-types]] ==== Reference Types @@ -187,12 +187,14 @@ relationships. ---- + <1> declare `List l`; - assign a new `ArrayList` to `l` -<2> call non-static member method `add` on `l` with arguments of `1` + implicit cast `new Arraylist` to `List`; + assign to `l` +<2> call `add` on `l` with arguments `(box int 1)` <3> declare `int i`; - call non-static member method `get` on `l` with arguments `0`; - add `1` to `2`; - assign `3` to `i` + return `Integer 1` from call `get` on `l` with arguments `(int 0)`; + unbox Integer `1`; + add `int 1` and `int 2`; + assign to `i` + * Sharing a reference type instance. + @@ -206,16 +208,19 @@ relationships. ---- + <1> declare `List l0`; - assign a new `ArrayList` to `l0` + implicit cast `new ArrayList` to `List`; + assign to `l0` <2> declare `List l1`; - assign a shallow-copy of `l0` to `l1` -<3> call non-static member method `add` on l0 with arguments of `1` -<4> call non-static member method `add` on l1 with arguments of `2` + assign shallow-copy of `l0` to `l1` +<3> call `add` on `l0` with arguments `(box int 1)` +<4> call `add` on `l1` with arguments `(box int 2)` <5> note `l0` and `l1` refer to the same reference type instance; - call non-static member method `get` on `l1` with arguments `0`; - call non-static member method `get` on `l0` with arguments `1`; - add `1` to `2`; - assign `3` to `i`; + return `Integer 1` from call `get` on `l1` with arguments `(int 0)`; + unbox `Integer 1`; + return `Integer 2` from call get` on `l0` with arguments `(int 1)`; + unbox `Integer 2`; + add `int 1` and `int 2`; + assign to `i`; + * Using the static members of a reference type. + diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 08d4f58a82323..719f088f3a487 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -44,14 +44,22 @@ assignment: '=' expression; <7> Map[][] m; ---- + -<1> declare a variable of type `int` and identifier `x` -<2> declare a variable of type `List` and identifier `y` -<3> declare three variables of type `int` and identifiers `x`, `y`, `z` -<4> declare a variable of type `def` and identifier `d` -<5> declare a variable of type `int` and identifier `i`; - assign the integer literal `10` to `i` -<6> declare a 1-dimensional array type variable of `float` and identifier `f` -<7> declare a 2-dimensional array type variable of `Map` and identifier `m` +<1> declare `int x`; + assign default value `null` to `x` +<2> declare `List y`; + assign default value `null` to `y` +<3> declare `int x`, `int y`, and int `z`; + assign default value `int 0` to `x`; + assign default value `int 0` to `y`; + assign default value `int 0` to `z`; +<4> declare `def d`; + assign default value `null` to `d` +<5> declare `int i`; + assign `int 10` to `i` +<6> declare `float[] f`; + assign default value `null` to `f` +<7> declare `Map[][] m`; + assign default value `null` to `m` [[assignment]] ==== Assignment @@ -60,7 +68,7 @@ Use the `equals` operator (`=`) to assign a value to a variable. Any expression that produces a value can be assigned to any variable as long as the <> are the same or the resultant <> can be implicitly <> to -the variable <>. Otherwise, an error will occur. +the variable <>. *Grammar* [source,ANTLR4] @@ -79,8 +87,8 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign default value `0` to `i` -<2> assign `10` to `i` + assign default value `int 0` to `i` +<2> assign `int 10` to `i` + * <> combined with immediate variable assignment. + @@ -91,9 +99,9 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign `10` to `i` + assign `int 10` to `i` <2> declare `double j`; - assign `2.0` to `j` + assign `double 2.0` to `j` + * Assignment of one variable to another using <>. @@ -105,7 +113,7 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign `10` to `i` + assign `int 10` to `i` <2> declare `int j`; assign `j` to `i` + @@ -119,9 +127,10 @@ assignment: ID '=' expression ---- + <1> declare `ArrayList l`; - assign a newly-allocated `Arraylist` to `l` + assign `new Arraylist` to `l` <2> declare `Map m`; - assign a newly-allocated `HashMap` to `m` with an implicit cast to `Map` + implicit cast `new HashMap` to `Map`; + assign to `m` + * Assignment of one variable to another using <>. @@ -135,12 +144,13 @@ assignment: ID '=' expression ---- + <1> declare `List l`; - assign a newly-allocated `Arraylist` to `l` with an implicit cast to `List` + implicit cast `new ArrayList` to `List`; + assign to `l` <2> declare `List k`; - assign a shallow-copy of `l` to `k` + assign shallow-copy of `l` to `k`; <3> declare `List m`; assign default value `null` to `m` -<4> assign a shallow-copy of `k` to `m` +<4> assign shallow-copy of `k` to `m` + * Assignment with the <> using the <>. @@ -152,16 +162,17 @@ assignment: ID '=' expression <3> ia1[0] = 1; <4> int[] ib1 = ia1; <5> int[][] ic2 = new int[2][5]; -<6> ic2[0][0] = 2; +<6> ic2[1][3] = 2; <7> ic2[0] = ia1; ---- + -<1> declare `int[] ia1` -<2> assign a newly-allocated 1-dimensional array type of `int` to `ia1` -<3> assign `1` to the 0th index of `ia1` +<1> declare `int[] ia1`; + assign default value `null` to `ia1` +<2> assign `new 1-d int array` to `ia1` with length `[2]` +<3> assign `int 1` to index `[0]` of `ia1` <4> declare `int[] ib1`; - assign a shallow-copy of `ia1` to `ib1` + assign shallow-copy of `ia1` to `ib1` <5> declare `int[][] ic2`; - assign a newly-allocated 2-dimensional array type of `int` to `ic2` -<6> assign `2` to the 0th index of the 0th index of `ic2` -<7> assign a shallow-copy of `ia1` to the 0th index of `ic2` \ No newline at end of file + assign `new 2-d int array` to `ic2` with length `[2, 5]` +<6> assign `int 2` to index `[1, 3]` of `ic2` +<7> assign shallow-copy of `ia1` to index `[0]` of `ic2`; \ No newline at end of file From 00ba531061b0d6cc1019d1f4eb02f5f51543579d Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Fri, 4 May 2018 15:58:05 -0700 Subject: [PATCH 12/55] Updated examples. --- docs/painless/painless-casting.asciidoc | 13 ++- docs/painless/painless-literals.asciidoc | 25 ++---- docs/painless/painless-types.asciidoc | 105 ++++++++++++---------- docs/painless/painless-variables.asciidoc | 77 +++++++++------- 4 files changed, 124 insertions(+), 96 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index e7b90e94c1884..5ae4fb9c45630 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -105,6 +105,7 @@ is read as a conversion of row to column. *error*: cannot implicitly cast `double 1.0` to `int` <2> declare `int b`; assign `int 2` to `b`; +<3> exist [[reference-casting]] ==== Reference Casting @@ -159,6 +160,16 @@ int c = (int)x; // Declare int variable c, explicitly cast def variable x to an // int, and assign x to c ---- +[[character-string-casting]] +==== Character-String Casting +* Casting a <> value into a <> value. ++ +[source,Painless] +---- +String s = "s"; +char c = (char)s; +---- + [[boxing-unboxing]] ==== Boxing and Unboxing @@ -214,4 +225,4 @@ def x = 1; // Declare def variable x and set it to the literal int 1 through x + 2.0F // Add def variable x and the literal float 2.0. // At compile-time the types are promoted to def. // At run-time the types are promoted to float. ----- +---- \ No newline at end of file diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index 441cb264f1e15..9e536255e5f0a 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -49,8 +49,8 @@ HEX: '-'? '0' [xX] [0-9a-fA-F]+ [lL]?; Use floating point literals to specify a floating point value of the <> `float` or `double`. Use the following single letter designations to specify the <>: -`f` or `F` for `float` and `d` or `D` for `double`. If not specified, the type defaults -to `double`. +`f` or `F` for `float` and `d` or `D` for `double`. If not specified, the type +defaults to `double`. *Grammar* [source,ANTLR4] @@ -117,26 +117,19 @@ STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) [[characters]] ==== Characters -Use the <> to convert string literals or -<> values into <> values. -<> values converted into -<> values must be exactly one character in length -or an error will occur. +Character literals cannot be specified directly. Instead, use the +<> to convert <> +values into <> values. <> values +converted into <> values must be exactly one character +in length or an error will occur. *Examples* -* Casting string literals into <> values. +* <> string literals into +<> values. + [source,Painless] ---- (char)"C" (char)'c' ---- -+ -* Casting a <> value into a <> value. -+ -[source,Painless] ----- -String s = "s"; -char c = (char)s; ----- diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 465c53ac1d931..d880b0696fc49 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -86,11 +86,11 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign `int 1` to `i` + assign value of `int 1` to `i` <2> declare `double d`; - assign the default value `double 0.0` to `d` + assign default value of `double 0.0` to `d` <3> declare `boolean b`; - assign `boolean true` to `b` + assign value of `boolean true` to `b` + * Method call on a primitive type from the corresponding <>. @@ -102,9 +102,9 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign `int 1` to `i` -<2> box `i` to `Integer`; - return `String '1'` from call `toString` + assign value of `int 1` to `i` +<2> box value of `i` -> `Integer 1`; + call `toString` on `Integer 1` -> `String '1'` [[reference-types]] ==== Reference Types @@ -116,7 +116,7 @@ use in scripts. A reference type instance is a single set of data for one reference type object allocated to the heap. A reference type instance is allocated using the -<>. +<>. Reference type values refer to reference type instances, and multiple reference type values may refer to a single reference type instance. A change to a @@ -177,7 +177,7 @@ relationships. *Examples* -* Reference types used in several different <>. +* Reference types used in several different <>. + [source,Painless] ---- @@ -187,14 +187,16 @@ relationships. ---- + <1> declare `List l`; - implicit cast `new Arraylist` to `List`; - assign to `l` -<2> call `add` on `l` with arguments `(box int 1)` + allocate `ArrayList` instance -> `ArrayList`; + implicit cast value of `Arraylist` to `List` -> `List`; + assign value of `List` to `l` +<2> box value of `int 1` -> `Integer 1`; + call `add` on `l` with arguments `(Integer 1)` <3> declare `int i`; - return `Integer 1` from call `get` on `l` with arguments `(int 0)`; - unbox Integer `1`; - add `int 1` and `int 2`; - assign to `i` + call `get` on `l` with arguments `(int 0)` -> `Integer 1`; + unbox value of Integer `1` -> `int 1`; + add value of `int 1` and value of `int 2` -> `int 3`; + assign value of `int 3` to `i` + * Sharing a reference type instance. + @@ -208,31 +210,37 @@ relationships. ---- + <1> declare `List l0`; - implicit cast `new ArrayList` to `List`; - assign to `l0` + allocate `ArrayList` instance -> `ArrayList`; + implicit cast value of `ArrayList` to `List` -> `List`; + assign value of `List` to `l0` <2> declare `List l1`; - assign shallow-copy of `l0` to `l1` -<3> call `add` on `l0` with arguments `(box int 1)` -<4> call `add` on `l1` with arguments `(box int 2)` -<5> note `l0` and `l1` refer to the same reference type instance; - return `Integer 1` from call `get` on `l1` with arguments `(int 0)`; - unbox `Integer 1`; - return `Integer 2` from call get` on `l0` with arguments `(int 1)`; - unbox `Integer 2`; - add `int 1` and `int 2`; - assign to `i`; + assign shallow-copy of value of `l0` to `l1` + (note `l0` and `l1` refer to the same instance) +<3> box value of `int 1` -> `Integer 1`; + call `add` on `l0` with arguments `(Integer 1)` +<4> box value of `int 2` -> `Integer 2`; + call `add` on `l1` with arguments `(Integer 2)` +<5> call `get` on `l1` with arguments `(int 0)` -> `Integer 1`; + unbox value of `Integer 1` -> `int 1`; + call get` on `l0` with arguments `(int 1)` -> `Integer 2`; + unbox value of `Integer 2` -> `int 2`; + add `int 1` and `int 2` -> `int 3`; + assign value of `int 3` to `i`; + * Using the static members of a reference type. + [source,Painless] ---- -<1> Integer.MAX_VALUE -<2> Long.parseLong("123L") +<1> int i = Integer.MAX_VALUE; +<2> Long l = Long.parseLong("123L"); ---- + -<1> access static field `MAX_VALUE` on reference type `Integer` -<2> call static member method `parseLong` on reference type `Long` with - arguments `long 123` +<1> declare `int i`; + access `MAX_VALUE` on `Integer` -> `int 2147483647`; + assign value of `int 2147483647` to `i` +<2> declare `Long l`; + call `parseLong` on `Long` with arguments `(long 123)` -> `Long 123`; + assign shallow-copy of value of `Long 123` to `l` [[dynamic-types]] ==== Dynamic Types @@ -262,17 +270,18 @@ reference types directly when performance is critical. + [source,Painless] ---- -<1> def i = 1; -<2> def l = new ArrayList(); -<3> l = i; +<1> def dp = 1; +<2> def dr = new ArrayList(); +<3> dr = dp; ---- + -<1> declare `def i`; - assign `1` to `i` -<2> declare `def l`; - assign a new `ArrayList` to `l` -<3> assign `i` to `l`; - note the switch in type from `ArrayList` to `int` +<1> declare `def dp`; + assign value of `int 1` to `dp` +<2> declare `def dr`; + allocate `ArrayList` instance -> `ArrayList`; + assign value of `ArrayList` to `dr` +<3> assign value of `dp` to `dr`; + (note the switch in type of `dr` from `ArrayList` to `int`) [[string-type]] ==== String Type @@ -296,13 +305,15 @@ While not required, the <> can allocate ---- + <1> declare `String r`; - assign `"some text"` to `r` + assign value of `"some text"` to `r` <2> declare `String s`; - assign `'some text'` to `s` + assign value of `'some text'` to `s` <3> declare `String t`; - assign new `String` with arguments `"some text"` to `t` + allocate `String` instance with arguments `("some text")` + -> `String "some text"`; + assign value of `String "some text"` to `t` <4> declare `String u`; - assign the default value of `null` to `u` + assign default value of `null` to `u` [[void-type]] ==== void Type @@ -361,8 +372,10 @@ the array type `int[][]`. <5> z[0] = y[9]; ---- + -<1> declare `int[] x` +<1> declare `int[] x`; + assign default value of `null` to `x` <2> declare `float[] y`; + assign a newly-allocated array type of `float` to `y` <3> declare `def z`; assign a newly-allocated array type of `float` to `z` diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 719f088f3a487..5bc3f318a1f5f 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -37,7 +37,7 @@ assignment: '=' expression; ---- <1> int x; <2> List y; -<3> int x, y, z; +<3> int x, y = 5, z; <4> def d; <5> int i = 10; <6> float[] f; @@ -45,26 +45,28 @@ assignment: '=' expression; ---- + <1> declare `int x`; - assign default value `null` to `x` + assign default value of `null` to `x` <2> declare `List y`; - assign default value `null` to `y` -<3> declare `int x`, `int y`, and int `z`; - assign default value `int 0` to `x`; - assign default value `int 0` to `y`; - assign default value `int 0` to `z`; + assign default value of `null` to `y` +<3> declare `int x`; + assign default value of `int 0` to `x`; + declare `int y`; + assign value of `int 5` to `y`; + declare `int z`; + assign default value of `int 0` to `z`; <4> declare `def d`; - assign default value `null` to `d` + assign default value of `null` to `d` <5> declare `int i`; - assign `int 10` to `i` + assign value of `int 10` to `i` <6> declare `float[] f`; - assign default value `null` to `f` + assign default value of `null` to `f` <7> declare `Map[][] m`; - assign default value `null` to `m` + assign default value of `null` to `m` [[assignment]] ==== Assignment -Use the `equals` operator (`=`) to assign a value to a variable. Any expression +Use the `equals operator '='` to assign a value to a variable. Any expression that produces a value can be assigned to any variable as long as the <> are the same or the resultant <> can be implicitly <> to @@ -87,8 +89,8 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign default value `int 0` to `i` -<2> assign `int 10` to `i` + assign default value of `int 0` to `i` +<2> assign value of `int 10` to `i` + * <> combined with immediate variable assignment. + @@ -99,9 +101,9 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign `int 10` to `i` + assign value of `int 10` to `i` <2> declare `double j`; - assign `double 2.0` to `j` + assign value of `double 2.0` to `j` + * Assignment of one variable to another using <>. @@ -113,9 +115,9 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign `int 10` to `i` + assign value of `int 10` to `i` <2> declare `int j`; - assign `j` to `i` + assign value of `j` to `i` + * Assignment with <> using the <>. @@ -127,10 +129,12 @@ assignment: ID '=' expression ---- + <1> declare `ArrayList l`; - assign `new Arraylist` to `l` + allocate `ArrayList` instance -> `ArrayList`; + assign value of `ArrayList` to `l` <2> declare `Map m`; - implicit cast `new HashMap` to `Map`; - assign to `m` + allocate `HashMap` instance -> `HashMap`; + implicit cast value of `HashMap` to `Map` -> `Map`; + assign value of `Map` to `m` + * Assignment of one variable to another using <>. @@ -144,13 +148,16 @@ assignment: ID '=' expression ---- + <1> declare `List l`; - implicit cast `new ArrayList` to `List`; - assign to `l` + allocate `ArrayList` instance -> `ArrayList`; + implicit cast value of `ArrayList` to `List` -> `List`; + assign value of `List` to `l` <2> declare `List k`; - assign shallow-copy of `l` to `k`; + assign shallow-copy of value of `l` to `k`; + (note `l` and `k` refer to the same instance) <3> declare `List m`; - assign default value `null` to `m` -<4> assign shallow-copy of `k` to `m` + assign default value of `null` to `m` +<4> assign shallow-copy of value of `k` to `m`; + (note `l`, `k`, and `m` refer to the same instance) + * Assignment with the <> using the <>. @@ -167,12 +174,16 @@ assignment: ID '=' expression ---- + <1> declare `int[] ia1`; - assign default value `null` to `ia1` -<2> assign `new 1-d int array` to `ia1` with length `[2]` -<3> assign `int 1` to index `[0]` of `ia1` + assign default value of `null` to `ia1` +<2> allocate `1-d int array` instance with `length [2]` -> `1-d int array`; + assign value of `1-d int array` to `ia1` +<3> assign value of `int 1` to `index [0]` of `ia1` <4> declare `int[] ib1`; - assign shallow-copy of `ia1` to `ib1` + assign shallow-copy of value of `ia1` to `ib1`; + (note `ia1` and `ib1` refer to the same instance) <5> declare `int[][] ic2`; - assign `new 2-d int array` to `ic2` with length `[2, 5]` -<6> assign `int 2` to index `[1, 3]` of `ic2` -<7> assign shallow-copy of `ia1` to index `[0]` of `ic2`; \ No newline at end of file + allocate `2-d int array` instance with `length [2, 5]` -> `2-d int array`; + assign value of `2-d int array` to `ic2` +<6> assign value of `int 2` to `index [1, 3]` of `ic2` +<7> assign shallow-copy of value of `ia1` to `index [0]` of `ic2`; + (note `ia1`, `ib1`, and `index [0]` of `ia2` refer to the same instance) From 7bcd114ba3cc7bcf760badc0c150e37276682874 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 7 May 2018 09:15:48 -0700 Subject: [PATCH 13/55] More changes. --- docs/painless/painless-types.asciidoc | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index d880b0696fc49..7fe08ae902ebd 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -375,12 +375,14 @@ the array type `int[][]`. <1> declare `int[] x`; assign default value of `null` to `x` <2> declare `float[] y`; - - assign a newly-allocated array type of `float` to `y` + allocate `1-d float array` instance with `length [10]` + -> `1-d float array`; + assign value of `1-d float array` to `y` <3> declare `def z`; - assign a newly-allocated array type of `float` to `z` -<4> assign `1.0F` to the 9th index of `y` -<5> assign the value of 9th index of `y` to the 0th index of `z` + allocate `1-d float array` instance with `length [5]` -> `1-d float array`; + assign value of `1-d float array` to `z` +<4> assign value of `float 1.0` to `index [9]` of `y` +<5> assign value of `index [9]` of `y` to `index [0]` of `z` + * Use of a multi-dimensional array. + @@ -392,7 +394,9 @@ the array type `int[][]`. ---- + <1> declare `int[][][] ia`; - assign a newly-allocated 3-dimensional array type of `int` to `ia3` -<2> assign `99` to the 3rd index of the 2nd index of the 1st index of `ia3` -<3> assign the value of the 3rd index of the 2nd index of the 1st index - of `ia3` to `i` \ No newline at end of file + allocate `3-d int array` instance with length `[2, 3, 4]` + -> `3-d float array`; + assign value of `3-d float array` to `ia3` +<2> assign value of `int 99` to `index [1, 2, 3]` of `ia3` +<3> declare `int i`; + assign value of `index [1, 2, 3]` of `ia3` to `i` \ No newline at end of file From 68059aee13396c761e7958d2ac6fd4d2c87e28c0 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 9 May 2018 15:22:15 -0700 Subject: [PATCH 14/55] More example clean up. --- docs/painless/painless-casting.asciidoc | 47 ++++++----- docs/painless/painless-literals.asciidoc | 5 +- docs/painless/painless-types.asciidoc | 99 +++++++++++++---------- docs/painless/painless-variables.asciidoc | 47 ++++++----- 4 files changed, 115 insertions(+), 83 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 5ae4fb9c45630..11cf4eb89bd97 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -30,14 +30,18 @@ cast: '(' TYPE ')' expression ---- + <1> declare `int i`; - explicitly cast `long 5` to `int`; - assign `5` to `i` + explicit cast value of `long 5` to value of `int 5` -> `int 5`; + assign `int 5` to `i` <2> declare `Map m`; - implicit cast new `HashMap` to `Map`; - assign `Map` value to `m` + allocate `HashMap` instance -> `HashMap reference`; + implicit cast value of `HashMap reference` to value of `Map reference` + -> `Map reference`; + assign value of `Map reference` to `m` <3> declare `HashMap hm`; - explicit cast `Map m` to `HashMap`; - assign `Map` value to `hm` + access `m` -> `Map reference`; + explicit cast value of `Map reference` to value of `HashMap reference` + -> `HashMap reference`; + assign value of `HashMap reference` to `hm` [[numeric-casting]] ==== Numeric Casting @@ -80,32 +84,37 @@ is read as a conversion of row to column. ---- + <1> declare `int a`; - assign `1` to `a` + assign `int 1` to `a` <2> declare `long b`; - implicit cast `long b` to `int`; - assign `int` value to `b` + access `a` -> `int 1`; + implicit cast value of `int 1` to value of `long 1` -> `long 1`; + assign value of `long 1` to `b` <3> declare `short c`; - explicit cast `long b` to `short`; - assign `short` value to `c` + access `b` -> `long 1`; + explicit cast value of `long 1` to value of `short 1` -> `short 1`; + assign `short 1` value to `c` <4> declare `double e`; - explicit cast `int a` to `double`; - assign `double` value to `e`; - note this cast is extraneous and can be implicit + access `a` -> `int 1`; + explicit cast value of `int 1` to `double 1.0`; + assign value of `double 1.0` to `e`; + (note this cast is extraneous and can be implicit) + * Invalid numeric casts resulting in errors. + [source,Painless] ---- -<1> int a = 1.0; +<1> int a = 1.0; // error <2> int b = 2; -<3> byte c = b; +<3> byte c = b; // error ---- + <1> declare `int i`; - *error*: cannot implicitly cast `double 1.0` to `int` + *error* -> cannot implicit cast value of `double 1.0` to `int 1` <2> declare `int b`; - assign `int 2` to `b`; -<3> exist + assign `int 2` to `b` +<3> declare byte `c`; + access `b` -> `int 2`; + *error* -> cannot implicit cast value of `int 2` to `byte 2` [[reference-casting]] ==== Reference Casting diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index 9e536255e5f0a..e408365f805c1 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -119,9 +119,8 @@ STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) Character literals cannot be specified directly. Instead, use the <> to convert <> -values into <> values. <> values -converted into <> values must be exactly one character -in length or an error will occur. +values into <> values. Use only <> +values one character in length for this conversion or an error will occur. *Examples* diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 7fe08ae902ebd..6dce1f86fdbf3 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -103,8 +103,9 @@ logical quantity with two possible values of `true` and `false` + <1> declare `int i`; assign value of `int 1` to `i` -<2> box value of `i` -> `Integer 1`; - call `toString` on `Integer 1` -> `String '1'` +<2> access `i` -> `int 1`; + box value of `int 1` -> `Integer 1 reference`; + call `toString` on `Integer 1 reference` -> `String '1'` [[reference-types]] ==== Reference Types @@ -187,14 +188,17 @@ relationships. ---- + <1> declare `List l`; - allocate `ArrayList` instance -> `ArrayList`; - implicit cast value of `Arraylist` to `List` -> `List`; - assign value of `List` to `l` -<2> box value of `int 1` -> `Integer 1`; - call `add` on `l` with arguments `(Integer 1)` + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast value of `Arraylist reference` to value of `List reference` + -> `List reference`; + assign value of `List reference` to `l` +<2> access `l` -> `List reference`; + implicit cast value of `int 1` to value of `def` -> `def` + call `add` on `List reference` with arguments (`def`) <3> declare `int i`; - call `get` on `l` with arguments `(int 0)` -> `Integer 1`; - unbox value of Integer `1` -> `int 1`; + access `l` -> `List reference`; + call `get` on `List reference` with arguments (`int 0`) -> `def`; + implicit cast value of `def` to value of `int 1` -> `int 1`; add value of `int 1` and value of `int 2` -> `int 3`; assign value of `int 3` to `i` + @@ -210,21 +214,28 @@ relationships. ---- + <1> declare `List l0`; - allocate `ArrayList` instance -> `ArrayList`; - implicit cast value of `ArrayList` to `List` -> `List`; - assign value of `List` to `l0` + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast value of `ArrayList reference` to value of `List reference` + -> `List reference`; + assign value of `List reference` to `l0` <2> declare `List l1`; - assign shallow-copy of value of `l0` to `l1` - (note `l0` and `l1` refer to the same instance) -<3> box value of `int 1` -> `Integer 1`; - call `add` on `l0` with arguments `(Integer 1)` -<4> box value of `int 2` -> `Integer 2`; - call `add` on `l1` with arguments `(Integer 2)` -<5> call `get` on `l1` with arguments `(int 0)` -> `Integer 1`; - unbox value of `Integer 1` -> `int 1`; - call get` on `l0` with arguments `(int 1)` -> `Integer 2`; - unbox value of `Integer 2` -> `int 2`; - add `int 1` and `int 2` -> `int 3`; + access `l0` -> `List reference`; + assign value of `List reference` to `l1` + (note `l0` and `l1` refer to the same instance known as a shallow-copy) +<3> access `l0` -> `List reference`; + implicit cast value of `int 1` to value of `def` -> `def` + call `add` on `List reference` with arguments (`def`) +<4> access `l1` -> `List reference`; + implicit cast value of `int 2` to value of `def` -> `def` + call `add` on `List reference` with arguments (`def`) +<5> declare `int i`; + access `l0` -> `List reference`; + call `get` on `List reference` with arguments (`int 0`) -> `def @0`; + implicit cast value of `def @0` to value of `int 1` -> `int 1`; + access `l1` -> `List reference`; + call `get` on `List reference` with arguments (`int 1`) -> `def @1`; + implicit cast value of `def @1` to value of `int 2` -> `int 2`; + add value of `int 1` and value of `int 2` -> `int 3`; assign value of `int 3` to `i`; + * Using the static members of a reference type. @@ -232,15 +243,15 @@ relationships. [source,Painless] ---- <1> int i = Integer.MAX_VALUE; -<2> Long l = Long.parseLong("123L"); +<2> long l = Long.parseLong("123L"); ---- + <1> declare `int i`; access `MAX_VALUE` on `Integer` -> `int 2147483647`; assign value of `int 2147483647` to `i` -<2> declare `Long l`; - call `parseLong` on `Long` with arguments `(long 123)` -> `Long 123`; - assign shallow-copy of value of `Long 123` to `l` +<2> declare `long l`; + call `parseLong` on `Long` with arguments (`long 123`) -> `long 123`; + assign value of `long 123` to `l` [[dynamic-types]] ==== Dynamic Types @@ -278,9 +289,10 @@ reference types directly when performance is critical. <1> declare `def dp`; assign value of `int 1` to `dp` <2> declare `def dr`; - allocate `ArrayList` instance -> `ArrayList`; - assign value of `ArrayList` to `dr` -<3> assign value of `dp` to `dr`; + allocate `ArrayList` instance -> `ArrayList reference`; + assign value of `ArrayList reference` to `dr` +<3> access `dp` -> `int 1`; + assign value of `int 1` to `dr`; (note the switch in type of `dr` from `ArrayList` to `int`) [[string-type]] @@ -305,12 +317,12 @@ While not required, the <> can allocate ---- + <1> declare `String r`; - assign value of `"some text"` to `r` + assign value of `String "some text"` to `r` <2> declare `String s`; - assign value of `'some text'` to `s` + assign value of `String 'some text'` to `s` <3> declare `String t`; - allocate `String` instance with arguments `("some text")` - -> `String "some text"`; + allocate `String` instance with arguments (`String "some text"`) + -> `String "some text"`; assign value of `String "some text"` to `t` <4> declare `String u`; assign default value of `null` to `u` @@ -376,13 +388,15 @@ the array type `int[][]`. assign default value of `null` to `x` <2> declare `float[] y`; allocate `1-d float array` instance with `length [10]` - -> `1-d float array`; - assign value of `1-d float array` to `y` + -> `1-d float array reference`; + assign value of `1-d float array reference` to `y` <3> declare `def z`; - allocate `1-d float array` instance with `length [5]` -> `1-d float array`; - assign value of `1-d float array` to `z` + allocate `1-d float array` instance with `length [5]` + -> `1-d float array reference`; + assign value of `1-d float array reference` to `z` <4> assign value of `float 1.0` to `index [9]` of `y` -<5> assign value of `index [9]` of `y` to `index [0]` of `z` +<5> access `index [9]` of `y` -> `float 1.0`; + assign `float 1.0` to `index [0]` of `z` + * Use of a multi-dimensional array. + @@ -395,8 +409,9 @@ the array type `int[][]`. + <1> declare `int[][][] ia`; allocate `3-d int array` instance with length `[2, 3, 4]` - -> `3-d float array`; - assign value of `3-d float array` to `ia3` + -> `3-d float array reference`; + assign value of `3-d float array reference` to `ia3` <2> assign value of `int 99` to `index [1, 2, 3]` of `ia3` <3> declare `int i`; - assign value of `index [1, 2, 3]` of `ia3` to `i` \ No newline at end of file + access `index [1, 2, 3]` of `ia3` -> `int 99`; + assign value of `int 99` to `i` \ No newline at end of file diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 5bc3f318a1f5f..922105386b0ab 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -117,7 +117,8 @@ assignment: ID '=' expression <1> declare `int i`; assign value of `int 10` to `i` <2> declare `int j`; - assign value of `j` to `i` + access `i` -> `int 10`; + assign value of `int 10` to `j` + * Assignment with <> using the <>. @@ -129,12 +130,13 @@ assignment: ID '=' expression ---- + <1> declare `ArrayList l`; - allocate `ArrayList` instance -> `ArrayList`; - assign value of `ArrayList` to `l` + allocate `ArrayList` instance -> `ArrayList reference`; + assign value of `ArrayList reference` to `l` <2> declare `Map m`; - allocate `HashMap` instance -> `HashMap`; - implicit cast value of `HashMap` to `Map` -> `Map`; - assign value of `Map` to `m` + allocate `HashMap` instance -> `HashMap reference`; + implicit cast value of `HashMap reference` to value of `Map reference` + -> `Map reference`; + assign value of `Map reference` to `m` + * Assignment of one variable to another using <>. @@ -148,15 +150,18 @@ assignment: ID '=' expression ---- + <1> declare `List l`; - allocate `ArrayList` instance -> `ArrayList`; - implicit cast value of `ArrayList` to `List` -> `List`; - assign value of `List` to `l` + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast value of `ArrayList reference` to value of `List reference` + -> `List reference`; + assign value of `List reference` to `l` <2> declare `List k`; - assign shallow-copy of value of `l` to `k`; - (note `l` and `k` refer to the same instance) + access `l` -> `List reference`; + assign value of `List reference` to `k`; + (note `l` and `k` refer to the same instance known as a shallow-copy) <3> declare `List m`; assign default value of `null` to `m` -<4> assign shallow-copy of value of `k` to `m`; +<4> access `k` -> `List reference`; + assign value of `List reference` to `m`; (note `l`, `k`, and `m` refer to the same instance) + * Assignment with the <> using the @@ -175,15 +180,19 @@ assignment: ID '=' expression + <1> declare `int[] ia1`; assign default value of `null` to `ia1` -<2> allocate `1-d int array` instance with `length [2]` -> `1-d int array`; - assign value of `1-d int array` to `ia1` +<2> allocate `1-d int array` instance with `length [2]` + -> `1-d int array reference`; + assign value of `1-d int array reference` to `ia1` <3> assign value of `int 1` to `index [0]` of `ia1` <4> declare `int[] ib1`; - assign shallow-copy of value of `ia1` to `ib1`; - (note `ia1` and `ib1` refer to the same instance) + access `ia1` -> `1-d int array reference`; + assign value of `1-d int array reference` to `ib1`; + (note `ia1` and `ib1` refer to the same instance known as a shallow copy) <5> declare `int[][] ic2`; - allocate `2-d int array` instance with `length [2, 5]` -> `2-d int array`; - assign value of `2-d int array` to `ic2` + allocate `2-d int array` instance with `length [2, 5]` + -> `2-d int array reference`; + assign value of `2-d int array reference` to `ic2` <6> assign value of `int 2` to `index [1, 3]` of `ic2` -<7> assign shallow-copy of value of `ia1` to `index [0]` of `ic2`; +<7> access `ia1` -> `1-d int array reference`; + assign value of `1-d int array reference` to `index [0]` of `ic2`; (note `ia1`, `ib1`, and `index [0]` of `ia2` refer to the same instance) From 73a24f08c589975ec8a63f0ae94f48373ba1e035 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 9 May 2018 16:30:12 -0700 Subject: [PATCH 15/55] More casting clean up. --- docs/painless/painless-casting.asciidoc | 126 ++++++++++++++++-------- 1 file changed, 84 insertions(+), 42 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 11cf4eb89bd97..231de6a94eb81 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -43,18 +43,18 @@ cast: '(' TYPE ')' expression -> `HashMap reference`; assign value of `HashMap reference` to `hm` -[[numeric-casting]] -==== Numeric Casting +[[numeric-type-casting]] +==== Numeric Type Casting -A numeric cast is the conversion of the value of one +A numeric type cast is the conversion of the value of one <> to the equivalent value of an inferred or specified <>. Casts between values of -<> will result in data loss when the value of -the type converted from is larger than the equivalent value of the type -converted to can accommodate. Casts between values of integral types and values -of floating point types will result in precision loss when the value of the -integral type converted from is unable to accurately represent the equivalent -value of the floating point type converted to and vice versa. +numeric types will result in data loss when the value of the type converted from +is larger than the equivalent value of the type converted to can accommodate. +Casts between values of integral types and values of floating point types will +result in precision loss when the value of the integral type converted from is +unable to accurately represent the equivalent value of the floating point type +converted to and vice versa. The table below illustrates legal casts between values of <> and if the cast must be explicit. Each cast @@ -73,7 +73,7 @@ is read as a conversion of row to column. *Examples* -* Valid numeric casts. +* Valid numeric type casts. + [source,Painless] ---- @@ -97,9 +97,9 @@ is read as a conversion of row to column. access `a` -> `int 1`; explicit cast value of `int 1` to `double 1.0`; assign value of `double 1.0` to `e`; - (note this cast is extraneous and can be implicit) + (note the explicit cast is extraneous, and an implicit cast is valid) + -* Invalid numeric casts resulting in errors. +* Invalid numeric type casts resulting in errors. + [source,Painless] ---- @@ -109,44 +109,86 @@ is read as a conversion of row to column. ---- + <1> declare `int i`; - *error* -> cannot implicit cast value of `double 1.0` to `int 1` + *error* -> cannot implicit cast value of `double 1.0` to value of `int 1`; + (note an explicit cast is valid) <2> declare `int b`; assign `int 2` to `b` <3> declare byte `c`; access `b` -> `int 2`; - *error* -> cannot implicit cast value of `int 2` to `byte 2` + *error* -> cannot implicit cast value of `int 2` to value of `byte 2`; + (note an explicit cast is valid) -[[reference-casting]] -==== Reference Casting +[[reference-type-casting]] +==== Reference Type Casting -A reference type can be implicitly cast to another reference type as long as -the type being cast _from_ is a descendant of the type being cast _to_. A -reference type can be explicitly cast _to_ if the type being cast to is a -descendant of the type being cast _from_. +A reference type cast is the conversion of the value of one +<> to the equivalent value of an inferred or +specified <>. Implicit casts between +reference type values are allowed when the reference type being cast *from* +is a descendant of the reference type being cast *to*. Explicit casts between +reference type values are allowed when the reference type being cast *from* +is a descendant of the reference type being cast *to* or the reference type +being cast *to* is a descendant of the reference type being cast *from*. -*Examples:* -[source,Java] +*Examples* + +* Valid reference type casts. ++ +[source,Painless] ---- -List x; // Declare List variable x -ArrayList y = new ArrayList(); // Declare ArrayList variable y and assign it a - // newly allocated ArrayList [1] -x = y; // Assign Arraylist y to List x using an - // implicit cast -y = (ArrayList)x; // Explicitly cast List x to an ArrayList and - // assign it to ArrayList y -x = (List)y; // Set List x to ArrayList y using an explicit - // cast (the explicit cast is not necessary) -y = x; // ERROR: List x cannot be implicitly cast to - // an ArrayList, an explicit cast is required -Map m = y; // ERROR: Cannot implicitly or explicitly cast [2] - // an ArrayList to a Map, no relationship - // exists between the two types. ----- -[1] `ArrayList` is a descendant of the `List` type. -[2] `Map` is unrelated to the `List` and `ArrayList` types. - -[[def-type-casting]] -==== def Type Casting +<1> List x; +<2> ArrayList y = new ArrayList(); +<3> x = y; +<4> y = (ArrayList)x; +<5> x = (List)y; +---- ++ +<1> declare `List x`; + assign default value `null` to `x` +<2> declare `ArrayList y`; + allocate `ArrayList` instance -> `ArrayList reference`; + assign value of `ArrayList reference` to `y`; +<3> access `y` -> `ArrayList reference`; + implicit cast value of `ArrayList reference` to value of `List reference` + -> `List reference`; + assign `List reference` to `x`; + (note `ArrayList` is a descendant of `List`) +<4> access `x` -> `List reference`; + explicit cast value of `List reference` to value of `ArrayList reference` + -> `ArrayList reference`; + assign `ArrayList reference` to `y`; +<5> access `y` -> `ArrayList reference`; + explicit cast value of `ArrayList reference` to value of `List reference` + -> `List reference`; + assign `List reference` to `x`; + (note the explicit cast is extraneous, and an implicit cast is valid) ++ +* Invalid reference type casts resulting in errors. ++ +[source,Painless] +---- +<1> List x = new ArrayList(); +<2> ArrayList y = x; // error +<3> Map m = (Map)x; // error +---- ++ +<1> declare `List x`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast value of `ArrayList reference` to value of `List reference` + -> `List reference`; + assign `List reference` to `x` +<2> declare `ArrayList y`; + access `x` -> `List reference`; + *error* -> cannot implicit cast `List reference` to `ArrayList reference`; + (note an explicit is valid since `ArrayList` is a descendant of `List`) +<3> declare `ArrayList y`; + access `x` -> `List reference`; + *error* -> cannot explicit cast `List reference` to `Map reference`; + (note no cast would be valid since neither `List` nor `Map` is a descendant + of the other) + +[[dynamic-type-casting]] +==== Dynamic Type Casting All primitive and reference types can always be implicitly cast to `def`. While it is possible to explicitly cast to `def`, it is not necessary. From c3fcd67383762eab01d898b44d82adba565b83dc Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 9 May 2018 21:15:25 -0700 Subject: [PATCH 16/55] More clean up. --- docs/painless/painless-casting.asciidoc | 41 ++++++---- docs/painless/painless-types.asciidoc | 104 ++++++++++++++---------- 2 files changed, 84 insertions(+), 61 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 231de6a94eb81..9f6c95a37543d 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -46,19 +46,19 @@ cast: '(' TYPE ')' expression [[numeric-type-casting]] ==== Numeric Type Casting -A numeric type cast is the conversion of the value of one +A <> cast is the conversion of the value of one <> to the equivalent value of an inferred or specified <>. Casts between values of -numeric types will result in data loss when the value of the type converted from -is larger than the equivalent value of the type converted to can accommodate. -Casts between values of integral types and values of floating point types will -result in precision loss when the value of the integral type converted from is -unable to accurately represent the equivalent value of the floating point type -converted to and vice versa. +<> will result in data loss when the value of +the type converted from is larger than the equivalent value of the type +converted to can accommodate. Casts between values of integral types and values +of floating point types will result in precision loss when the value of the +integral type converted from is unable to accurately represent the equivalent +value of the floating point type converted to and vice versa. -The table below illustrates legal casts between values of -<> and if the cast must be explicit. Each cast -is read as a conversion of row to column. +The table below illustrates allowed casts between values of +<> and which specific casts must be explicit. +Each cast is read as a conversion of row to column. |==== | | byte | short | char | int | long | float | double @@ -73,7 +73,7 @@ is read as a conversion of row to column. *Examples* -* Valid numeric type casts. +* Valid <> casts. + [source,Painless] ---- @@ -99,7 +99,7 @@ is read as a conversion of row to column. assign value of `double 1.0` to `e`; (note the explicit cast is extraneous, and an implicit cast is valid) + -* Invalid numeric type casts resulting in errors. +* Invalid <> casts resulting in errors. + [source,Painless] ---- @@ -121,9 +121,9 @@ is read as a conversion of row to column. [[reference-type-casting]] ==== Reference Type Casting -A reference type cast is the conversion of the value of one -<> to the equivalent value of an inferred or -specified <>. Implicit casts between +A <> cast is the conversion of the value of +one <> to the equivalent value of an inferred +or specified <>. Implicit casts between reference type values are allowed when the reference type being cast *from* is a descendant of the reference type being cast *to*. Explicit casts between reference type values are allowed when the reference type being cast *from* @@ -132,7 +132,7 @@ being cast *to* is a descendant of the reference type being cast *from*. *Examples* -* Valid reference type casts. +* Valid <> casts. + [source,Painless] ---- @@ -163,7 +163,7 @@ being cast *to* is a descendant of the reference type being cast *from*. assign `List reference` to `x`; (note the explicit cast is extraneous, and an implicit cast is valid) + -* Invalid reference type casts resulting in errors. +* Invalid <> casts resulting in errors. + [source,Painless] ---- @@ -189,6 +189,13 @@ being cast *to* is a descendant of the reference type being cast *from*. [[dynamic-type-casting]] ==== Dynamic Type Casting + +A <> cast is the conversion of the value of one +<> to the equivalent value of any inferred or +specified other <> and vice versa. Implicit casts from +<> to the <>. +<>. Use reference type instances to store +and manipulate complex data. Reference type values refer to reference type instances, and multiple reference type values may refer to a single reference type instance. A change to a @@ -128,44 +129,59 @@ function as arguments. The default value for a <> reference type <> is `null`. <> a -<> reference type instance or -<> an existing reference type instance to a reference type -<> for <> later in a -script. <> `null` to a reference type value to indicate the -reference type value refers to no reference type instance. A reference type -instance will be garbage collected by the JVM when no reference type values -refer to that reference type instance. - -Reference type objects can contain member fields, member methods, and -constructors. Member fields are named and typed pieces of data that are read -and written to using the <>. Member methods are -functions decicated to a single reference type object that can manipulate -member fields and return values. Call member methods using the -<>. Constructors are a special type of function -used to allocate a reference type instance using the -<>. - -Reference type objects can have both static and non-static members (member -fields and member methods). <> and -<> static members of a reference type object without -allocating a reference type instance using the reference type object name -as the <> in place of a reference type value. -Static members are singletons per reference type object. Non-static members are -specific to a reference type instance. <> and -<> non-static members on a reference type value referring -to an allocated reference type instance. - -A reference type can contain the following: - -* zero to many <> static member fields -* zero to many <> non-static member fields -* zero to many reference type static member fields -* zero to many reference type non-static member fields -* zero to many <> static member fields -* zero to many <> non-static member fields -* zero to many static member methods -* zero to many non-static member methods -* zero to many constructors +<> reference type instance or an existing +reference type value to a reference type <> for +<> within a script. <> `null` to a +reference type <> to indicate the reference type +value refers to no reference type instance. The JVM will garbage collect a +reference type instance when no reference type values refer to that reference +type instance. + +A reference type object specifies zero-to-many of each of the following: + +static member fields:: + +Static member fields are named and <> pieces of data +specific to a single reference type object. Each reference type *object* +contains one set of data representative of its static member fields. Use the +<> in correspondence with the reference type +object name to access static member fields for reading and writing to a +specific reference type *object*. No reference type instance allocation is +necessary to use static member fields. + +non-static member fields:: + +Non-static member fields are named and <> pieces of data +specified by a reference type object. Each reference type *instance* contains +one set of data representative of its reference type object's non-static member +fields. Use the <> for reading and writing to +non-static member fields of a specific reference type *instance*. An allocated +reference type instance is required to use non-static member fields. + +static member methods:: + +Static member methods are functions specific to a single reference type +*object*. Use the <> in +correspondence with the reference type object name to invoke static member +methods. No reference type instance allocation is necessary to use static +member methods. + +non-static member methods:: + +Non-static member methods are functions specified by a reference type object +and called on a specific reference type *instance*. Non-static member methods +called on a specific reference type instance may read from and write to +non-static member fields of that specific reference type instance. Use the +<> in correspondence with a +specific reference type instance to invoke non-static member methods. An +allocated reference type instance is required to use non-static member methods. + +constructors:: + +Constructors are a special type of function specific to a reference type +*object* used to allocate reference type instances of that reference type +object. Use the <> to +allocate a reference type instance. Reference type objects support a basic inheritance model. Consider types A and B. Type A is considered to be a parent of B, and B a child of A, if B inherits @@ -189,7 +205,7 @@ relationships. + <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast value of `Arraylist reference` to value of `List reference` + implicit cast value of `ArrayList reference` to value of `List reference` -> `List reference`; assign value of `List reference` to `l` <2> access `l` -> `List reference`; From 19abc562fc1979ba8ace3a4566014a5ac84e646f Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 14 May 2018 08:48:03 -0700 Subject: [PATCH 17/55] More changes. --- docs/painless/painless-casting.asciidoc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 9f6c95a37543d..655a6720e299f 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -180,7 +180,8 @@ being cast *to* is a descendant of the reference type being cast *from*. <2> declare `ArrayList y`; access `x` -> `List reference`; *error* -> cannot implicit cast `List reference` to `ArrayList reference`; - (note an explicit is valid since `ArrayList` is a descendant of `List`) + (note an explicit cast is valid since `ArrayList` is a descendant of + `List`) <3> declare `ArrayList y`; access `x` -> `List reference`; *error* -> cannot explicit cast `List reference` to `Map reference`; @@ -192,9 +193,9 @@ being cast *to* is a descendant of the reference type being cast *from*. A <> cast is the conversion of the value of one <> to the equivalent value of any inferred or -specified other <> and vice versa. Implicit casts from -<> to the <> or vice versa. Implicit casts from +<> to the <>, `def`, are +always allowed. All primitive and reference types can always be implicitly cast to `def`. While it is possible to explicitly cast to `def`, it is not necessary. From 0cb3e66fc719d67e49e23d2174c97f469f7f78cf Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 14 May 2018 13:27:09 -0700 Subject: [PATCH 18/55] More fixes. --- docs/painless/painless-casting.asciidoc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 655a6720e299f..e7f44ec69bd60 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -193,18 +193,21 @@ being cast *to* is a descendant of the reference type being cast *from*. A <> cast is the conversion of the value of one <> to the equivalent value of any inferred or -specified other <> or vice versa. Implicit casts from +specified other <> or vice versa. + +Implicit casts from <> to the +<>, `def`, are always allowed. Explicit casts from <> to the <>, `def`, are -always allowed. +allowed but never necessary. -All primitive and reference types can always be implicitly cast to -`def`. While it is possible to explicitly cast to `def`, it is not necessary. +Implicit and explicit casts from the >, `def`, to +<> are allowed if and only if the cast would be +allowed . However, it is not always possible to implicitly cast a `def` to other primitive and reference types. An explicit cast is required if an explicit cast would normally be required between the non-def types. - *Examples:* [source,Java] ---- From 507ac487061dfd98437aa6e5f68cc99457c1c2f0 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 14 May 2018 17:16:12 -0700 Subject: [PATCH 19/55] More example clean up. --- docs/painless/painless-casting.asciidoc | 51 +++++++++++----- docs/painless/painless-types.asciidoc | 71 ++++++++++++++++++----- docs/painless/painless-variables.asciidoc | 18 +++--- 3 files changed, 103 insertions(+), 37 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index e7f44ec69bd60..2b435c4bed45c 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -20,7 +20,7 @@ cast: '(' TYPE ')' expression *Examples* -* General casts. +* Valid general casts. + [source,Painless] ---- @@ -192,24 +192,47 @@ being cast *to* is a descendant of the reference type being cast *from*. ==== Dynamic Type Casting A <> cast is the conversion of the value of one -<> to the equivalent value of any inferred or -specified other <> or vice versa. +<>, `def`, to the equivalent value of any inferred +or specified other <> or vice versa. -Implicit casts from <> to the -<>, `def`, are always allowed. Explicit casts from -<> to the <>, `def`, are +Implicit casts from <> value to a +<> value are always allowed. Explicit casts from +<> value to a <> value are allowed but never necessary. -Implicit and explicit casts from the >, `def`, to -<> are allowed if and only if the cast would be -allowed . +Implicit and explicit casts from a >, value to +<> value are allowed if and only if the cast is +normally allowed based on the current type value the +> value represents. -However, it is not always possible to implicitly cast a `def` to other -primitive and reference types. An explicit cast is required if an explicit -cast would normally be required between the non-def types. +*Examples* ++ +* Examples of casting <> to the + <>. ++ +[source,Painless] +---- +def d0 = 3; +d0 = new ArrayList(); +Object m = new HashMap(); +def d1 = m; +int i = d1.size(); +---- ++ +* Examples of casting from the <> to + <>. ++ +[source,Painless] +---- +---- ++ +* Examples of errors casting with <>. ++ +[source,Painless] +---- +---- -*Examples:* -[source,Java] +[source,Painless] ---- def x; // Declare def variable x and set it to null x = 3; // Set the def variable x to the literal 3 with an implicit diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 135c066ac1af0..46d0276021409 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -272,9 +272,11 @@ relationships. [[dynamic-types]] ==== Dynamic Types -Dynamic types can represent values of any primitive type or reference type -under a single type name `def`. The `def` type mimics the behavior of whatever -value is currently represented. +Use dynamic type values to represent the values of any primitive type or +reference type under a single type name `def`. A `def` type value mimics +the behavior of whatever value it currently represents and will always +represent the child-most descendant type value of any value when used in +<> and statements. Internally, if a `def` type value is a primitive type value, the value is converted (<>) to the corresponding reference type @@ -303,13 +305,41 @@ reference types directly when performance is critical. ---- + <1> declare `def dp`; - assign value of `int 1` to `dp` + implicit cast value of `int 1` to value of `def` -> `def`; + assign value of `def` to `dp` <2> declare `def dr`; allocate `ArrayList` instance -> `ArrayList reference`; - assign value of `ArrayList reference` to `dr` -<3> access `dp` -> `int 1`; - assign value of `int 1` to `dr`; - (note the switch in type of `dr` from `ArrayList` to `int`) + implicit cast value of `ArrayList reference` to value of `def` -> `def`; + assign value of `def` to `dr` +<3> access `dp` -> `def`; + assign value of `def` to `dr`; + (note the switch in type `dr` represents from `ArrayList` to `int`) ++ +* A `def` type value representing the child-most descendant of a value. ++ +[source,Painless] +---- +<1> Object l = new ArrayList(); +<2> def d = l; +<3> d.ensureCapacity(10); +---- ++ +<1> declare `Object l`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast value of `ArrayList reference` to value of `Object reference` + -> `Object reference`; + assign value of `Object reference` to `l` +<2> declare `def d`; + access `l` -> `Object reference`; + implicit cast value of `Object reference` to value of `def` -> `def`; + assign value of `def` to `d`; +<3> access `d` -> `def`; + implicit cast value of `def` to value of `ArrayList reference` + -> `ArrayList reference`; + call `ensureCapacity` on `ArrayList reference` with arguments (`int 10`); + (note value of `def` was implicit cast to value of `ArrayList reference` + since ArrayList` is the child-most descendant type value that the + `def` type value represents) [[string-type]] ==== String Type @@ -409,10 +439,17 @@ the array type `int[][]`. <3> declare `def z`; allocate `1-d float array` instance with `length [5]` -> `1-d float array reference`; - assign value of `1-d float array reference` to `z` -<4> assign value of `float 1.0` to `index [9]` of `y` -<5> access `index [9]` of `y` -> `float 1.0`; - assign `float 1.0` to `index [0]` of `z` + implicit cast value of `1-d float array reference` to value of `def` + -> `def`; + assign value of `def` to `z` +<4> access `y` -> `1-d float array reference`; + assign value of `float 1.0` to `index [9]` of `1-d float array reference` +<5> access `y` -> `1-d float array reference @1`; + access `index [9]` of `1-d float array reference @1` -> `float 1.0`; + access `z` -> `def`; + implicit cast value of `def` to value of `1-d float array reference @2` + -> `1-d float array reference @2` + assign `float 1.0` to `index [0]` of `1-d float array reference @2` + * Use of a multi-dimensional array. + @@ -425,9 +462,11 @@ the array type `int[][]`. + <1> declare `int[][][] ia`; allocate `3-d int array` instance with length `[2, 3, 4]` - -> `3-d float array reference`; - assign value of `3-d float array reference` to `ia3` -<2> assign value of `int 99` to `index [1, 2, 3]` of `ia3` + -> `3-d int array reference`; + assign value of `3-d int array reference` to `ia3` +<2> access `ia3` -> `3-d int array reference`; + assign value of `int 99` to `index [1, 2, 3]` of `3-d int array reference` <3> declare `int i`; - access `index [1, 2, 3]` of `ia3` -> `int 99`; + access `ia3` -> `3-d int array reference`; + access `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; assign value of `int 99` to `i` \ No newline at end of file diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 922105386b0ab..09d8898739387 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -106,7 +106,7 @@ assignment: ID '=' expression assign value of `double 2.0` to `j` + * Assignment of one variable to another using -<>. + <>. + [source,Painless] ---- @@ -121,7 +121,7 @@ assignment: ID '=' expression assign value of `int 10` to `j` + * Assignment with <> using the -<>. + <>. + [source,Painless] ---- @@ -139,7 +139,7 @@ assignment: ID '=' expression assign value of `Map reference` to `m` + * Assignment of one variable to another using -<>. + <>. + [source,Painless] ---- @@ -165,7 +165,7 @@ assignment: ID '=' expression (note `l`, `k`, and `m` refer to the same instance) + * Assignment with the <> using the -<>. + <>. + [source,Painless] ---- @@ -183,7 +183,8 @@ assignment: ID '=' expression <2> allocate `1-d int array` instance with `length [2]` -> `1-d int array reference`; assign value of `1-d int array reference` to `ia1` -<3> assign value of `int 1` to `index [0]` of `ia1` +<3> access `ia1` -> `1-d int array reference`; + assign value of `int 1` to `index [0]` of `1-d int array reference` <4> declare `int[] ib1`; access `ia1` -> `1-d int array reference`; assign value of `1-d int array reference` to `ib1`; @@ -192,7 +193,10 @@ assignment: ID '=' expression allocate `2-d int array` instance with `length [2, 5]` -> `2-d int array reference`; assign value of `2-d int array reference` to `ic2` -<6> assign value of `int 2` to `index [1, 3]` of `ic2` +<6> access `ic2` -> `2-d int array reference`; + assign value of `int 2` to `index [1, 3]` of `2-d int array reference` <7> access `ia1` -> `1-d int array reference`; - assign value of `1-d int array reference` to `index [0]` of `ic2`; + access `ic2` -> `2-d int array reference`; + assign value of `1-d int array reference` to + `index [0]` of `2-d int array reference`; (note `ia1`, `ib1`, and `index [0]` of `ia2` refer to the same instance) From 7ad4ebb92ea2d4f10a7ced0b313d59713bb68d67 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 14 May 2018 22:01:03 -0700 Subject: [PATCH 20/55] More changes. --- docs/painless/painless-casting.asciidoc | 149 +++++++++++++++++----- docs/painless/painless-literals.asciidoc | 16 +-- docs/painless/painless-types.asciidoc | 46 +++---- docs/painless/painless-variables.asciidoc | 14 +- 4 files changed, 151 insertions(+), 74 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 2b435c4bed45c..6f6f5c26f9324 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -38,7 +38,7 @@ cast: '(' TYPE ')' expression -> `Map reference`; assign value of `Map reference` to `m` <3> declare `HashMap hm`; - access `m` -> `Map reference`; + access value of `m` -> `Map reference`; explicit cast value of `Map reference` to value of `HashMap reference` -> `HashMap reference`; assign value of `HashMap reference` to `hm` @@ -86,15 +86,15 @@ Each cast is read as a conversion of row to column. <1> declare `int a`; assign `int 1` to `a` <2> declare `long b`; - access `a` -> `int 1`; + access value of `a` -> `int 1`; implicit cast value of `int 1` to value of `long 1` -> `long 1`; assign value of `long 1` to `b` <3> declare `short c`; - access `b` -> `long 1`; + access value of `b` -> `long 1`; explicit cast value of `long 1` to value of `short 1` -> `short 1`; assign `short 1` value to `c` <4> declare `double e`; - access `a` -> `int 1`; + access value of `a` -> `int 1`; explicit cast value of `int 1` to `double 1.0`; assign value of `double 1.0` to `e`; (note the explicit cast is extraneous, and an implicit cast is valid) @@ -114,7 +114,7 @@ Each cast is read as a conversion of row to column. <2> declare `int b`; assign `int 2` to `b` <3> declare byte `c`; - access `b` -> `int 2`; + access value of `b` -> `int 2`; *error* -> cannot implicit cast value of `int 2` to value of `byte 2`; (note an explicit cast is valid) @@ -148,16 +148,16 @@ being cast *to* is a descendant of the reference type being cast *from*. <2> declare `ArrayList y`; allocate `ArrayList` instance -> `ArrayList reference`; assign value of `ArrayList reference` to `y`; -<3> access `y` -> `ArrayList reference`; +<3> access value of `y` -> `ArrayList reference`; implicit cast value of `ArrayList reference` to value of `List reference` -> `List reference`; assign `List reference` to `x`; (note `ArrayList` is a descendant of `List`) -<4> access `x` -> `List reference`; +<4> access value of `x` -> `List reference`; explicit cast value of `List reference` to value of `ArrayList reference` -> `ArrayList reference`; assign `ArrayList reference` to `y`; -<5> access `y` -> `ArrayList reference`; +<5> access value of `y` -> `ArrayList reference`; explicit cast value of `ArrayList reference` to value of `List reference` -> `List reference`; assign `List reference` to `x`; @@ -178,12 +178,12 @@ being cast *to* is a descendant of the reference type being cast *from*. -> `List reference`; assign `List reference` to `x` <2> declare `ArrayList y`; - access `x` -> `List reference`; + access value of `x` -> `List reference`; *error* -> cannot implicit cast `List reference` to `ArrayList reference`; (note an explicit cast is valid since `ArrayList` is a descendant of `List`) <3> declare `ArrayList y`; - access `x` -> `List reference`; + access value of `x` -> `List reference`; *error* -> cannot explicit cast `List reference` to `Map reference`; (note no cast would be valid since neither `List` nor `Map` is a descendant of the other) @@ -212,48 +212,137 @@ normally allowed based on the current type value the + [source,Painless] ---- -def d0 = 3; -d0 = new ArrayList(); -Object m = new HashMap(); -def d1 = m; -int i = d1.size(); +<1> def d0 = 3; +<2> d0 = new ArrayList(); +<3> Object o = new HashMap(); +<4> def d1 = o; +<5> int i = d1.size(); ---- + +<1> declare `def d0`; + implicit cast value of `int 3` to `def` + assign value of `int 3` to `d0` +<2> allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast value of `ArrayList reference` to value of `def` -> `def`; + assign value of `def` to `d0` +<3> declare `Object o`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast value of `HashMap reference` to value of `Object reference` + -> `Object reference`; + assign value of `Object reference` to `o` +<4> declare `def d1`; + access value of `o` -> `Object reference`; + implicit cast value of `Object reference` to value of `def` -> `def`; + assign `def` to `d1` +<5> declare `int i`; + access value of `d1` -> `def`; + implicit cast value of `def` to value of `HashMap reference` + -> HashMap reference`; + call `size` on `HashMap reference` -> `int 0`; + assign `int 0` to `i`; + (note value of `def` was implicit cast to value of `HashMap reference` + since `HashMap` is the child-most descendant type value that the + `def` type value represents) ++ * Examples of casting from the <> to <>. + [source,Painless] ---- +<1> def d = 1.0; +<2> int i = (int)d; +<3> d = 1; +<4> float f = d; +<5> d = new ArrayList(); +<6> List l = d; ---- + +<1> declare `def d`; + implicit cast value of `double 1.0` to value of `def` -> `def`; + assign value of `def` to `d` +<2> declare `int i`; + access value of `d` -> `def`; + implicit cast value of `def` to value of `double 1.0` -> `double 1.0`; + explicit cast value of `double 1.0` to value of `int 1` -> `int 1`; + assign value of `int 1` to `i`; + (note the explicit cast is necessary since a `double` value cannot be + converted to an `int` value implicitly) +<3> assign value of `int 1` to `d`; + (note the switch in the type `d` represents from `double` to `int`) +<4> declare `float i`; + access value of `d` -> `def`; + implicit cast value of `def` to value of `int 1` -> `int 1`; + implicit cast value of `int 1` to value of `float 1.0` -> `float 1.0`; + assign value of `float 1.0` to `f` +<5> allocate `ArrayList` instance -> `ArrayList reference`; + assign value of `ArrayList reference` to `d`; + (note the switch in the type `d` represents from `int` to `ArrayList`) +<6> declare `List l`; + access value of `d` -> `def`; + implicit cast value of `def` to value of `ArrayList reference` + -> `ArrayList reference`; + implicit cast value of `ArrayList reference` to value of `List reference` + -> `List reference`; + assign value of `List reference` to `l` ++ * Examples of errors casting with <>. + [source,Painless] ---- +<1> def d = 1; +<2> short s = d; // error +<3> d = new HashMap(); +<4> List l = d; // error ---- +<1> declare `def d`; + implicit cast value of `int 1` to value of `def` -> `def`; + assign value of `def` to `d` +<2> declare `short s`; + access value of `d` -> `def`; + implicit cast value of `def` to value of `int 1` -> `int 1`; + *error* -> cannot implicit cast value of `int 1` to value of `short 1`; + (note an explicit cast is valid) +<3> allocate `HashMap` instance -> `HashMap reference`; + implicit cast value of `HashMap reference` to value of `def` -> `def`; + assign value of `def` to `d` +<4> declare `List l`; + access value of `d` -> `def`; + implicit cast value of `def` to value of `HashMap reference`; + *error* -> cannot implicit cast `HashMap reference` to `List reference`; + (note no cast would be valid since neither `HashMap` nor `List` is a + descendant of the other) + +[[string-character-casting]] +==== String to Character Casting + +Use the <> to convert +<> values into <> values. Use only +<> values one character in length for this conversion or +an error will occur. +*Examples* + +* Casting <> into <> values. ++ [source,Painless] ---- -def x; // Declare def variable x and set it to null -x = 3; // Set the def variable x to the literal 3 with an implicit - // cast from int to def -double a = x; // Declare double variable a and set it to def variable x, - // which contains a double -int b = x; // ERROR: Results in a run-time error because an explicit cast is - // required to cast from a double to an int -int c = (int)x; // Declare int variable c, explicitly cast def variable x to an - // int, and assign x to c +<1> char c = (char)"C" +<2> c = (char)'c' ---- - -[[character-string-casting]] -==== Character-String Casting -* Casting a <> value into a <> value. ++ +<1> a +<2> a ++ +* Casting a <> value into a <> + value. + [source,Painless] ---- -String s = "s"; -char c = (char)s; +<1> String s = "s"; +<2> char c = (char)s; ---- +<1> a +<2> a [[boxing-unboxing]] ==== Boxing and Unboxing diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index e408365f805c1..2588b964cbf32 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -118,17 +118,5 @@ STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) ==== Characters Character literals cannot be specified directly. Instead, use the -<> to convert <> -values into <> values. Use only <> -values one character in length for this conversion or an error will occur. - -*Examples* - -* <> string literals into -<> values. -+ -[source,Painless] ----- -(char)"C" -(char)'c' ----- +<> to convert +<> values into <> values. diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 46d0276021409..7aa8052482a0b 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -103,7 +103,7 @@ logical quantity with two possible values of `true` and `false` + <1> declare `int i`; assign value of `int 1` to `i` -<2> access `i` -> `int 1`; +<2> access value of `i` -> `int 1`; box value of `int 1` -> `Integer 1 reference`; call `toString` on `Integer 1 reference` -> `String '1'` @@ -208,11 +208,11 @@ relationships. implicit cast value of `ArrayList reference` to value of `List reference` -> `List reference`; assign value of `List reference` to `l` -<2> access `l` -> `List reference`; +<2> access value of `l` -> `List reference`; implicit cast value of `int 1` to value of `def` -> `def` call `add` on `List reference` with arguments (`def`) <3> declare `int i`; - access `l` -> `List reference`; + access value of `l` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def`; implicit cast value of `def` to value of `int 1` -> `int 1`; add value of `int 1` and value of `int 2` -> `int 3`; @@ -235,20 +235,20 @@ relationships. -> `List reference`; assign value of `List reference` to `l0` <2> declare `List l1`; - access `l0` -> `List reference`; + access value of `l0` -> `List reference`; assign value of `List reference` to `l1` (note `l0` and `l1` refer to the same instance known as a shallow-copy) -<3> access `l0` -> `List reference`; +<3> access value of `l0` -> `List reference`; implicit cast value of `int 1` to value of `def` -> `def` call `add` on `List reference` with arguments (`def`) -<4> access `l1` -> `List reference`; +<4> access value of `l1` -> `List reference`; implicit cast value of `int 2` to value of `def` -> `def` call `add` on `List reference` with arguments (`def`) <5> declare `int i`; - access `l0` -> `List reference`; + access value of `l0` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def @0`; implicit cast value of `def @0` to value of `int 1` -> `int 1`; - access `l1` -> `List reference`; + access value of `l1` -> `List reference`; call `get` on `List reference` with arguments (`int 1`) -> `def @1`; implicit cast value of `def @1` to value of `int 2` -> `int 2`; add value of `int 1` and value of `int 2` -> `int 3`; @@ -263,7 +263,7 @@ relationships. ---- + <1> declare `int i`; - access `MAX_VALUE` on `Integer` -> `int 2147483647`; + access value of `MAX_VALUE` on `Integer` -> `int 2147483647`; assign value of `int 2147483647` to `i` <2> declare `long l`; call `parseLong` on `Long` with arguments (`long 123`) -> `long 123`; @@ -311,9 +311,9 @@ reference types directly when performance is critical. allocate `ArrayList` instance -> `ArrayList reference`; implicit cast value of `ArrayList reference` to value of `def` -> `def`; assign value of `def` to `dr` -<3> access `dp` -> `def`; +<3> access value of `dp` -> `def`; assign value of `def` to `dr`; - (note the switch in type `dr` represents from `ArrayList` to `int`) + (note the switch in the type `dr` represents from `ArrayList` to `int`) + * A `def` type value representing the child-most descendant of a value. + @@ -330,10 +330,10 @@ reference types directly when performance is critical. -> `Object reference`; assign value of `Object reference` to `l` <2> declare `def d`; - access `l` -> `Object reference`; + access value of `l` -> `Object reference`; implicit cast value of `Object reference` to value of `def` -> `def`; assign value of `def` to `d`; -<3> access `d` -> `def`; +<3> access value of `d` -> `def`; implicit cast value of `def` to value of `ArrayList reference` -> `ArrayList reference`; call `ensureCapacity` on `ArrayList reference` with arguments (`int 10`); @@ -442,14 +442,14 @@ the array type `int[][]`. implicit cast value of `1-d float array reference` to value of `def` -> `def`; assign value of `def` to `z` -<4> access `y` -> `1-d float array reference`; +<4> access value of `y` -> `1-d float array reference`; assign value of `float 1.0` to `index [9]` of `1-d float array reference` -<5> access `y` -> `1-d float array reference @1`; - access `index [9]` of `1-d float array reference @1` -> `float 1.0`; - access `z` -> `def`; - implicit cast value of `def` to value of `1-d float array reference @2` - -> `1-d float array reference @2` - assign `float 1.0` to `index [0]` of `1-d float array reference @2` +<5> access value of `y` -> `1-d float array reference @0`; + access `index [9]` of `1-d float array reference @0` -> `float 1.0`; + access value of `z` -> `def`; + implicit cast value of `def` to value of `1-d float array reference @1` + -> `1-d float array reference @1`; + assign value of `float 1.0` to `index [0]` of `1-d float array reference @1` + * Use of a multi-dimensional array. + @@ -464,9 +464,9 @@ the array type `int[][]`. allocate `3-d int array` instance with length `[2, 3, 4]` -> `3-d int array reference`; assign value of `3-d int array reference` to `ia3` -<2> access `ia3` -> `3-d int array reference`; +<2> access value of `ia3` -> `3-d int array reference`; assign value of `int 99` to `index [1, 2, 3]` of `3-d int array reference` <3> declare `int i`; - access `ia3` -> `3-d int array reference`; - access `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; + access value of `ia3` -> `3-d int array reference`; + access value of `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; assign value of `int 99` to `i` \ No newline at end of file diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 09d8898739387..683acd2dcdf8d 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -155,12 +155,12 @@ assignment: ID '=' expression -> `List reference`; assign value of `List reference` to `l` <2> declare `List k`; - access `l` -> `List reference`; + access value of `l` -> `List reference`; assign value of `List reference` to `k`; (note `l` and `k` refer to the same instance known as a shallow-copy) <3> declare `List m`; assign default value of `null` to `m` -<4> access `k` -> `List reference`; +<4> access value of `k` -> `List reference`; assign value of `List reference` to `m`; (note `l`, `k`, and `m` refer to the same instance) + @@ -183,20 +183,20 @@ assignment: ID '=' expression <2> allocate `1-d int array` instance with `length [2]` -> `1-d int array reference`; assign value of `1-d int array reference` to `ia1` -<3> access `ia1` -> `1-d int array reference`; +<3> access value of `ia1` -> `1-d int array reference`; assign value of `int 1` to `index [0]` of `1-d int array reference` <4> declare `int[] ib1`; - access `ia1` -> `1-d int array reference`; + access value of `ia1` -> `1-d int array reference`; assign value of `1-d int array reference` to `ib1`; (note `ia1` and `ib1` refer to the same instance known as a shallow copy) <5> declare `int[][] ic2`; allocate `2-d int array` instance with `length [2, 5]` -> `2-d int array reference`; assign value of `2-d int array reference` to `ic2` -<6> access `ic2` -> `2-d int array reference`; +<6> access value of `ic2` -> `2-d int array reference`; assign value of `int 2` to `index [1, 3]` of `2-d int array reference` -<7> access `ia1` -> `1-d int array reference`; - access `ic2` -> `2-d int array reference`; +<7> access value of `ia1` -> `1-d int array reference`; + access value of `ic2` -> `2-d int array reference`; assign value of `1-d int array reference` to `index [0]` of `2-d int array reference`; (note `ia1`, `ib1`, and `index [0]` of `ia2` refer to the same instance) From a9c941e8aaeb42c0153791b4ece3f75e86750a3d Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 14 May 2018 23:41:37 -0700 Subject: [PATCH 21/55] Finished promotion and boxing/unboxing. --- docs/painless/painless-casting.asciidoc | 188 ++++++++++++++++-------- 1 file changed, 129 insertions(+), 59 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 6f6f5c26f9324..45f169ed90f41 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -31,7 +31,7 @@ cast: '(' TYPE ')' expression + <1> declare `int i`; explicit cast value of `long 5` to value of `int 5` -> `int 5`; - assign `int 5` to `i` + assign value of `int 5` to `i` <2> declare `Map m`; allocate `HashMap` instance -> `HashMap reference`; implicit cast value of `HashMap reference` to value of `Map reference` @@ -84,7 +84,7 @@ Each cast is read as a conversion of row to column. ---- + <1> declare `int a`; - assign `int 1` to `a` + assign value of `int 1` to `a` <2> declare `long b`; access value of `a` -> `int 1`; implicit cast value of `int 1` to value of `long 1` -> `long 1`; @@ -92,7 +92,7 @@ Each cast is read as a conversion of row to column. <3> declare `short c`; access value of `b` -> `long 1`; explicit cast value of `long 1` to value of `short 1` -> `short 1`; - assign `short 1` value to `c` + assign value of `short 1` value to `c` <4> declare `double e`; access value of `a` -> `int 1`; explicit cast value of `int 1` to `double 1.0`; @@ -112,7 +112,7 @@ Each cast is read as a conversion of row to column. *error* -> cannot implicit cast value of `double 1.0` to value of `int 1`; (note an explicit cast is valid) <2> declare `int b`; - assign `int 2` to `b` + assign value of `int 2` to `b` <3> declare byte `c`; access value of `b` -> `int 2`; *error* -> cannot implicit cast value of `int 2` to value of `byte 2`; @@ -151,16 +151,16 @@ being cast *to* is a descendant of the reference type being cast *from*. <3> access value of `y` -> `ArrayList reference`; implicit cast value of `ArrayList reference` to value of `List reference` -> `List reference`; - assign `List reference` to `x`; + assign value of `List reference` to `x`; (note `ArrayList` is a descendant of `List`) <4> access value of `x` -> `List reference`; explicit cast value of `List reference` to value of `ArrayList reference` -> `ArrayList reference`; - assign `ArrayList reference` to `y`; + assign value of `ArrayList reference` to `y`; <5> access value of `y` -> `ArrayList reference`; explicit cast value of `ArrayList reference` to value of `List reference` -> `List reference`; - assign `List reference` to `x`; + assign value of `List reference` to `x`; (note the explicit cast is extraneous, and an implicit cast is valid) + * Invalid <> casts resulting in errors. @@ -176,7 +176,7 @@ being cast *to* is a descendant of the reference type being cast *from*. allocate `ArrayList` instance -> `ArrayList reference`; implicit cast value of `ArrayList reference` to value of `List reference` -> `List reference`; - assign `List reference` to `x` + assign value of `List reference` to `x` <2> declare `ArrayList y`; access value of `x` -> `List reference`; *error* -> cannot implicit cast `List reference` to `ArrayList reference`; @@ -206,7 +206,7 @@ normally allowed based on the current type value the > value represents. *Examples* -+ + * Examples of casting <> to the <>. + @@ -220,7 +220,7 @@ normally allowed based on the current type value the ---- + <1> declare `def d0`; - implicit cast value of `int 3` to `def` + implicit cast value of `int 3` to `def`; assign value of `int 3` to `d0` <2> allocate `ArrayList` instance -> `ArrayList reference`; implicit cast value of `ArrayList reference` to value of `def` -> `def`; @@ -233,13 +233,13 @@ normally allowed based on the current type value the <4> declare `def d1`; access value of `o` -> `Object reference`; implicit cast value of `Object reference` to value of `def` -> `def`; - assign `def` to `d1` + assign value of `def` to `d1` <5> declare `int i`; access value of `d1` -> `def`; implicit cast value of `def` to value of `HashMap reference` -> HashMap reference`; call `size` on `HashMap reference` -> `int 0`; - assign `int 0` to `i`; + assign value of `int 0` to `i`; (note value of `def` was implicit cast to value of `HashMap reference` since `HashMap` is the child-most descendant type value that the `def` type value represents) @@ -285,7 +285,7 @@ normally allowed based on the current type value the -> `List reference`; assign value of `List reference` to `l` + -* Examples of errors casting with <>. +* Examples of errors when casting with the <>. + [source,Painless] ---- @@ -330,8 +330,11 @@ an error will occur. <2> c = (char)'c' ---- + -<1> a -<2> a +<1> declare `char c`; + explicit cast value of `String "C"` to value of `char C` -> `char C`; + assign value of `char C` to `c` +<2> explicit cast value of `String 'c'` to value of `char c` -> `char c`; + assign value of `char c` to `c` + * Casting a <> value into a <> value. @@ -341,62 +344,129 @@ an error will occur. <1> String s = "s"; <2> char c = (char)s; ---- -<1> a -<2> a +<1> declare `String s`; + assign value of `String "s"` to `s`; +<2> declare `char c` + access value of `s` -> `String "s"`; + explicit cast value of `String "s"` to value of `char s` -> `char s`; + assign value of `char s` to `c` [[boxing-unboxing]] ==== Boxing and Unboxing -Boxing is where a cast is used to convert a primitive type to its corresponding -reference type. Unboxing is the reverse, converting a reference type to the -corresponding primitive type. - -There are two places Painless performs implicit boxing and unboxing: +Boxing is a special type of cast used to convert a +<> to its corresponding +<>. Unboxing is the reverse used to convert a +<> to its corresponding +<>. + +Implicit boxing/unboxing occurs during the following +<>: + +* Conversions between the <> and + <> will be implicitly boxed/unboxed as + necessary, though this is referred to as an implicit cast throughout the + documentation. +* <>/function call arguments will be implicitly + boxed/unboxed as necessary. +* <> values will be implicitly boxed when a + <> <> is made on a + <> value. + +Explicit boxing/unboxing is not allowed and will result in an error. Use the +reference type API to explicitly convert primitive type values to their +respective reference type values and vice versa. -* When you call methods, Painless automatically boxes and unboxes arguments -so you can specify either primitive types or their corresponding reference -types. -* When you use the `def` type, Painless automatically boxes and unboxes as -needed when converting to and from `def`. - -The casting operator does not support any way to explicitly box a primitive -type or unbox a reference type. - -If a primitive type needs to be converted to a reference type, the Painless -reference type API supports methods that can do that. However, under normal -circumstances this should not be necessary. +*Examples* -*Examples:* -[source,Java] +* Uses of implicit boxing/unboxing. ++ +[source,Painless] +---- +<1> List l = new ArrayList(); +<2> l.add(1); +<3> Integer I = Integer.valueOf(0); +<4> int i = l.get(i); +---- ++ +<1> declare `List l`; + allocate `ArrayList` instance -> `ArrayList reference`; + assign value of `ArrayList reference` to `l`; +<2> access value of `l` -> `List reference`; + implicit cast value of `int 1` to value of `def` -> `def`; + call `add` on `List reference` with arguments (`def`); + (note internally `int 1` is boxed to `Integer 1` to store as a `def` type + value) +<3> declare `Integer I`; + call `valueOf` on `Integer` with arguments of (`int 0`) -> `Integer 0`; + assign value of `Integer 0` to `I`; +<4> declare `int i`; + access value of `I` -> `Integer 0`; + unbox `Integer 0` -> `int 0`; + access value of `l` -> `List reference`; + call `get` on `List reference` with arguments (`int 0`) -> `def`; + implicit cast value of `def` to value of `int 1` -> `int 1`; + assign value of `int 1` to `i`; + (note internally `int 1` is unboxed from `Integer 1` when read from a `def` + type value) ++ +* Uses of invalid boxing/unboxing resulting in errors. ++ +[source,Painless] ---- -Integer x = 1; // ERROR: not a legal implicit cast -Integer y = (Integer)1; // ERROR: not a legal explicit cast -int a = new Integer(1); // ERROR: not a legal implicit cast -int b = (int)new Integer(1); // ERROR: not a legal explicit cast +<1> Integer x = 1; // error +<2> Integer y = (Integer)1; // error +<3> int a = Integer.valueOf(1); // error +<4> int b = (int)Integer.valueOf(1); // error ---- ++ +<1> declare `Integer x`; + *error* -> cannot implicit box `int 1` to `Integer 1` during assignment +<2> declare `Integer y`; + *error* -> cannot explicit box `int 1` to `Integer 1` during assignment +<3> declare `int a`; + call `valueOf` on `Integer` with arguments of (`int 1`) -> `Integer 1`; + *error* -> cannot implicit unbox `Integer 1` to `int 1` during assignment +<4> declare `int a`; + call `valueOf` on `Integer` with arguments of (`int 1`) -> `Integer 1`; + *error* -> cannot explicit unbox `Integer 1` to `int 1` during assignment [[promotion]] ==== Promotion -Promotion is where certain operations require types to be either a minimum -numerical type or for two (or more) types to be equivalent. -The documentation for each operation that has these requirements -includes promotion tables that describe how this is handled. +Promotion is when a value is converted into either a certain type or when +multiple values are converted into equivalent types for use during an +<>. Each <> that +requires promotion will have a promotion table that shows all allowed +conversions. Values can be promoted to the `def` type at compile-time; however, +at run-time, the promoted type of value is derived from what the `def` type +value represents. -When an operation promotes a type or types, the resultant type -of the operation is the promoted type. Types can be promoted to def -at compile-time; however, at run-time, the resultant type will be the -promotion of the types the `def` is representing. +*Examples* -*Examples:* -[source,Java] +* Uses of promotion. ++ +[source,Painless] ---- -2 + 2.0 // Add the literal int 2 and the literal double 2.0. The literal - // 2 is promoted to a double and the resulting value is a double. - -def x = 1; // Declare def variable x and set it to the literal int 1 through - // an implicit cast -x + 2.0F // Add def variable x and the literal float 2.0. - // At compile-time the types are promoted to def. - // At run-time the types are promoted to float. ----- \ No newline at end of file +<1> double d = 2 + 2.0; +<2> def x = 1; +<3> float f = x + 2.0F; +---- +<1> declare `double d`; + promote value of `int 2` and value of `double 2.0 @0` -> `double 2.0 @0`; + implicit cast value of `int 2` to value of `double 2.0 @1` + -> `double 2.0 @1`; + add `double 2.0 @1` and `double 2.0 @0` -> `double 4.0`; + assign value of `double 4.0` to `d` +<2> declare `def x`; + implicit cast value of `int 1` to value of `def` -> `def`; + assign value of `def` to `x`; +<3> declare `float f`; + access value of `x` -> `def`; + implicit cast value of `def` to value of `int 1` -> `int 1`; + promote value of `int 1` and value of `float 2.0` -> `float 2.0`; + implicit cast value of `int 1` to value of `float 1.0` -> `float `1.0`; + add `float 1.0` and `float 2.0` -> `float 3.0`; + assign value of `float 3.0` to `f`; + (note this example illustrates promotion done at run-time as promotion + done at compile-time would have resolved to a `def` type value) \ No newline at end of file From 988fc235b1c5d7fb37ce96d847f2ed954b68e64a Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Fri, 18 May 2018 17:27:35 -0700 Subject: [PATCH 22/55] Cleaned up casting basic on PR comments. --- docs/painless/painless-casting.asciidoc | 360 ++++++++++++------------ 1 file changed, 174 insertions(+), 186 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 45f169ed90f41..d72d12b8f7ee7 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -1,16 +1,17 @@ [[painless-casting]] === Casting -A cast is the conversion of the value of one type to the equivalent value of an -inferred or specified type. Implicit casts are an inferred operation that -automatically convert values between types within a statement or -<> when necessary. Explicit casts are a -specified operation that forcefully convert values between types and are -required when an appropriate type for a statement or -<> cannot be inferred. If there exists no -equivalent value for the type converted to during a cast operation an error -will occur. If an implicit cast is given but an explicit cast is required an -error will occur. +A cast converts the value of an original <> to the +equivalent value of a target <>. An implicit cast infers +the target type and automatically occurs during certain +<>. An explicit cast specifies the target type +and forcefully occurs as its own operation. Use the *cast operator ()* to +specify an explicit cast. + +*Errors* + +* If during a cast there exists no equivalent value for the target type. +* If an implicit cast is given, but an explicit cast is required. *Grammar* [source,ANTLR4] @@ -20,7 +21,7 @@ cast: '(' TYPE ')' expression *Examples* -* Valid general casts. +* Valid casts. + [source,Painless] ---- @@ -30,35 +31,29 @@ cast: '(' TYPE ')' expression ---- + <1> declare `int i`; - explicit cast value of `long 5` to value of `int 5` -> `int 5`; - assign value of `int 5` to `i` + explicit cast `long 5` to `int 5` -> `int 5`; + assign `int 5` to `i` <2> declare `Map m`; allocate `HashMap` instance -> `HashMap reference`; - implicit cast value of `HashMap reference` to value of `Map reference` - -> `Map reference`; - assign value of `Map reference` to `m` + implicit cast `HashMap reference` to `Map reference` -> `Map reference`; + assign `Map reference` to `m` <3> declare `HashMap hm`; - access value of `m` -> `Map reference`; - explicit cast value of `Map reference` to value of `HashMap reference` - -> `HashMap reference`; - assign value of `HashMap reference` to `hm` + access `m` -> `Map reference`; + explicit cast `Map reference` to `HashMap reference` -> `HashMap reference`; + assign `HashMap reference` to `hm` [[numeric-type-casting]] ==== Numeric Type Casting -A <> cast is the conversion of the value of one -<> to the equivalent value of an inferred or -specified <>. Casts between values of -<> will result in data loss when the value of -the type converted from is larger than the equivalent value of the type -converted to can accommodate. Casts between values of integral types and values -of floating point types will result in precision loss when the value of the -integral type converted from is unable to accurately represent the equivalent -value of the floating point type converted to and vice versa. +A <> cast converts the value of an original +numeric type to the equivalent value of a target numeric type. A cast between +two numeric type values results in data loss when the value of the original +numeric type is larger than the target numeric type can accommodate. A cast +between an integer type value and a floating point type value can result in +precision loss. -The table below illustrates allowed casts between values of -<> and which specific casts must be explicit. -Each cast is read as a conversion of row to column. +The allowed casts for values of each numeric type is shown as a row in the table +below. |==== | | byte | short | char | int | long | float | double @@ -73,7 +68,7 @@ Each cast is read as a conversion of row to column. *Examples* -* Valid <> casts. +* Valid numeric type casts. + [source,Painless] ---- @@ -84,22 +79,22 @@ Each cast is read as a conversion of row to column. ---- + <1> declare `int a`; - assign value of `int 1` to `a` + assign `int 1` to `a` <2> declare `long b`; - access value of `a` -> `int 1`; - implicit cast value of `int 1` to value of `long 1` -> `long 1`; - assign value of `long 1` to `b` + access `a` -> `int 1`; + implicit cast `int 1` to `long 1` -> `long 1`; + assign `long 1` to `b` <3> declare `short c`; - access value of `b` -> `long 1`; - explicit cast value of `long 1` to value of `short 1` -> `short 1`; - assign value of `short 1` value to `c` + access `b` -> `long 1`; + explicit cast `long 1` to `short 1` -> `short 1`; + assign `short 1` value to `c` <4> declare `double e`; - access value of `a` -> `int 1`; - explicit cast value of `int 1` to `double 1.0`; - assign value of `double 1.0` to `e`; - (note the explicit cast is extraneous, and an implicit cast is valid) + access `a` -> `int 1`; + explicit cast `int 1` to `double 1.0`; + assign `double 1.0` to `e`; + (note the explicit cast is extraneous since an implicit cast is valid) + -* Invalid <> casts resulting in errors. +* Invalid numeric type casts resulting in errors. + [source,Painless] ---- @@ -109,30 +104,28 @@ Each cast is read as a conversion of row to column. ---- + <1> declare `int i`; - *error* -> cannot implicit cast value of `double 1.0` to value of `int 1`; + *error* -> cannot implicit cast `double 1.0` to `int 1`; (note an explicit cast is valid) <2> declare `int b`; - assign value of `int 2` to `b` + assign `int 2` to `b` <3> declare byte `c`; - access value of `b` -> `int 2`; - *error* -> cannot implicit cast value of `int 2` to value of `byte 2`; + access `b` -> `int 2`; + *error* -> cannot implicit cast `int 2` to `byte 2`; (note an explicit cast is valid) [[reference-type-casting]] ==== Reference Type Casting -A <> cast is the conversion of the value of -one <> to the equivalent value of an inferred -or specified <>. Implicit casts between -reference type values are allowed when the reference type being cast *from* -is a descendant of the reference type being cast *to*. Explicit casts between -reference type values are allowed when the reference type being cast *from* -is a descendant of the reference type being cast *to* or the reference type -being cast *to* is a descendant of the reference type being cast *from*. +A <> cast converts the value of an original +reference type to the equivalent value of a target reference type. An implicit +cast between two reference type values is allowed when the original reference +type is a descendant of the target type. An explicit cast between two reference +type values is allowed when the original type is a descendant of the target type +or the target type is a descendant of the original type. *Examples* -* Valid <> casts. +* Valid reference type casts. + [source,Painless] ---- @@ -147,23 +140,21 @@ being cast *to* is a descendant of the reference type being cast *from*. assign default value `null` to `x` <2> declare `ArrayList y`; allocate `ArrayList` instance -> `ArrayList reference`; - assign value of `ArrayList reference` to `y`; -<3> access value of `y` -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `List reference` - -> `List reference`; - assign value of `List reference` to `x`; + assign `ArrayList reference` to `y`; +<3> access `y` -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + assign `List reference` to `x`; (note `ArrayList` is a descendant of `List`) -<4> access value of `x` -> `List reference`; - explicit cast value of `List reference` to value of `ArrayList reference` +<4> access `x` -> `List reference`; + explicit cast `List reference` to `ArrayList reference` -> `ArrayList reference`; - assign value of `ArrayList reference` to `y`; -<5> access value of `y` -> `ArrayList reference`; - explicit cast value of `ArrayList reference` to value of `List reference` - -> `List reference`; - assign value of `List reference` to `x`; + assign `ArrayList reference` to `y`; +<5> access `y` -> `ArrayList reference`; + explicit cast `ArrayList reference` to `List reference` -> `List reference`; + assign `List reference` to `x`; (note the explicit cast is extraneous, and an implicit cast is valid) + -* Invalid <> casts resulting in errors. +* Invalid reference type casts resulting in errors. + [source,Painless] ---- @@ -174,16 +165,14 @@ being cast *to* is a descendant of the reference type being cast *from*. + <1> declare `List x`; allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `List reference` - -> `List reference`; - assign value of `List reference` to `x` + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + assign `List reference` to `x` <2> declare `ArrayList y`; - access value of `x` -> `List reference`; + access `x` -> `List reference`; *error* -> cannot implicit cast `List reference` to `ArrayList reference`; - (note an explicit cast is valid since `ArrayList` is a descendant of - `List`) + (note an explicit cast is valid since `ArrayList` is a descendant of `List`) <3> declare `ArrayList y`; - access value of `x` -> `List reference`; + access `x` -> `List reference`; *error* -> cannot explicit cast `List reference` to `Map reference`; (note no cast would be valid since neither `List` nor `Map` is a descendant of the other) @@ -191,24 +180,21 @@ being cast *to* is a descendant of the reference type being cast *from*. [[dynamic-type-casting]] ==== Dynamic Type Casting -A <> cast is the conversion of the value of one -<>, `def`, to the equivalent value of any inferred -or specified other <> or vice versa. +A <> cast converts the value of an original +`def` type to the equivalent value of any target type or converts the value of +any original type to the equivalent value of a target `def` type. -Implicit casts from <> value to a -<> value are always allowed. Explicit casts from -<> value to a <> value are -allowed but never necessary. +An implicit cast from any original type value to a `def` type value is always +allowed. An explicit cast from any original type value to a `def` type value is +always allowed but never necessary. -Implicit and explicit casts from a >, value to -<> value are allowed if and only if the cast is -normally allowed based on the current type value the -> value represents. +An implicit or explicit cast from an original `def` type value to +any target type value is allowed if and only if the cast is normally allowed +based on the current type value the `def` type value represents. *Examples* -* Examples of casting <> to the - <>. +* Valid dynamic type casts with any original type to a target `def` type. + [source,Painless] ---- @@ -220,32 +206,30 @@ normally allowed based on the current type value the ---- + <1> declare `def d0`; - implicit cast value of `int 3` to `def`; - assign value of `int 3` to `d0` + implicit cast `int 3` to `def`; + assign `int 3` to `d0` <2> allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `def` -> `def`; - assign value of `def` to `d0` + implicit cast `ArrayList reference` to `def` -> `def`; + assign `def` to `d0` <3> declare `Object o`; allocate `HashMap` instance -> `HashMap reference`; - implicit cast value of `HashMap reference` to value of `Object reference` + implicit cast `HashMap reference` to `Object reference` -> `Object reference`; - assign value of `Object reference` to `o` + assign `Object reference` to `o` <4> declare `def d1`; - access value of `o` -> `Object reference`; - implicit cast value of `Object reference` to value of `def` -> `def`; - assign value of `def` to `d1` + access `o` -> `Object reference`; + implicit cast `Object reference` to `def` -> `def`; + assign `def` to `d1` <5> declare `int i`; - access value of `d1` -> `def`; - implicit cast value of `def` to value of `HashMap reference` - -> HashMap reference`; + access `d1` -> `def`; + implicit cast `def` to `HashMap reference` -> HashMap reference`; call `size` on `HashMap reference` -> `int 0`; - assign value of `int 0` to `i`; - (note value of `def` was implicit cast to value of `HashMap reference` - since `HashMap` is the child-most descendant type value that the - `def` type value represents) + assign `int 0` to `i`; + (note `def` was implicit cast to `HashMap reference` since `HashMap` is the + child-most descendant type value that the `def` type value + represents) + -* Examples of casting from the <> to - <>. +* Valid dynamic type casts with an original `def` type to any target type. + [source,Painless] ---- @@ -258,34 +242,32 @@ normally allowed based on the current type value the ---- + <1> declare `def d`; - implicit cast value of `double 1.0` to value of `def` -> `def`; - assign value of `def` to `d` + implicit cast `double 1.0` to `def` -> `def`; + assign `def` to `d` <2> declare `int i`; - access value of `d` -> `def`; - implicit cast value of `def` to value of `double 1.0` -> `double 1.0`; - explicit cast value of `double 1.0` to value of `int 1` -> `int 1`; - assign value of `int 1` to `i`; + access `d` -> `def`; + implicit cast `def` to `double 1.0` -> `double 1.0`; + explicit cast `double 1.0` to `int 1` -> `int 1`; + assign `int 1` to `i`; (note the explicit cast is necessary since a `double` value cannot be converted to an `int` value implicitly) -<3> assign value of `int 1` to `d`; +<3> assign `int 1` to `d`; (note the switch in the type `d` represents from `double` to `int`) <4> declare `float i`; - access value of `d` -> `def`; - implicit cast value of `def` to value of `int 1` -> `int 1`; - implicit cast value of `int 1` to value of `float 1.0` -> `float 1.0`; - assign value of `float 1.0` to `f` + access `d` -> `def`; + implicit cast `def` to `int 1` -> `int 1`; + implicit cast `int 1` to `float 1.0` -> `float 1.0`; + assign `float 1.0` to `f` <5> allocate `ArrayList` instance -> `ArrayList reference`; - assign value of `ArrayList reference` to `d`; + assign `ArrayList reference` to `d`; (note the switch in the type `d` represents from `int` to `ArrayList`) <6> declare `List l`; - access value of `d` -> `def`; - implicit cast value of `def` to value of `ArrayList reference` - -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `List reference` - -> `List reference`; - assign value of `List reference` to `l` + access `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + assign `List reference` to `l` + -* Examples of errors when casting with the <>. +* Invalid dynamic type casts resulting in errors. + [source,Painless] ---- @@ -295,19 +277,19 @@ normally allowed based on the current type value the <4> List l = d; // error ---- <1> declare `def d`; - implicit cast value of `int 1` to value of `def` -> `def`; - assign value of `def` to `d` + implicit cast `int 1` to `def` -> `def`; + assign `def` to `d` <2> declare `short s`; - access value of `d` -> `def`; - implicit cast value of `def` to value of `int 1` -> `int 1`; - *error* -> cannot implicit cast value of `int 1` to value of `short 1`; + access `d` -> `def`; + implicit cast `def` to `int 1` -> `int 1`; + *error* -> cannot implicit cast `int 1` to `short 1`; (note an explicit cast is valid) <3> allocate `HashMap` instance -> `HashMap reference`; - implicit cast value of `HashMap reference` to value of `def` -> `def`; - assign value of `def` to `d` + implicit cast `HashMap reference` to `def` -> `def`; + assign `def` to `d` <4> declare `List l`; - access value of `d` -> `def`; - implicit cast value of `def` to value of `HashMap reference`; + access `d` -> `def`; + implicit cast `def` to `HashMap reference`; *error* -> cannot implicit cast `HashMap reference` to `List reference`; (note no cast would be valid since neither `HashMap` nor `List` is a descendant of the other) @@ -315,14 +297,16 @@ normally allowed based on the current type value the [[string-character-casting]] ==== String to Character Casting -Use the <> to convert -<> values into <> values. Use only -<> values one character in length for this conversion or -an error will occur. +Use the <> to convert a +<> value into a <> value. + +*Errors* + +* If the String type value isn't one character in length. *Examples* -* Casting <> into <> values. +* Casting <> into char type values. + [source,Painless] ---- @@ -331,13 +315,12 @@ an error will occur. ---- + <1> declare `char c`; - explicit cast value of `String "C"` to value of `char C` -> `char C`; - assign value of `char C` to `c` -<2> explicit cast value of `String 'c'` to value of `char c` -> `char c`; - assign value of `char c` to `c` + explicit cast `String "C"` to `char C` -> `char C`; + assign `char C` to `c` +<2> explicit cast `String 'c'` to `char c` -> `char c`; + assign `char c` to `c` + -* Casting a <> value into a <> - value. +* Casting a String type value into a char type value. + [source,Painless] ---- @@ -345,11 +328,11 @@ an error will occur. <2> char c = (char)s; ---- <1> declare `String s`; - assign value of `String "s"` to `s`; + assign `String "s"` to `s`; <2> declare `char c` - access value of `s` -> `String "s"`; - explicit cast value of `String "s"` to value of `char s` -> `char s`; - assign value of `char s` to `c` + access `s` -> `String "s"`; + explicit cast `String "s"` to `char s` -> `char s`; + assign `char s` to `c` [[boxing-unboxing]] ==== Boxing and Unboxing @@ -357,25 +340,27 @@ an error will occur. Boxing is a special type of cast used to convert a <> to its corresponding <>. Unboxing is the reverse used to convert a -<> to its corresponding -<>. +reference type to its corresponding primitive type. Implicit boxing/unboxing occurs during the following <>: * Conversions between the <> and - <> will be implicitly boxed/unboxed as + primitive types will be implicitly boxed/unboxed as necessary, though this is referred to as an implicit cast throughout the documentation. * <>/function call arguments will be implicitly boxed/unboxed as necessary. -* <> values will be implicitly boxed when a - <> <> is made on a - <> value. +* Primitive type values will be implicitly boxed when a reference type method + call is invoked on a primitive type value. + +Explicit boxing/unboxing is not allowed. Use the reference type API to +explicitly convert primitive type values to their respective reference type +values and vice versa. + +*Errors* -Explicit boxing/unboxing is not allowed and will result in an error. Use the -reference type API to explicitly convert primitive type values to their -respective reference type values and vice versa. +* If an explicit cast is made to box/unbox a primitive type. *Examples* @@ -391,22 +376,22 @@ respective reference type values and vice versa. + <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; - assign value of `ArrayList reference` to `l`; -<2> access value of `l` -> `List reference`; - implicit cast value of `int 1` to value of `def` -> `def`; + assign `ArrayList reference` to `l`; +<2> access `l` -> `List reference`; + implicit cast `int 1` to `def` -> `def`; call `add` on `List reference` with arguments (`def`); (note internally `int 1` is boxed to `Integer 1` to store as a `def` type value) <3> declare `Integer I`; call `valueOf` on `Integer` with arguments of (`int 0`) -> `Integer 0`; - assign value of `Integer 0` to `I`; + assign `Integer 0` to `I`; <4> declare `int i`; - access value of `I` -> `Integer 0`; + access `I` -> `Integer 0`; unbox `Integer 0` -> `int 0`; - access value of `l` -> `List reference`; + access `l` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def`; - implicit cast value of `def` to value of `int 1` -> `int 1`; - assign value of `int 1` to `i`; + implicit cast `def` to `int 1` -> `int 1`; + assign `int 1` to `i`; (note internally `int 1` is unboxed from `Integer 1` when read from a `def` type value) + @@ -436,11 +421,15 @@ respective reference type values and vice versa. Promotion is when a value is converted into either a certain type or when multiple values are converted into equivalent types for use during an -<>. Each <> that -requires promotion will have a promotion table that shows all allowed -conversions. Values can be promoted to the `def` type at compile-time; however, -at run-time, the promoted type of value is derived from what the `def` type -value represents. +<>. Each operation that requires promotion will +have a promotion table that shows all allowed conversions. Values can be +promoted to the `def` type at compile-time; however, at run-time, the promoted +type value is derived from what the `def` type value represents. + +*Errors* + +* If a specific operation cannot find an allowed promotion type for the type(s) + of value(s) given. *Examples* @@ -453,20 +442,19 @@ value represents. <3> float f = x + 2.0F; ---- <1> declare `double d`; - promote value of `int 2` and value of `double 2.0 @0` -> `double 2.0 @0`; - implicit cast value of `int 2` to value of `double 2.0 @1` - -> `double 2.0 @1`; + promote `int 2` and `double 2.0 @0` -> `double 2.0 @0`; + implicit cast `int 2` to `double 2.0 @1` -> `double 2.0 @1`; add `double 2.0 @1` and `double 2.0 @0` -> `double 4.0`; - assign value of `double 4.0` to `d` + assign `double 4.0` to `d` <2> declare `def x`; - implicit cast value of `int 1` to value of `def` -> `def`; - assign value of `def` to `x`; + implicit cast `int 1` to `def` -> `def`; + assign `def` to `x`; <3> declare `float f`; - access value of `x` -> `def`; - implicit cast value of `def` to value of `int 1` -> `int 1`; - promote value of `int 1` and value of `float 2.0` -> `float 2.0`; - implicit cast value of `int 1` to value of `float 1.0` -> `float `1.0`; + access `x` -> `def`; + implicit cast `def` to `int 1` -> `int 1`; + promote `int 1` and `float 2.0` -> `float 2.0`; + implicit cast `int 1` to `float 1.0` -> `float `1.0`; add `float 1.0` and `float 2.0` -> `float 3.0`; - assign value of `float 3.0` to `f`; + assign `float 3.0` to `f`; (note this example illustrates promotion done at run-time as promotion - done at compile-time would have resolved to a `def` type value) \ No newline at end of file + done at compile-time would have resolved to a `def` type value) \ No newline at end of file From b95ce254fc16272abc8114ddf13978b08f9bad27 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 21 May 2018 10:49:51 -0700 Subject: [PATCH 23/55] More changes. --- docs/painless/painless-casting.asciidoc | 12 ++++++------ docs/painless/painless-types.asciidoc | 15 +++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index d72d12b8f7ee7..92dab330899f3 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -419,12 +419,12 @@ values and vice versa. [[promotion]] ==== Promotion -Promotion is when a value is converted into either a certain type or when -multiple values are converted into equivalent types for use during an -<>. Each operation that requires promotion will -have a promotion table that shows all allowed conversions. Values can be -promoted to the `def` type at compile-time; however, at run-time, the promoted -type value is derived from what the `def` type value represents. +Promotion is when a single value is or multiple values are converted to a +certain type for use during an <>. Each operation +that requires promotion has a promotion table that shows all allowed +conversions. Values can be promoted to the `def` type at compile-time; however, +at run-time, the promoted type value is derived from what the `def` type value +represents. *Errors* diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 7aa8052482a0b..841125ff54178 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -11,19 +11,18 @@ categories: <>, [[primitive-types]] ==== Primitive Types -Primitive types are built straight into the JVM, directly contain their data, +Primitive types are built into the JVM natively, directly contain their data, and are allocated to non-heap memory. Primitive type values are copied when <> and when passed into a <> or function as arguments. Primitive types have corresponding <> (also known as <>). Any member of the corresponding -<> can be <> or -<> by executing the appropriate operation on the -primitive type value. Operations performed in this manner convert -(<>) the primitive type value to its corresponding -<> value at runtime and execute the specified -<> or <>. +reference type can be <> or <> by +executing the appropriate operation on the primitive type value. Operations +performed in this manner box the primitive type value to its corresponding +reference type value at runtime and execute the specified field access or +method call. The following primitive types are available: @@ -93,7 +92,7 @@ logical quantity with two possible values of `true` and `false` assign value of `boolean true` to `b` + * Method call on a primitive type from the corresponding -<>. +< Date: Mon, 21 May 2018 14:24:51 -0700 Subject: [PATCH 24/55] More fixes. --- docs/painless/painless-casting.asciidoc | 30 ++-- docs/painless/painless-types.asciidoc | 181 ++++++++++++------------ 2 files changed, 105 insertions(+), 106 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 92dab330899f3..c5f874611a32e 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -5,7 +5,7 @@ A cast converts the value of an original <> to the equivalent value of a target <>. An implicit cast infers the target type and automatically occurs during certain <>. An explicit cast specifies the target type -and forcefully occurs as its own operation. Use the *cast operator ()* to +and forcefully occurs as its own operation. Use the *cast operator* to specify an explicit cast. *Errors* @@ -297,7 +297,7 @@ based on the current type value the `def` type value represents. [[string-character-casting]] ==== String to Character Casting -Use the <> to convert a +Use the <> to convert a <> value into a <> value. *Errors* @@ -345,18 +345,18 @@ reference type to its corresponding primitive type. Implicit boxing/unboxing occurs during the following <>: -* Conversions between the <> and - primitive types will be implicitly boxed/unboxed as +* Conversions between a <> and + a primitive type will be implicitly boxed/unboxed as necessary, though this is referred to as an implicit cast throughout the documentation. * <>/function call arguments will be implicitly boxed/unboxed as necessary. -* Primitive type values will be implicitly boxed when a reference type method - call is invoked on a primitive type value. +* A primitive type value will be implicitly boxed when a reference type method + call is invoked on it. Explicit boxing/unboxing is not allowed. Use the reference type API to -explicitly convert primitive type values to their respective reference type -values and vice versa. +explicitly convert a primitive type value to its respective reference type +value and vice versa. *Errors* @@ -419,12 +419,14 @@ values and vice versa. [[promotion]] ==== Promotion -Promotion is when a single value is or multiple values are converted to a -certain type for use during an <>. Each operation -that requires promotion has a promotion table that shows all allowed -conversions. Values can be promoted to the `def` type at compile-time; however, -at run-time, the promoted type value is derived from what the `def` type value -represents. +Promotion is when a single value is implicitly <> to a +certain type or multiple values are implicitly <> to the +same type as required for evaluation by certain +<>. Each operation that requires promotion has a +promotion table that shows all required implicit casts based on the type(s) of +value(s). A value can be promoted to a `def` type at compile-time; however, the +promoted type value is derived from what the `def` type value represents at +run-time. *Errors* diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 841125ff54178..99862a71c01bb 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -1,27 +1,28 @@ [[painless-types]] === Types -Types are a classification of data used to describe the properties of values -operated on in expressions and statements. These properties describe what data -the value can represent such as a number, string, or something more complex and -the rules for when a value is operated on. Types are split into the following -categories: <>, -<>, and <>. +A type is a classification of data used to define the properties of a value. +These properties specify what data a value represents such as a number, string, +These properties specify what data a value represents such as a number, string, +or something more complex and the rules for when a value is evaluated during +an <>. Each type belongs to one of the following +categories: <>, <>, +or <>. [[primitive-types]] ==== Primitive Types -Primitive types are built into the JVM natively, directly contain their data, -and are allocated to non-heap memory. Primitive type values are copied when +A primitive type represents basic data build natively into the JVM and is +allocated to non-heap memory. A primitive type value is copied when <> and when passed into a <> or -function as arguments. +function as an argument. -Primitive types have corresponding <> (also -known as <>). Any member of the corresponding +A primitive type has a corresponding <> (also +known as a <>). Any member of the corresponding reference type can be <> or <> by -executing the appropriate operation on the primitive type value. Operations +evaluating the appropriate operation on a primitive type value. Operations performed in this manner box the primitive type value to its corresponding -reference type value at runtime and execute the specified field access or +reference type value at runtime and evaluate the specified field access or method call. The following primitive types are available: @@ -85,14 +86,13 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign value of `int 1` to `i` + assign `int 1` to `i` <2> declare `double d`; - assign default value of `double 0.0` to `d` + assign default `double 0.0` to `d` <3> declare `boolean b`; - assign value of `boolean true` to `b` + assign `boolean true` to `b` + -* Method call on a primitive type from the corresponding -< declare `int i`; - assign value of `int 1` to `i` -<2> access value of `i` -> `int 1`; - box value of `int 1` -> `Integer 1 reference`; + assign `int 1` to `i` +<2> access `i` -> `int 1`; + box `int 1` -> `Integer 1 reference`; call `toString` on `Integer 1 reference` -> `String '1'` [[reference-types]] ==== Reference Types -Reference types are named constructs (objects), potentially representing +A reference type is a named construct (object), potentially representing multiple pieces of data (member fields) and logic to manipulate that data (member methods), defined as part of the application programming interface -(API) for use in scripts. +(API). A reference type instance is a single set of data for one reference type object allocated to the heap. A reference type instance is allocated using the -<>. Use reference type instances to store -and manipulate complex data. +<>. Use a reference type instance to +store and manipulate complex data. -Reference type values refer to reference type instances, and multiple reference -type values may refer to a single reference type instance. A change to a -reference type instance will affect all reference type values referring to that -instance. Reference type values are shallow-copied when +A reference type value refers to a reference type instance, and multiple +reference type values may refer to a single reference type instance. A change to +a reference type instance will affect all reference type values referring to +that specific instance. A reference type value is shallow-copied when <> and when passed into a <> or -function as arguments. +function as an argument. The default value for a <> reference type <> is `null`. <> a <> reference type instance or an existing reference type value to a reference type <> for -<> within a script. <> `null` to a -reference type <> to indicate the reference type -value refers to no reference type instance. The JVM will garbage collect a -reference type instance when no reference type values refer to that reference -type instance. - -A reference type object specifies zero-to-many of each of the following: - -static member fields:: - -Static member fields are named and <> pieces of data -specific to a single reference type object. Each reference type *object* -contains one set of data representative of its static member fields. Use the -<> in correspondence with the reference type -object name to access static member fields for reading and writing to a -specific reference type *object*. No reference type instance allocation is -necessary to use static member fields. - -non-static member fields:: - -Non-static member fields are named and <> pieces of data -specified by a reference type object. Each reference type *instance* contains -one set of data representative of its reference type object's non-static member -fields. Use the <> for reading and writing to -non-static member fields of a specific reference type *instance*. An allocated -reference type instance is required to use non-static member fields. - -static member methods:: - -Static member methods are functions specific to a single reference type -*object*. Use the <> in -correspondence with the reference type object name to invoke static member -methods. No reference type instance allocation is necessary to use static -member methods. - -non-static member methods:: - -Non-static member methods are functions specified by a reference type object -and called on a specific reference type *instance*. Non-static member methods -called on a specific reference type instance may read from and write to -non-static member fields of that specific reference type instance. Use the -<> in correspondence with a -specific reference type instance to invoke non-static member methods. An -allocated reference type instance is required to use non-static member methods. - -constructors:: - -Constructors are a special type of function specific to a reference type -*object* used to allocate reference type instances of that reference type -object. Use the <> to -allocate a reference type instance. - -Reference type objects support a basic inheritance model. Consider types A and +evaluation during a later <>. +<> `null` to a reference type +<> to indicate the reference type value refers to +no reference type instance. The JVM will garbage collect a reference type +instance when it is no longer referred to by any reference types values. + +A reference type object defines zero-to-many of each of the following: + +static member field:: + +A static member field is a named and <> piece of data. +Each reference type *object* contains one set of data representative of its +static member fields. Use the <> in +correspondence with the reference type object name to access a static member +field for reading and writing to a specific reference type *object*. No +reference type instance allocation is necessary to use a static member field. + +non-static member field:: + +A non-static member field is a named and <> piece of +data. Each reference type *instance* contains one set of data representative of +its reference type object's non-static member fields. Use the +<> for reading and writing to a +non-static member field of a specific reference type *instance*. An allocated +reference type instance is required to use a non-static member field. + +static member method:: + +A static member method is a function called on a reference type *object*. Use +the <> in correspondence with the +reference type object name to call a static member method. No reference type +instance allocation is necessary to use a static member method. + +non-static member method:: + +A non-static member method is a function called on a reference type *instance*. +A non-static member method called on a reference type instance can read from and +write to non-static member fields of that specific reference type instance. Use +the <> in correspondence with a specific +reference type instance to call a non-static member method. An allocated +reference type instance is required to use a non-static member method. + +constructor:: + +A constructor is a special type of function used to allocate a reference type +*instance* defined by a specific reference type *object*. Use the +<> to allocate a reference type +instance. + +A reference type object follows a basic inheritance model. Consider types A and B. Type A is considered to be a parent of B, and B a child of A, if B inherits (is able to access as its own) all of A's non-static members. Type B is considered a descendant of A if there exists a recursive parent-child @@ -193,7 +190,7 @@ relationships. *Examples* -* Reference types used in several different <>. +* Reference types evaluated in several different operations. + [source,Painless] ---- @@ -204,18 +201,18 @@ relationships. + <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `List reference` + implicit cast `ArrayList reference` to `List reference` -> `List reference`; - assign value of `List reference` to `l` -<2> access value of `l` -> `List reference`; - implicit cast value of `int 1` to value of `def` -> `def` + assign `List reference` to `l` +<2> access `l` -> `List reference`; + implicit cast `int 1` to `def` -> `def` call `add` on `List reference` with arguments (`def`) <3> declare `int i`; - access value of `l` -> `List reference`; + access `l` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def`; - implicit cast value of `def` to value of `int 1` -> `int 1`; - add value of `int 1` and value of `int 2` -> `int 3`; - assign value of `int 3` to `i` + implicit cast `def` to `int 1` -> `int 1`; + add `int 1` and `int 2` -> `int 3`; + assign `int 3` to `i` + * Sharing a reference type instance. + From 8fc45660cc7c89088d91806db28b9cd5e3460fb7 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 21 May 2018 17:19:16 -0700 Subject: [PATCH 25/55] Fixed casting and types based on PR feedback. --- docs/painless/painless-casting.asciidoc | 48 ++-- docs/painless/painless-operators.asciidoc | 1 + docs/painless/painless-types.asciidoc | 320 +++++++++++----------- 3 files changed, 181 insertions(+), 188 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index c5f874611a32e..5817f9bcb9b57 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -1,12 +1,11 @@ [[painless-casting]] === Casting -A cast converts the value of an original <> to the -equivalent value of a target <>. An implicit cast infers -the target type and automatically occurs during certain -<>. An explicit cast specifies the target type -and forcefully occurs as its own operation. Use the *cast operator* to -specify an explicit cast. +A cast converts the value of an original type to the equivalent value of a +target type. An implicit cast infers the target type and automatically occurs +during certain <>. An explicit cast specifies +the target type and forcefully occurs as its own operation. Use the *cast +operator* to specify an explicit cast. *Errors* @@ -52,8 +51,8 @@ numeric type is larger than the target numeric type can accommodate. A cast between an integer type value and a floating point type value can result in precision loss. -The allowed casts for values of each numeric type is shown as a row in the table -below. +The allowed casts for values of each numeric type are shown as a row in the +following table: |==== | | byte | short | char | int | long | float | double @@ -297,8 +296,8 @@ based on the current type value the `def` type value represents. [[string-character-casting]] ==== String to Character Casting -Use the <> to convert a -<> value into a <> value. +Use the *cast operator* to convert a <> value into a +<> value. *Errors* @@ -306,7 +305,7 @@ Use the <> to convert a *Examples* -* Casting <> into char type values. +* Casting strings, string literals into char type values. + [source,Painless] ---- @@ -337,20 +336,17 @@ Use the <> to convert a [[boxing-unboxing]] ==== Boxing and Unboxing -Boxing is a special type of cast used to convert a -<> to its corresponding -<>. Unboxing is the reverse used to convert a +Boxing is a special type of cast used to convert a primitive type to its +corresponding reference type. Unboxing is the reverse used to convert a reference type to its corresponding primitive type. -Implicit boxing/unboxing occurs during the following -<>: +Implicit boxing/unboxing occurs during the following operations: -* Conversions between a <> and +* Conversions between a `def` type and a primitive type will be implicitly boxed/unboxed as necessary, though this is referred to as an implicit cast throughout the documentation. -* <>/function call arguments will be implicitly - boxed/unboxed as necessary. +* Method/function call arguments will be implicitly boxed/unboxed as necessary. * A primitive type value will be implicitly boxed when a reference type method call is invoked on it. @@ -419,14 +415,12 @@ value and vice versa. [[promotion]] ==== Promotion -Promotion is when a single value is implicitly <> to a -certain type or multiple values are implicitly <> to the -same type as required for evaluation by certain -<>. Each operation that requires promotion has a -promotion table that shows all required implicit casts based on the type(s) of -value(s). A value can be promoted to a `def` type at compile-time; however, the -promoted type value is derived from what the `def` type value represents at -run-time. +Promotion is when a single value is implicitly cast to a certain type or +multiple values are implicitly cast to the same type as required for evaluation +by certain operations. Each operation that requires promotion has a promotion +table that shows all required implicit casts based on the type(s) of value(s). A +value can be promoted to a `def` type at compile-time; however, the promoted +type value is derived from what the `def` type value represents at run-time. *Errors* diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index d80a6699680e0..8329686f663af 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -339,6 +339,7 @@ return d[z]; // Access the 1st element of array d using the 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. diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 99862a71c01bb..2ec87c8806414 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -2,28 +2,26 @@ === Types A type is a classification of data used to define the properties of a value. -These properties specify what data a value represents such as a number, string, -These properties specify what data a value represents such as a number, string, -or something more complex and the rules for when a value is evaluated during -an <>. Each type belongs to one of the following -categories: <>, <>, -or <>. +These properties specify what data a value represents and the rules for how a +value is evaluated during an <>. Each type +belongs to one of the following categories: <>, +<>, or <>. [[primitive-types]] ==== Primitive Types A primitive type represents basic data build natively into the JVM and is -allocated to non-heap memory. A primitive type value is copied when -<> and when passed into a <> or -function as an argument. - -A primitive type has a corresponding <> (also -known as a <>). Any member of the corresponding -reference type can be <> or <> by -evaluating the appropriate operation on a primitive type value. Operations -performed in this manner box the primitive type value to its corresponding -reference type value at runtime and evaluate the specified field access or -method call. +allocated to non-heap memory. Declare a primitive type +<>, and assign it a primitive type value for +evaluation during later operations. The default value for a newly-declared +primitive type variable is listed as part of the definitions below. A primitive +type value is copied during an assignment or as an argument for a +method/function call. + +A primitive type has a corresponding reference type (also known as a boxed +type). Use the <> or +<> on a primitive type value to force +evaluation as its corresponding reference type value. The following primitive types are available: @@ -75,8 +73,7 @@ logical quantity with two possible values of `true` and `false` *Examples* -* Primitive types used in <> and -<>. +* Primitive types used in declaration, declaration and assignment. + [source,Painless] ---- @@ -86,11 +83,11 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign `int 1` to `i` + assign `int 1` to `i` <2> declare `double d`; - assign default `double 0.0` to `d` + assign default `double 0.0` to `d` <3> declare `boolean b`; - assign `boolean true` to `b` + assign `boolean true` to `b` + * Method call on a primitive type using the corresponding reference type. + @@ -101,9 +98,9 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign `int 1` to `i` -<2> access `i` -> `int 1`; - box `int 1` -> `Integer 1 reference`; + assign `int 1` to `i` +<2> access `i` -> `int 1`; + box `int 1` -> `Integer 1 reference`; call `toString` on `Integer 1 reference` -> `String '1'` [[reference-types]] @@ -112,63 +109,62 @@ logical quantity with two possible values of `true` and `false` A reference type is a named construct (object), potentially representing multiple pieces of data (member fields) and logic to manipulate that data (member methods), defined as part of the application programming interface -(API). +(API) for scripts. A reference type instance is a single set of data for one reference type -object allocated to the heap. A reference type instance is allocated using the -<>. Use a reference type instance to -store and manipulate complex data. +object allocated to the heap. Use the +<> to allocate a reference type +instance. Use a reference type instance to read from, write to, and manipulate +complex data. A reference type value refers to a reference type instance, and multiple -reference type values may refer to a single reference type instance. A change to +reference type values may refer to the same reference type instance. A change to a reference type instance will affect all reference type values referring to -that specific instance. A reference type value is shallow-copied when -<> and when passed into a <> or -function as an argument. - -The default value for a <> reference type -<> is `null`. <> a -<> reference type instance or an existing -reference type value to a reference type <> for -evaluation during a later <>. -<> `null` to a reference type -<> to indicate the reference type value refers to -no reference type instance. The JVM will garbage collect a reference type -instance when it is no longer referred to by any reference types values. +that specific instance. + +Declare a reference type <>, and assign it a +reference type value for evaluation during later operations. The default value +for a newly-declared reference type variable is `null`. A reference type value +is shallow-copied during an assignment or as an argument for a method/function +call. Assign `null` to a reference type variable to indicate the reference type +value refers to no reference type instance. The JVM will garbage collect a +reference type instance when it is no longer referred to by any reference type +values. Pass `null` as an argument to a method/function call to indicate the +argument refers to no reference type instance. A reference type object defines zero-to-many of each of the following: static member field:: -A static member field is a named and <> piece of data. -Each reference type *object* contains one set of data representative of its -static member fields. Use the <> in -correspondence with the reference type object name to access a static member -field for reading and writing to a specific reference type *object*. No -reference type instance allocation is necessary to use a static member field. +A static member field is a named and typed piece of data. Each reference type +*object* contains one set of data representative of its static member fields. +Use the <> in correspondence with the +reference type object name to access a static member field for reading and +writing to a specific reference type *object*. No reference type instance +allocation is necessary to use a static member field. non-static member field:: -A non-static member field is a named and <> piece of -data. Each reference type *instance* contains one set of data representative of -its reference type object's non-static member fields. Use the -<> for reading and writing to a -non-static member field of a specific reference type *instance*. An allocated -reference type instance is required to use a non-static member field. +A non-static member field is a named and typed piece of data. Each reference +type *instance* contains one set of data representative of its reference type +object's non-static member fields. Use the +<> for reading and writing to a non-static +member field of a specific reference type *instance*. An allocated reference +type instance is required to use a non-static member field. static member method:: A static member method is a function called on a reference type *object*. Use -the <> in correspondence with the -reference type object name to call a static member method. No reference type -instance allocation is necessary to use a static member method. +the <> in correspondence with the reference +type object name to call a static member method. No reference type instance +allocation is necessary to use a static member method. non-static member method:: A non-static member method is a function called on a reference type *instance*. A non-static member method called on a reference type instance can read from and write to non-static member fields of that specific reference type instance. Use -the <> in correspondence with a specific +the <> in correspondence with a specific reference type instance to call a non-static member method. An allocated reference type instance is required to use a non-static member method. @@ -176,7 +172,7 @@ constructor:: A constructor is a special type of function used to allocate a reference type *instance* defined by a specific reference type *object*. Use the -<> to allocate a reference type +<> to allocate a reference type instance. A reference type object follows a basic inheritance model. Consider types A and @@ -201,18 +197,17 @@ relationships. + <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast `ArrayList reference` to `List reference` - -> `List reference`; - assign `List reference` to `l` -<2> access `l` -> `List reference`; - implicit cast `int 1` to `def` -> `def` + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + assign `List reference` to `l` +<2> access `l` -> `List reference`; + implicit cast `int 1` to `def` -> `def` call `add` on `List reference` with arguments (`def`) <3> declare `int i`; - access `l` -> `List reference`; + access `l` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def`; - implicit cast `def` to `int 1` -> `int 1`; - add `int 1` and `int 2` -> `int 3`; - assign `int 3` to `i` + implicit cast `def` to `int 1` -> `int 1`; + add `int 1` and `int 2` -> `int 3`; + assign `int 3` to `i` + * Sharing a reference type instance. + @@ -227,28 +222,27 @@ relationships. + <1> declare `List l0`; allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `List reference` - -> `List reference`; - assign value of `List reference` to `l0` + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + assign `List reference` to `l0` <2> declare `List l1`; - access value of `l0` -> `List reference`; - assign value of `List reference` to `l1` + access `l0` -> `List reference`; + assign `List reference` to `l1` (note `l0` and `l1` refer to the same instance known as a shallow-copy) -<3> access value of `l0` -> `List reference`; - implicit cast value of `int 1` to value of `def` -> `def` +<3> access `l0` -> `List reference`; + implicit cast `int 1` to `def` -> `def` call `add` on `List reference` with arguments (`def`) -<4> access value of `l1` -> `List reference`; - implicit cast value of `int 2` to value of `def` -> `def` +<4> access `l1` -> `List reference`; + implicit cast `int 2` to `def` -> `def` call `add` on `List reference` with arguments (`def`) <5> declare `int i`; - access value of `l0` -> `List reference`; + access `l0` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def @0`; - implicit cast value of `def @0` to value of `int 1` -> `int 1`; - access value of `l1` -> `List reference`; + implicit cast `def @0` to `int 1` -> `int 1`; + access `l1` -> `List reference`; call `get` on `List reference` with arguments (`int 1`) -> `def @1`; - implicit cast value of `def @1` to value of `int 2` -> `int 2`; - add value of `int 1` and value of `int 2` -> `int 3`; - assign value of `int 3` to `i`; + implicit cast `def @1` to `int 2` -> `int 2`; + add `int 1` and `int 2` -> `int 3`; + assign `int 3` to `i`; + * Using the static members of a reference type. + @@ -259,35 +253,34 @@ relationships. ---- + <1> declare `int i`; - access value of `MAX_VALUE` on `Integer` -> `int 2147483647`; - assign value of `int 2147483647` to `i` + access `MAX_VALUE` on `Integer` -> `int 2147483647`; + assign `int 2147483647` to `i` <2> declare `long l`; call `parseLong` on `Long` with arguments (`long 123`) -> `long 123`; - assign value of `long 123` to `l` + assign `long 123` to `l` [[dynamic-types]] ==== Dynamic Types -Use dynamic type values to represent the values of any primitive type or -reference type under a single type name `def`. A `def` type value mimics -the behavior of whatever value it currently represents and will always -represent the child-most descendant type value of any value when used in -<> and statements. +A dynamic type value can represent the value of any primitive type or +reference type using a single type name `def`. A `def` type value mimics +the behavior of whatever value it represents at run-time and will always +represent the child-most descendant type value of any type value when evaluated +during operations. -Internally, if a `def` type value is a primitive type value, the value is -converted (<>) to the corresponding reference type -instance. However, the `def` type still behaves like the primitive type -including within the <>. +Declare a `def` type <>, and assign it +any type of value for evaluation during later operations. The default value +for a newly-declared `def` type variable is `null`. A `def` type variable or +method/function parameter can change the type it represents during the +compilation and evaluation of a script. -The default value for a <> `def` type -<> is `null`. A `def` type -<> can have different types -<> throughout a script. +Using the `def` type can have a slight impact on performance. Use only primitive +types and reference types directly when performance is critical. -<> using the `def` type will generate -errors at runtime if an inappropriate type is represented. Using the `def` -type can have a slight impact on performance. Use only primitive types and -reference types directly when performance is critical. +*Errors* + +* If a `def` type value represents an inappropriate type for evaluation of an + operation at run-time. *Examples* @@ -301,14 +294,14 @@ reference types directly when performance is critical. ---- + <1> declare `def dp`; - implicit cast value of `int 1` to value of `def` -> `def`; - assign value of `def` to `dp` + implicit cast `int 1` to `def` -> `def`; + assign `def` to `dp` <2> declare `def dr`; allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `def` -> `def`; - assign value of `def` to `dr` -<3> access value of `dp` -> `def`; - assign value of `def` to `dr`; + implicit cast `ArrayList reference` to `def` -> `def`; + assign `def` to `dr` +<3> access `dp` -> `def`; + assign `def` to `dr`; (note the switch in the type `dr` represents from `ArrayList` to `int`) + * A `def` type value representing the child-most descendant of a value. @@ -322,18 +315,17 @@ reference types directly when performance is critical. + <1> declare `Object l`; allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `Object reference` + implicit cast `ArrayList reference` to `Object reference` -> `Object reference`; - assign value of `Object reference` to `l` + assign `Object reference` to `l` <2> declare `def d`; - access value of `l` -> `Object reference`; - implicit cast value of `Object reference` to value of `def` -> `def`; - assign value of `def` to `d`; -<3> access value of `d` -> `def`; - implicit cast value of `def` to value of `ArrayList reference` - -> `ArrayList reference`; + access `l` -> `Object reference`; + implicit cast `Object reference` to `def` -> `def`; + assign `def` to `d`; +<3> access `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; call `ensureCapacity` on `ArrayList reference` with arguments (`int 10`); - (note value of `def` was implicit cast to value of `ArrayList reference` + (note `def` was implicit cast to `ArrayList reference` since ArrayList` is the child-most descendant type value that the `def` type value represents) @@ -341,10 +333,10 @@ reference types directly when performance is critical. ==== String Type The `String` type is a specialized reference type that does not require -explicit allocation. Use <> to directly -<> or <> on `String` values. -While not required, the <> can allocate -`String` values. +explicit allocation. Use a <> to directly evaluate a +`String` type value. While not required, +the <> can allocate `String` type +instances. *Examples* @@ -359,21 +351,21 @@ While not required, the <> can allocate ---- + <1> declare `String r`; - assign value of `String "some text"` to `r` + assign `String "some text"` to `r` <2> declare `String s`; - assign value of `String 'some text'` to `s` + assign `String 'some text'` to `s` <3> declare `String t`; allocate `String` instance with arguments (`String "some text"`) -> `String "some text"`; - assign value of `String "some text"` to `t` + assign `String "some text"` to `t` <4> declare `String u`; - assign default value of `null` to `u` + assign default `null` to `u` [[void-type]] ==== void Type -The `void` type represents the concept of a lack of type. The `void` type is -primarily used to indicate a function will return no value. +The `void` type represents the concept of a lack of type. Use the `void` type to +indicate a function returns no value. *Examples* @@ -389,21 +381,28 @@ void addToList(List l, def d) { [[array-type]] ==== Array Type -The array type is a specialized reference type where an array type instance -represents a series of values. All values in an array type instance are of -the same type. Each value is assigned an index from within the range -`[0, length)` where length is the total number of values allocated for the -array type instance. Specify the type of values and the length during an -array allocation. - -Allocate an array type instance using the <> or the -<>. Array type instances are -allocated to the heap. <> and <> -array type variables for <> within scripts. The -default value for newly-declared array instance types is `null`. Array type -values are shallow-copied when <> and when passed into a -<> or function as arguments. Read and write to individual -values within the array type instance using the <>. +An array type is a specialized reference type where an array type instance +represents a series of values allocated to the heap. All values in an array +type instance are of the same type. Each value is assigned an index from within +the range `[0, length)` where length is the total number of values allocated for +the array type instance. + +Use the <> or the +<> to allocate an array +type instance. Declare an array type <>, and +assign it an array type value for evaluation during later operations. The +default value for a newly-declared array type variable is `null`. An array type +value is shallow-copied during an assignment or as an argument for a +method/function call. Assign `null` to an array type variable to indicate the +array type value refers to no array type instance. The JVM will garbage collect +an array type instance when it is no longer referred to by any array type +values. Pass `null` as an argument to a method/function call to indicate the +argument refers to no array type instance. + +Use the <> to retrieve the length of an +array type value as an int type value. Use the +<> to read and write to individual values +within an array type value. When an array type instance is allocated with multiple dimensions using the range `[2, d]` where `d >= 2`, each dimension in the range `[1, d-1]` is also @@ -427,25 +426,24 @@ the array type `int[][]`. ---- + <1> declare `int[] x`; - assign default value of `null` to `x` + assign default `null` to `x` <2> declare `float[] y`; allocate `1-d float array` instance with `length [10]` -> `1-d float array reference`; - assign value of `1-d float array reference` to `y` + assign `1-d float array reference` to `y` <3> declare `def z`; allocate `1-d float array` instance with `length [5]` -> `1-d float array reference`; - implicit cast value of `1-d float array reference` to value of `def` - -> `def`; - assign value of `def` to `z` -<4> access value of `y` -> `1-d float array reference`; - assign value of `float 1.0` to `index [9]` of `1-d float array reference` -<5> access value of `y` -> `1-d float array reference @0`; + implicit cast `1-d float array reference` to `def` -> `def`; + assign `def` to `z` +<4> access `y` -> `1-d float array reference`; + assign `float 1.0` to `index [9]` of `1-d float array reference` +<5> access `y` -> `1-d float array reference @0`; access `index [9]` of `1-d float array reference @0` -> `float 1.0`; - access value of `z` -> `def`; - implicit cast value of `def` to value of `1-d float array reference @1` + access `z` -> `def`; + implicit cast `def` to `1-d float array reference @1` -> `1-d float array reference @1`; - assign value of `float 1.0` to `index [0]` of `1-d float array reference @1` + assign `float 1.0` to `index [0]` of `1-d float array reference @1` + * Use of a multi-dimensional array. + @@ -459,10 +457,10 @@ the array type `int[][]`. <1> declare `int[][][] ia`; allocate `3-d int array` instance with length `[2, 3, 4]` -> `3-d int array reference`; - assign value of `3-d int array reference` to `ia3` -<2> access value of `ia3` -> `3-d int array reference`; - assign value of `int 99` to `index [1, 2, 3]` of `3-d int array reference` + assign `3-d int array reference` to `ia3` +<2> access `ia3` -> `3-d int array reference`; + assign `int 99` to `index [1, 2, 3]` of `3-d int array reference` <3> declare `int i`; - access value of `ia3` -> `3-d int array reference`; - access value of `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; - assign value of `int 99` to `i` \ No newline at end of file + access `ia3` -> `3-d int array reference`; + access `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; + assign `int 99` to `i` \ No newline at end of file From ca2bb83c767bb056a314086796f3bbc0f47dd66b Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 21 May 2018 18:41:31 -0700 Subject: [PATCH 26/55] Cleaned up more. --- docs/painless/painless-casting.asciidoc | 22 ++-- docs/painless/painless-comments.asciidoc | 12 +- docs/painless/painless-identifiers.asciidoc | 8 +- docs/painless/painless-keywords.asciidoc | 6 +- docs/painless/painless-lang-spec.asciidoc | 2 +- docs/painless/painless-literals.asciidoc | 32 ++--- docs/painless/painless-types.asciidoc | 22 ++-- docs/painless/painless-variables.asciidoc | 135 ++++++++++---------- 8 files changed, 118 insertions(+), 121 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 5817f9bcb9b57..430b45eb0dd55 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -296,16 +296,17 @@ based on the current type value the `def` type value represents. [[string-character-casting]] ==== String to Character Casting -Use the *cast operator* to convert a <> value into a -<> value. +Use the *cast operator* to convert a <> value into a +<> value. *Errors* -* If the String type value isn't one character in length. +* If the `String` type value isn't one character in length. +* If the `String` type value is `null`. *Examples* -* Casting strings, string literals into char type values. +* Casting string literals into `char` type values. + [source,Painless] ---- @@ -319,7 +320,7 @@ Use the *cast operator* to convert a <> value into a <2> explicit cast `String 'c'` to `char c` -> `char c`; assign `char c` to `c` + -* Casting a String type value into a char type value. +* Casting a `String` reference into a `char` value. + [source,Painless] ---- @@ -342,10 +343,9 @@ reference type to its corresponding primitive type. Implicit boxing/unboxing occurs during the following operations: -* Conversions between a `def` type and - a primitive type will be implicitly boxed/unboxed as - necessary, though this is referred to as an implicit cast throughout the - documentation. +* Conversions between a `def` type and a primitive type will be implicitly + boxed/unboxed as necessary, though this is referred to as an implicit cast + throughout the documentation. * Method/function call arguments will be implicitly boxed/unboxed as necessary. * A primitive type value will be implicitly boxed when a reference type method call is invoked on it. @@ -388,8 +388,8 @@ value and vice versa. call `get` on `List reference` with arguments (`int 0`) -> `def`; implicit cast `def` to `int 1` -> `int 1`; assign `int 1` to `i`; - (note internally `int 1` is unboxed from `Integer 1` when read from a `def` - type value) + (note internally `int 1` is unboxed from `Integer 1` when loaded from a + `def` type value) + * Uses of invalid boxing/unboxing resulting in errors. + diff --git a/docs/painless/painless-comments.asciidoc b/docs/painless/painless-comments.asciidoc index 588e464d97f78..bde30e37e04e1 100644 --- a/docs/painless/painless-comments.asciidoc +++ b/docs/painless/painless-comments.asciidoc @@ -1,12 +1,12 @@ [[painless-comments]] === Comments -Use the `//` token anywhere on a line to specify a single-line comment. All -characters from the `//` token to the end of the line are ignored. Use an -opening `/*` token and a closing `*/` token to specify a multi-line comment. -Multi-line comments can start anywhere on a line, and all characters in between -the `/*` token and `*/` token are ignored. Comments can be included anywhere -within a script. +Use a comment to annotate or explain code within a script. Use the `//` token +anywhere on a line to specify a single-line comment. All characters from the +`//` token to the end of the line are ignored. Use an opening `/*` token and a +closing `*/` token to specify a multi-line comment. Multi-line comments can +start anywhere on a line, and all characters in between the `/*` token and `*/` +token are ignored. Comments can be included anywhere within a script. *Grammar* [source,ANTLR4] diff --git a/docs/painless/painless-identifiers.asciidoc b/docs/painless/painless-identifiers.asciidoc index 17073e3d4c415..7762f56cb7b23 100644 --- a/docs/painless/painless-identifiers.asciidoc +++ b/docs/painless/painless-identifiers.asciidoc @@ -1,10 +1,10 @@ [[painless-identifiers]] === Identifiers -Specify identifiers to <>, <>, and -<> variables, <>, and -<>. <> and -<> cannot be used as identifiers. +Use an identifier as a named token to specify a +<>, <>, +<>, <>, or function. +<> cannot be used as identifiers. *Grammar* [source,ANTLR4] diff --git a/docs/painless/painless-keywords.asciidoc b/docs/painless/painless-keywords.asciidoc index cb3bafbd20f13..39a2201fd2b4b 100644 --- a/docs/painless/painless-keywords.asciidoc +++ b/docs/painless/painless-keywords.asciidoc @@ -1,9 +1,9 @@ [[painless-keywords]] === Keywords -The keywords in the table below are reserved for built-in language -features. These keywords cannot be used as -<> or <>. +Keywords are reserved tokens for built-in language features and cannot be used +as <> within a script. The following are +keywords: [cols="^1,^1,^1,^1,^1"] |==== diff --git a/docs/painless/painless-lang-spec.asciidoc b/docs/painless/painless-lang-spec.asciidoc index ba6595000ae2f..5e6b84d8c57d1 100644 --- a/docs/painless/painless-lang-spec.asciidoc +++ b/docs/painless/painless-lang-spec.asciidoc @@ -6,7 +6,7 @@ Painless syntax is similar to Java syntax along with some additional features such as dynamic typing, Map and List accessor shortcuts, and array initializers. As a direct comparison to Java, there are some important differences, especially related to the casting model. For more detailed -conceptual information about the basic constructs that Java and Painless share, +conceptual information about the basic constructs that Painless and Java share, refer to the corresponding topics in the https://docs.oracle.com/javase/specs/jls/se8/html/index.html[Java Language Specification]. diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index 2588b964cbf32..ebf7eaa07b657 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -1,18 +1,19 @@ [[painless-literals]] === Literals -Use literals to specify different types of values directly in a script. +Use a literal to specify a value directly in an +<>. [[integers]] ==== Integers -Use integer literals to specify an integer value in decimal, octal, or hex -notation of the <> `int`, `long`, `float`, +Use an integer literal to specify an integer type value in decimal, octal, or +hex notation of a <> `int`, `long`, `float`, or `double`. Use the following single letter designations to specify the -<>: `l` or `L` for `long`, `f` or `F` for -`float`, and `d` or `D` for `double`. If not specified, the type defaults to -`int`. Use `0` as a prefix to specify an integer literal as octal, and use -`0x` or `0X` as a prefix to specify an integer literal as hex. +primitive type: `l` or `L` for `long`, `f` or `F` for `float`, and `d` or `D` +for `double`. If not specified, the type defaults to `int`. Use `0` as a prefix +to specify an integer literal as octal, and use `0x` or `0X` as a prefix to +specify an integer literal as hex. *Grammar* [source,ANTLR4] @@ -46,11 +47,10 @@ HEX: '-'? '0' [xX] [0-9a-fA-F]+ [lL]?; [[floats]] ==== Floats -Use floating point literals to specify a floating point value of the -<> `float` or `double`. Use the following -single letter designations to specify the <>: -`f` or `F` for `float` and `d` or `D` for `double`. If not specified, the type -defaults to `double`. +Use a floating point literal to specify a floating point type value of a +<> `float` or `double`. Use the following +single letter designations to specify the primitive type: `f` or `F` for `float` +and `d` or `D` for `double`. If not specified, the type defaults to `double`. *Grammar* [source,ANTLR4] @@ -81,7 +81,7 @@ EXPONENT: ( [eE] [+\-]? [0-9]+ ); [[strings]] ==== Strings -Use string literals to specify <> values with +Use a string literal to specify a <> value with either single-quotes or double-quotes. Use a `\"` token to include a double-quote as part of a double-quoted string literal. Use a `\'` token to include a single-quote as part of a single-quoted string literal. Use a `\\` @@ -117,6 +117,6 @@ STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) [[characters]] ==== Characters -Character literals cannot be specified directly. Instead, use the -<> to convert -<> values into <> values. +A character literal cannot be specified directly. Instead, use the +<> to convert a `String` type value +into a `char` type value. diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 2ec87c8806414..d9aea01c21a79 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -10,7 +10,7 @@ belongs to one of the following categories: <>, [[primitive-types]] ==== Primitive Types -A primitive type represents basic data build natively into the JVM and is +A primitive type represents basic data built natively into the JVM and is allocated to non-heap memory. Declare a primitive type <>, and assign it a primitive type value for evaluation during later operations. The default value for a newly-declared @@ -114,7 +114,7 @@ multiple pieces of data (member fields) and logic to manipulate that data A reference type instance is a single set of data for one reference type object allocated to the heap. Use the <> to allocate a reference type -instance. Use a reference type instance to read from, write to, and manipulate +instance. Use a reference type instance to load from, store to, and manipulate complex data. A reference type value refers to a reference type instance, and multiple @@ -139,8 +139,8 @@ static member field:: A static member field is a named and typed piece of data. Each reference type *object* contains one set of data representative of its static member fields. Use the <> in correspondence with the -reference type object name to access a static member field for reading and -writing to a specific reference type *object*. No reference type instance +reference type object name to access a static member field for loading and +storing to a specific reference type *object*. No reference type instance allocation is necessary to use a static member field. non-static member field:: @@ -148,7 +148,7 @@ non-static member field:: A non-static member field is a named and typed piece of data. Each reference type *instance* contains one set of data representative of its reference type object's non-static member fields. Use the -<> for reading and writing to a non-static +<> for loading and storing to a non-static member field of a specific reference type *instance*. An allocated reference type instance is required to use a non-static member field. @@ -162,8 +162,8 @@ allocation is necessary to use a static member method. non-static member method:: A non-static member method is a function called on a reference type *instance*. -A non-static member method called on a reference type instance can read from and -write to non-static member fields of that specific reference type instance. Use +A non-static member method called on a reference type instance can load from and +store to non-static member fields of that specific reference type instance. Use the <> in correspondence with a specific reference type instance to call a non-static member method. An allocated reference type instance is required to use a non-static member method. @@ -334,8 +334,8 @@ types and reference types directly when performance is critical. The `String` type is a specialized reference type that does not require explicit allocation. Use a <> to directly evaluate a -`String` type value. While not required, -the <> can allocate `String` type +`String` type value. While not required, the +<> can allocate `String` type instances. *Examples* @@ -401,8 +401,8 @@ argument refers to no array type instance. Use the <> to retrieve the length of an array type value as an int type value. Use the -<> to read and write to individual values -within an array type value. +<> to load from and store to individual +values within an array type value. When an array type instance is allocated with multiple dimensions using the range `[2, d]` where `d >= 2`, each dimension in the range `[1, d-1]` is also diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 683acd2dcdf8d..8b8782b151132 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -1,31 +1,31 @@ [[painless-variables]] === Variables -<> variables to <> values for -<> in expressions. Specify variables as a -<>, <>, or -<>. Variable operations follow the structure of a -standard JVM in relation to instruction execution and memory usage. +A variable loads and stores a value for evaluation during +<>. [[declaration]] ==== Declaration -Declare variables before use with the format of <> -<>. Declare <> -variables using an opening `[` token and a closing `]` token for each -dimension directly after the <>. Specify a -comma-separated list of <> following the -<> to declare multiple variables in a single statement. -Use an <> statement combined with a declaration -statement to immediately assign a value to a variable. Variables not -immediately assigned a value will have a default value assigned implicitly -based on the <>. +Declare a variable before use with the format of <> +followed by <>. Declare an +<> variable using an opening `[` token and a closing `]` +token for each dimension directly after the identifier. Specify a +comma-separated list of identifiers following the type to declare multiple +variables in a single statement. Use an <> +combined with a declaration to immediately assign a value to a variable. +A variable not immediately assigned a value will have a default value assigned +implicitly based on the type. + +*Errors* + +* If a variable is used prior to or without declaration. *Grammar* [source,ANTLR4] ---- declaration : type ID assignment? (',' ID assignment?)*; -type: ID ('[' ']')*; +type: ID ('.' ID)* ('[' ']')*; assignment: '=' expression; ---- @@ -45,32 +45,35 @@ assignment: '=' expression; ---- + <1> declare `int x`; - assign default value of `null` to `x` + assign default `null` to `x` <2> declare `List y`; - assign default value of `null` to `y` + assign default `null` to `y` <3> declare `int x`; - assign default value of `int 0` to `x`; + assign default `int 0` to `x`; declare `int y`; - assign value of `int 5` to `y`; + assign `int 5` to `y`; declare `int z`; - assign default value of `int 0` to `z`; + assign default `int 0` to `z`; <4> declare `def d`; - assign default value of `null` to `d` + assign default `null` to `d` <5> declare `int i`; - assign value of `int 10` to `i` + assign `int 10` to `i` <6> declare `float[] f`; - assign default value of `null` to `f` + assign default `null` to `f` <7> declare `Map[][] m`; - assign default value of `null` to `m` + assign default `null` to `m` [[assignment]] ==== Assignment -Use the `equals operator '='` to assign a value to a variable. Any expression +Use the *assignment operator* to store a value in a variable. Any operation that produces a value can be assigned to any variable as long as the -<> are the same or the resultant -<> can be implicitly <> to -the variable <>. +<> are the same or the resultant type can be +<> to the variable type. + +*Errors* + +* If the type of value is unable to match the type of variable. *Grammar* [source,ANTLR4] @@ -80,7 +83,7 @@ assignment: ID '=' expression *Examples* -* Variable assignment with an <>. +* Variable assignment with an integer literal. + [source,Painless] ---- @@ -89,10 +92,10 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign default value of `int 0` to `i` -<2> assign value of `int 10` to `i` + assign default `int 0` to `i` +<2> assign `int 10` to `i` + -* <> combined with immediate variable assignment. +* Declaration combined with immediate assignment. + [source,Painless] ---- @@ -101,12 +104,11 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign value of `int 10` to `i` + assign `int 10` to `i` <2> declare `double j`; - assign value of `double 2.0` to `j` + assign `double 2.0` to `j` + -* Assignment of one variable to another using - <>. +* Assignment of one variable to another using primitive types. + [source,Painless] ---- @@ -115,13 +117,12 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign value of `int 10` to `i` + assign `int 10` to `i` <2> declare `int j`; access `i` -> `int 10`; - assign value of `int 10` to `j` + assign `int 10` to `j` + -* Assignment with <> using the - <>. +* Assignment with reference types using the *new instance operator*. + [source,Painless] ---- @@ -131,15 +132,13 @@ assignment: ID '=' expression + <1> declare `ArrayList l`; allocate `ArrayList` instance -> `ArrayList reference`; - assign value of `ArrayList reference` to `l` + assign `ArrayList reference` to `l` <2> declare `Map m`; allocate `HashMap` instance -> `HashMap reference`; - implicit cast value of `HashMap reference` to value of `Map reference` - -> `Map reference`; - assign value of `Map reference` to `m` + implicit cast `HashMap reference` to `Map reference` -> `Map reference`; + assign `Map reference` to `m` + -* Assignment of one variable to another using - <>. +* Assignment of one variable to another using reference types. + [source,Painless] ---- @@ -151,21 +150,19 @@ assignment: ID '=' expression + <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; - implicit cast value of `ArrayList reference` to value of `List reference` - -> `List reference`; - assign value of `List reference` to `l` + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + assign `List reference` to `l` <2> declare `List k`; - access value of `l` -> `List reference`; - assign value of `List reference` to `k`; + access `l` -> `List reference`; + assign `List reference` to `k`; (note `l` and `k` refer to the same instance known as a shallow-copy) <3> declare `List m`; - assign default value of `null` to `m` -<4> access value of `k` -> `List reference`; - assign value of `List reference` to `m`; + assign default `null` to `m` +<4> access `k` -> `List reference`; + assign `List reference` to `m`; (note `l`, `k`, and `m` refer to the same instance) + -* Assignment with the <> using the - <>. +* Assignment with an array type variable using the *new array operator*. + [source,Painless] ---- @@ -179,24 +176,24 @@ assignment: ID '=' expression ---- + <1> declare `int[] ia1`; - assign default value of `null` to `ia1` + assign default `null` to `ia1` <2> allocate `1-d int array` instance with `length [2]` -> `1-d int array reference`; - assign value of `1-d int array reference` to `ia1` -<3> access value of `ia1` -> `1-d int array reference`; - assign value of `int 1` to `index [0]` of `1-d int array reference` + assign `1-d int array reference` to `ia1` +<3> access `ia1` -> `1-d int array reference`; + assign `int 1` to `index [0]` of `1-d int array reference` <4> declare `int[] ib1`; - access value of `ia1` -> `1-d int array reference`; - assign value of `1-d int array reference` to `ib1`; + access `ia1` -> `1-d int array reference`; + assign `1-d int array reference` to `ib1`; (note `ia1` and `ib1` refer to the same instance known as a shallow copy) <5> declare `int[][] ic2`; allocate `2-d int array` instance with `length [2, 5]` -> `2-d int array reference`; - assign value of `2-d int array reference` to `ic2` -<6> access value of `ic2` -> `2-d int array reference`; - assign value of `int 2` to `index [1, 3]` of `2-d int array reference` -<7> access value of `ia1` -> `1-d int array reference`; - access value of `ic2` -> `2-d int array reference`; - assign value of `1-d int array reference` to + assign `2-d int array reference` to `ic2` +<6> access `ic2` -> `2-d int array reference`; + assign `int 2` to `index [1, 3]` of `2-d int array reference` +<7> access `ia1` -> `1-d int array reference`; + access `ic2` -> `2-d int array reference`; + assign `1-d int array reference` to `index [0]` of `2-d int array reference`; (note `ia1`, `ib1`, and `index [0]` of `ia2` refer to the same instance) From ae1ae75cd69d16912ae54c4d96facb5458d30b51 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 22 May 2018 11:03:58 -0700 Subject: [PATCH 27/55] Extra blank lines at end of docs. --- docs/painless/painless-casting.asciidoc | 2 +- docs/painless/painless-types.asciidoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 430b45eb0dd55..a3624f9083145 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -453,4 +453,4 @@ type value is derived from what the `def` type value represents at run-time. add `float 1.0` and `float 2.0` -> `float 3.0`; assign `float 3.0` to `f`; (note this example illustrates promotion done at run-time as promotion - done at compile-time would have resolved to a `def` type value) \ No newline at end of file + done at compile-time would have resolved to a `def` type value) diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index d9aea01c21a79..a897b8e8a04f0 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -463,4 +463,4 @@ the array type `int[][]`. <3> declare `int i`; access `ia3` -> `3-d int array reference`; access `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; - assign `int 99` to `i` \ No newline at end of file + assign `int 99` to `i` From 7b70e15f2ceb56b9104d5b3f41f3a3f0580ed863 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 22 May 2018 12:19:51 -0700 Subject: [PATCH 28/55] Start of structural change for operators. --- docs/painless/painless-lang-spec.asciidoc | 10 ++ .../painless-operators-array.asciidoc | 4 + .../painless-operators-boolean.asciidoc | 4 + .../painless-operators-general.asciidoc | 4 + .../painless-operators-numeric.asciidoc | 4 + .../painless-operators-reference.asciidoc | 4 + docs/painless/painless-operators.asciidoc | 110 +++++++++--------- 7 files changed, 87 insertions(+), 53 deletions(-) create mode 100644 docs/painless/painless-operators-array.asciidoc create mode 100644 docs/painless/painless-operators-boolean.asciidoc create mode 100644 docs/painless/painless-operators-general.asciidoc create mode 100644 docs/painless/painless-operators-numeric.asciidoc create mode 100644 docs/painless/painless-operators-reference.asciidoc diff --git a/docs/painless/painless-lang-spec.asciidoc b/docs/painless/painless-lang-spec.asciidoc index 5e6b84d8c57d1..66142618aa538 100644 --- a/docs/painless/painless-lang-spec.asciidoc +++ b/docs/painless/painless-lang-spec.asciidoc @@ -33,4 +33,14 @@ include::painless-casting.asciidoc[] include::painless-operators.asciidoc[] +include::painless-operators-general.asciidoc[] + +include::painless-operators-numeric.asciidoc[] + +include::painless-operators-boolean.asciidoc[] + +include::painless-operators-reference.asciidoc[] + +include::painless-operators-array.asciidoc[] + include::painless-general-syntax.asciidoc[] diff --git a/docs/painless/painless-operators-array.asciidoc b/docs/painless/painless-operators-array.asciidoc new file mode 100644 index 0000000000000..d236f03f13289 --- /dev/null +++ b/docs/painless/painless-operators-array.asciidoc @@ -0,0 +1,4 @@ +[[painless-operators-array]] +=== Operators: Array Type + +test diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc new file mode 100644 index 0000000000000..ffbaea2c77001 --- /dev/null +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -0,0 +1,4 @@ +[[painless-operators-boolean]] +=== Operators: Boolean + +test diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc new file mode 100644 index 0000000000000..ef602ba36d5e6 --- /dev/null +++ b/docs/painless/painless-operators-general.asciidoc @@ -0,0 +1,4 @@ +[[painless-operators-general]] +=== Operators: General + +test diff --git a/docs/painless/painless-operators-numeric.asciidoc b/docs/painless/painless-operators-numeric.asciidoc new file mode 100644 index 0000000000000..9fd1382226cd5 --- /dev/null +++ b/docs/painless/painless-operators-numeric.asciidoc @@ -0,0 +1,4 @@ +[[painless-operators-numeric]] +=== Operators: Numeric + +test diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc new file mode 100644 index 0000000000000..51639b0168b07 --- /dev/null +++ b/docs/painless/painless-operators-reference.asciidoc @@ -0,0 +1,4 @@ +[[painless-operators-reference]] +=== Operators: Reference Type + +test diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index 8329686f663af..f3bbd2e1394c0 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -1,62 +1,66 @@ [[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]. +An operator is the most basic action that can be taken to evaluate values in a +script. An expression is one-to-many consecutive operations. Precedence is the +order in which an operator will be evaluated relative to another operator. +Associativity is the direction within an expression in which a specific operator +is evaluated. The following table lists all available operators: [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 +| Operator | Symbol(s) | Precedence | Associativity +| Precedence | () | 0 | -> +| Field Access | . | 1 | -> +| Method Call | . () | 1 | -> +| Null Safe | ?. | 1 | -> +| Function Call | () | 1 | -> +| Array Initialization | [] {} | 1 | -> +| Array Access | [] | 1 | -> +| Array Length | . | 1 | -> +| List Initialization | [] | 1 | -> +| List Access | [] | 1 | -> +| Map Initialization | [:] | 1 | -> +| Map Access | [] | 1 | -> +| Post Increment | ++ | 1 | -> +| Post Decrement | -- | 1 | -> +| Pre Increment | ++ | 2 | <- +| Pre Decrement | -- | 2 | <- +| Unary Positive | + | 2 | <- +| Unary Negative | - | 2 | <- +| Boolean Not | ! | 2 | <- +| Bitwise Not | ~ | 2 | <- +| Cast | () | 3 | <- +| Mew Instance | new () | 3 | <- +| New Array | new | 3 | <- +| Multiplication | * | 4 | -> +| Division | / | 4 | -> +| Remainder | % | 4 | -> +| String Concatenation | + | 5 | -> +| Addition | + | 5 | -> +| Subtraction | - | 5 | -> +| Left Shift | << | 6 | -> +| Right Shift | >> | 6 | -> +| Unsigned Right Shift | >>> | 6 | -> +| Greater Than | > | 7 | -> +| Greater Than Or Equal | >= | 7 | -> +| Less Than | < | 7 | -> +| Less Than Or Equal | <= | 7 | -> +| Instance Of | instanceof | 8 | -> +| Equality Equals | == | 9 | -> +| Equality Not Equals | != | 9 | -> +| Identity Equals | === | 9 | -> +| Identity Not Equals | !== | 9 | -> +| Bitwise And | & | 10 | -> +| Boolean Xor | ^ | 11 | -> +| Bitwise Xor | ^ | 11 | -> +| Bitwise Or | \| | 12 | -> +| Boolean And | && | 13 | -> +| Boolean Or | \|\| | 14 | -> +| Conditional | ? : | 15 | <- +| Elvis | ?: | 16 | <- +| Assignment | = | 17 | <- +| Compound Assignment | $= | 17 | <- |==== [[precedence-operator]] From 093a10f566cb5ad7d35a2b23b06e306788e04c9e Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 22 May 2018 18:01:28 -0700 Subject: [PATCH 29/55] Moved operations to the appropriate pages. --- docs/painless/painless-identifiers.asciidoc | 2 +- .../painless-operators-array.asciidoc | 133 +- .../painless-operators-boolean.asciidoc | 514 ++++- .../painless-operators-general.asciidoc | 166 +- .../painless-operators-numeric.asciidoc | 661 +++++- .../painless-operators-reference.asciidoc | 321 ++- docs/painless/painless-operators.asciidoc | 1861 +---------------- docs/painless/painless-types.asciidoc | 67 +- docs/painless/painless-variables.asciidoc | 10 +- 9 files changed, 1879 insertions(+), 1856 deletions(-) diff --git a/docs/painless/painless-identifiers.asciidoc b/docs/painless/painless-identifiers.asciidoc index 7762f56cb7b23..7364e3a68ac99 100644 --- a/docs/painless/painless-identifiers.asciidoc +++ b/docs/painless/painless-identifiers.asciidoc @@ -3,7 +3,7 @@ Use an identifier as a named token to specify a <>, <>, -<>, <>, or function. +<>, <>, or function. <> cannot be used as identifiers. *Grammar* diff --git a/docs/painless/painless-operators-array.asciidoc b/docs/painless/painless-operators-array.asciidoc index d236f03f13289..2283a9e49fb0d 100644 --- a/docs/painless/painless-operators-array.asciidoc +++ b/docs/painless/painless-operators-array.asciidoc @@ -1,4 +1,133 @@ [[painless-operators-array]] -=== Operators: Array Type +=== Operators: Array -test +[[array-initialization]] +==== Array Initialization + +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]] +==== Array Access + +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 +---- + +[[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 +---- \ No newline at end of file diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc index ffbaea2c77001..298577759b01b 100644 --- a/docs/painless/painless-operators-boolean.asciidoc +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -1,4 +1,516 @@ [[painless-operators-boolean]] === Operators: Boolean -test +[[boolean-not]] +==== 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 +---- + +[[greater-than]] +==== 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 + +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 + +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 + +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]] +==== 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 + +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 + +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 + +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 + +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 +---- + +[[boolean-xor]] +==== 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 +---- + +[[boolean-and]] +==== 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 + +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 +---- \ No newline at end of file diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index ef602ba36d5e6..3cd1e21b3ec46 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -1,4 +1,168 @@ [[painless-operators-general]] === Operators: General -test +[[precedence]] +==== 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 +---- + +[[function-call]] +==== Function Call + +User-defined function calls can be made in Painless using the parenthesis +operator. See Function Calls [MARK] for more information. + +[[cast]] +==== Cast + +The cast operator can be used to explicitly convert one type to another. See casting [MARK] for more information. + +[[conditional]] +==== 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]] +==== 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 + +Assignment can be used to assign a value to a variable. See Variable Assignment [MARK] for more information. + +[[compound-assignment]] +==== 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') +---- \ No newline at end of file diff --git a/docs/painless/painless-operators-numeric.asciidoc b/docs/painless/painless-operators-numeric.asciidoc index 9fd1382226cd5..d4ae04e947374 100644 --- a/docs/painless/painless-operators-numeric.asciidoc +++ b/docs/painless/painless-operators-numeric.asciidoc @@ -1,4 +1,663 @@ [[painless-operators-numeric]] === Operators: Numeric -test +[[post-increment]] +==== 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]] +==== 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]] +==== 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]] +==== 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 + +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 + +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 +---- + +[[bitwise-not]] +==== 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 +---- + +[[multiplication]] +==== 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]] +==== 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]] +==== 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) +---- + +[[addition]] +==== 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]] +==== 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]] +==== 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]] +==== 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]] +==== 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 +---- + +[[bitwise-and]] +==== 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 +---- + +[[bitwise-xor]] +==== 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 + +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 +---- \ No newline at end of file diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 51639b0168b07..29216955a029e 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -1,4 +1,321 @@ [[painless-operators-reference]] -=== Operators: Reference Type +=== Operators: Reference -test +[[method-call]] +==== Method Call + +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 <>. +************************** + +[[field-access]] +==== Field Access +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 +---- + +[[null-safe]] +==== 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 +---- + +[[list-initialization]] +==== List Initialization + +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 +---- + +[[list-access]] +==== List Access + +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. + +[[map-initialization]] +==== Map Initialization + +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 +---- + +[[map-access]] +==== Map Access + +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. + +[[new-instance]] +==== New Instance + +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 +---- + +[[string-concatenation]] +==== 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" +---- \ No newline at end of file diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index f3bbd2e1394c0..eb2d7a13e2f95 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -10,1814 +10,55 @@ is evaluated. The following table lists all available operators: [options="header",cols="6,3,2,4"] |==== | Operator | Symbol(s) | Precedence | Associativity -| Precedence | () | 0 | -> -| Field Access | . | 1 | -> -| Method Call | . () | 1 | -> -| Null Safe | ?. | 1 | -> -| Function Call | () | 1 | -> -| Array Initialization | [] {} | 1 | -> -| Array Access | [] | 1 | -> -| Array Length | . | 1 | -> -| List Initialization | [] | 1 | -> -| List Access | [] | 1 | -> -| Map Initialization | [:] | 1 | -> -| Map Access | [] | 1 | -> -| Post Increment | ++ | 1 | -> -| Post Decrement | -- | 1 | -> -| Pre Increment | ++ | 2 | <- -| Pre Decrement | -- | 2 | <- -| Unary Positive | + | 2 | <- -| Unary Negative | - | 2 | <- -| Boolean Not | ! | 2 | <- -| Bitwise Not | ~ | 2 | <- -| Cast | () | 3 | <- -| Mew Instance | new () | 3 | <- -| New Array | new | 3 | <- -| Multiplication | * | 4 | -> -| Division | / | 4 | -> -| Remainder | % | 4 | -> -| String Concatenation | + | 5 | -> -| Addition | + | 5 | -> -| Subtraction | - | 5 | -> -| Left Shift | << | 6 | -> -| Right Shift | >> | 6 | -> -| Unsigned Right Shift | >>> | 6 | -> -| Greater Than | > | 7 | -> -| Greater Than Or Equal | >= | 7 | -> -| Less Than | < | 7 | -> -| Less Than Or Equal | <= | 7 | -> -| Instance Of | instanceof | 8 | -> -| Equality Equals | == | 9 | -> -| Equality Not Equals | != | 9 | -> -| Identity Equals | === | 9 | -> -| Identity Not Equals | !== | 9 | -> -| Bitwise And | & | 10 | -> -| Boolean Xor | ^ | 11 | -> -| Bitwise Xor | ^ | 11 | -> -| Bitwise Or | \| | 12 | -> -| Boolean And | && | 13 | -> -| Boolean Or | \|\| | 14 | -> -| Conditional | ? : | 15 | <- -| Elvis | ?: | 16 | <- -| Assignment | = | 17 | <- -| Compound Assignment | $= | 17 | <- +| <> | () | 0 | left +| <> | . () | 1 | left +| <> | . | 1 | left +| <> | ?. | 1 | left +| <> | () | 1 | left +| <> | [] {} | 1 | left +| <> | [] | 1 | left +| <> | . | 1 | left +| <> | [] | 1 | left +| <> | [] | 1 | left +| <> | [:] | 1 | left +| <> | [] | 1 | left +| <> | ++ | 1 | left +| <> | -- | 1 | left +| <> | ++ | 2 | right +| <> | -- | 2 | right +| <> | + | 2 | right +| <> | - | 2 | right +| <> | ! | 2 | right +| <> | ~ | 2 | right +| <> | () | 3 | right +| <> | new () | 3 | right +| <> | new | 3 | right +| <> | * | 4 | left +| <> | / | 4 | left +| <> | % | 4 | left +| <> | + | 5 | left +| <> | + | 5 | left +| <> | - | 5 | left +| <> | << | 6 | left +| <> | >> | 6 | left +| <> | >>> | 6 | left +| <> | > | 7 | left +| <> | >= | 7 | left +| <> | < | 7 | left +| <> | <= | 7 | left +| <> | instanceof | 8 | left +| <> | == | 9 | left +| <> | != | 9 | left +| <> | === | 9 | left +| <> | !== | 9 | left +| <> | & | 10 | left +| <> | ^ | 11 | left +| <> | ^ | 11 | left +| <> | \| | 12 | left +| <> | && | 13 | left +| <> | \|\| | 14 | left +| <> | ? : | 15 | right +| <> | ?: | 16 | right +| <> | = | 17 | right +| <> | $= | 17 | right |==== - -[[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') ----- diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index a897b8e8a04f0..6a759c4da067c 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -12,15 +12,15 @@ belongs to one of the following categories: <>, A primitive type represents basic data built natively into the JVM and is allocated to non-heap memory. Declare a primitive type -<>, and assign it a primitive type value for -evaluation during later operations. The default value for a newly-declared -primitive type variable is listed as part of the definitions below. A primitive -type value is copied during an assignment or as an argument for a -method/function call. +<> or access a primitive type member field (from +a reference type instance), and assign it a primitive type value for evaluation +during later operations. The default value for a newly-declared primitive type +variable is listed as part of the definitions below. A primitive type value is +copied during an assignment or as an argument for a method/function call. A primitive type has a corresponding reference type (also known as a boxed type). Use the <> or -<> on a primitive type value to force +<> on a primitive type value to force evaluation as its corresponding reference type value. The following primitive types are available: @@ -113,19 +113,20 @@ multiple pieces of data (member fields) and logic to manipulate that data A reference type instance is a single set of data for one reference type object allocated to the heap. Use the -<> to allocate a reference type -instance. Use a reference type instance to load from, store to, and manipulate -complex data. +<> to allocate a reference type instance. +Use a reference type instance to load from, store to, and manipulate complex +data. A reference type value refers to a reference type instance, and multiple reference type values may refer to the same reference type instance. A change to a reference type instance will affect all reference type values referring to that specific instance. -Declare a reference type <>, and assign it a -reference type value for evaluation during later operations. The default value -for a newly-declared reference type variable is `null`. A reference type value -is shallow-copied during an assignment or as an argument for a method/function +Declare a reference type <> or access a reference +type member field (from a reference type instance), and assign it a reference +type value for evaluation during later operations. The default value for a +newly-declared reference type variable is `null`. A reference type value is +shallow-copied during an assignment or as an argument for a method/function call. Assign `null` to a reference type variable to indicate the reference type value refers to no reference type instance. The JVM will garbage collect a reference type instance when it is no longer referred to by any reference type @@ -155,7 +156,7 @@ type instance is required to use a non-static member field. static member method:: A static member method is a function called on a reference type *object*. Use -the <> in correspondence with the reference +the <> in correspondence with the reference type object name to call a static member method. No reference type instance allocation is necessary to use a static member method. @@ -164,7 +165,7 @@ non-static member method:: A non-static member method is a function called on a reference type *instance*. A non-static member method called on a reference type instance can load from and store to non-static member fields of that specific reference type instance. Use -the <> in correspondence with a specific +the <> in correspondence with a specific reference type instance to call a non-static member method. An allocated reference type instance is required to use a non-static member method. @@ -172,8 +173,7 @@ constructor:: A constructor is a special type of function used to allocate a reference type *instance* defined by a specific reference type *object*. Use the -<> to allocate a reference type -instance. +<> to allocate a reference type instance. A reference type object follows a basic inheritance model. Consider types A and B. Type A is considered to be a parent of B, and B a child of A, if B inherits @@ -268,11 +268,12 @@ the behavior of whatever value it represents at run-time and will always represent the child-most descendant type value of any type value when evaluated during operations. -Declare a `def` type <>, and assign it -any type of value for evaluation during later operations. The default value -for a newly-declared `def` type variable is `null`. A `def` type variable or -method/function parameter can change the type it represents during the -compilation and evaluation of a script. +Declare a `def` type <> or access a `def` type +member field (from a reference type instance), and assign it any type of value +for evaluation during later operations. The default value for a newly-declared +`def` type variable is `null`. A `def` type variable or method/function +parameter can change the type it represents during the compilation and +evaluation of a script. Using the `def` type can have a slight impact on performance. Use only primitive types and reference types directly when performance is critical. @@ -335,8 +336,7 @@ types and reference types directly when performance is critical. The `String` type is a specialized reference type that does not require explicit allocation. Use a <> to directly evaluate a `String` type value. While not required, the -<> can allocate `String` type -instances. +<> can allocate `String` type instances. *Examples* @@ -389,15 +389,16 @@ the array type instance. Use the <> or the <> to allocate an array -type instance. Declare an array type <>, and -assign it an array type value for evaluation during later operations. The -default value for a newly-declared array type variable is `null`. An array type -value is shallow-copied during an assignment or as an argument for a -method/function call. Assign `null` to an array type variable to indicate the -array type value refers to no array type instance. The JVM will garbage collect -an array type instance when it is no longer referred to by any array type -values. Pass `null` as an argument to a method/function call to indicate the -argument refers to no array type instance. +type instance. Declare an array type <> or access +an array type member field (from a reference type instance), and assign it an +array type value for evaluation during later operations. The default value for a +newly-declared array type variable is `null`. An array type value is +shallow-copied during an assignment or as an argument for a method/function +call. Assign `null` to an array type variable to indicate the array type value +refers to no array type instance. The JVM will garbage collect an array type +instance when it is no longer referred to by any array type values. Pass `null` +as an argument to a method/function call to indicate the argument refers to no +array type instance. Use the <> to retrieve the length of an array type value as an int type value. Use the diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 8b8782b151132..8df0202773701 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -12,10 +12,10 @@ followed by <>. Declare an <> variable using an opening `[` token and a closing `]` token for each dimension directly after the identifier. Specify a comma-separated list of identifiers following the type to declare multiple -variables in a single statement. Use an <> -combined with a declaration to immediately assign a value to a variable. -A variable not immediately assigned a value will have a default value assigned -implicitly based on the type. +variables in a single statement. Use an +<> combined with a declaration to +immediately assign a value to a variable. A variable not immediately assigned a +value will have a default value assigned implicitly based on the type. *Errors* @@ -63,7 +63,7 @@ assignment: '=' expression; <7> declare `Map[][] m`; assign default `null` to `m` -[[assignment]] +[[variable-assignment]] ==== Assignment Use the *assignment operator* to store a value in a variable. Any operation From bb4dc1cde60cd46edc07cac21ba645bb15c68486 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 23 May 2018 13:31:45 -0700 Subject: [PATCH 30/55] More clean up. --- docs/painless/painless-operators.asciidoc | 106 +++++++++++----------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index eb2d7a13e2f95..4ed7ff3675279 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -7,58 +7,58 @@ order in which an operator will be evaluated relative to another operator. Associativity is the direction within an expression in which a specific operator is evaluated. The following table lists all available operators: -[options="header",cols="6,3,2,4"] +[cols="<6,<3,^3,^2,^4"] |==== -| Operator | Symbol(s) | Precedence | Associativity -| <> | () | 0 | left -| <> | . () | 1 | left -| <> | . | 1 | left -| <> | ?. | 1 | left -| <> | () | 1 | left -| <> | [] {} | 1 | left -| <> | [] | 1 | left -| <> | . | 1 | left -| <> | [] | 1 | left -| <> | [] | 1 | left -| <> | [:] | 1 | left -| <> | [] | 1 | left -| <> | ++ | 1 | left -| <> | -- | 1 | left -| <> | ++ | 2 | right -| <> | -- | 2 | right -| <> | + | 2 | right -| <> | - | 2 | right -| <> | ! | 2 | right -| <> | ~ | 2 | right -| <> | () | 3 | right -| <> | new () | 3 | right -| <> | new | 3 | right -| <> | * | 4 | left -| <> | / | 4 | left -| <> | % | 4 | left -| <> | + | 5 | left -| <> | + | 5 | left -| <> | - | 5 | left -| <> | << | 6 | left -| <> | >> | 6 | left -| <> | >>> | 6 | left -| <> | > | 7 | left -| <> | >= | 7 | left -| <> | < | 7 | left -| <> | <= | 7 | left -| <> | instanceof | 8 | left -| <> | == | 9 | left -| <> | != | 9 | left -| <> | === | 9 | left -| <> | !== | 9 | left -| <> | & | 10 | left -| <> | ^ | 11 | left -| <> | ^ | 11 | left -| <> | \| | 12 | left -| <> | && | 13 | left -| <> | \|\| | 14 | left -| <> | ? : | 15 | right -| <> | ?: | 16 | right -| <> | = | 17 | right -| <> | $= | 17 | right +| *Operator* | *Category* | *Symbol(s)* | *Precedence* | *Associativity* +| <> | <> | () | 0 | left -> right +| <> | <> | . () | 1 | left -> right +| <> | <> | . | 1 | left -> right +| <> | <> | ?. | 1 | left -> right +| <> | <> | () | 1 | left -> right +| <> | <> | [] {} | 1 | left -> right +| <> | <> | [] | 1 | left -> right +| <> | <> | . | 1 | left -> right +| <> | <> | [] | 1 | left -> right +| <> | <> | [] | 1 | left -> right +| <> | <> | [:] | 1 | left -> right +| <> | <> | [] | 1 | left -> right +| <> | <> | ++ | 1 | left -> right +| <> | <> | -- | 1 | left -> right +| <> | <> | ++ | 2 | right -> left +| <> | <> | -- | 2 | right -> left +| <> | <> | + | 2 | right -> left +| <> | <> | - | 2 | right -> left +| <> | <> | ! | 2 | right -> left +| <> | <> | ~ | 2 | right -> left +| <> | <> | () | 3 | right -> left +| <> | <> | new () | 3 | right -> left +| <> | <> | new | 3 | right -> left +| <> | <> | * | 4 | left -> right +| <> | <> | / | 4 | left -> right +| <> | <> | % | 4 | left -> right +| <> | <> | + | 5 | left -> right +| <> | <> | + | 5 | left -> right +| <> | <> | - | 5 | left -> right +| <> | <> | << | 6 | left -> right +| <> | <> | >> | 6 | left -> right +| <> | <> | >>> | 6 | left -> right +| <> | <> | > | 7 | left -> right +| <> | <> | >= | 7 | left -> right +| <> | <> | < | 7 | left -> right +| <> | <> | <= | 7 | left -> right +| <> | <> | instanceof | 8 | left -> right +| <> | <> | == | 9 | left -> right +| <> | <> | != | 9 | left -> right +| <> | <> | === | 9 | left -> right +| <> | <> | !== | 9 | left -> right +| <> | <> | & | 10 | left -> right +| <> | <> | ^ | 11 | left -> right +| <> | <> | ^ | 11 | left -> right +| <> | <> | \| | 12 | left -> right +| <> | <> | && | 13 | left -> right +| <> | <> | \|\| | 14 | left -> right +| <> | <> | ? : | 15 | right -> left +| <> | <> | ?: | 16 | right -> left +| <> | <> | = | 17 | right -> left +| <> | <> | $= | 17 | right -> left |==== From a122212939315b9a722d2d37d74b98eca9a6824d Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 24 May 2018 11:48:52 -0700 Subject: [PATCH 31/55] Added a casting table. --- docs/painless/painless-casting.asciidoc | 49 +++++++++++++++++++ .../painless-operators-general.asciidoc | 5 +- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index a3624f9083145..449d04810c222 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -7,6 +7,9 @@ during certain <>. An explicit cast specifies the target type and forcefully occurs as its own operation. Use the *cast operator* to specify an explicit cast. +See the <> for a quick reference on all +allowed casts. + *Errors* * If during a cast there exists no equivalent value for the target type. @@ -454,3 +457,49 @@ type value is derived from what the `def` type value represents at run-time. assign `float 3.0` to `f`; (note this example illustrates promotion done at run-time as promotion done at compile-time would have resolved to a `def` type value) + +[[allowed-casts]] +==== Allowed Casts + +The following table lists all allowed casts (with implicit as I, explicit as +E, and not allowed as -): + +[cols="<3,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1"] +|==== +| | b | s | c | i | j | f | d | B | S | C | I | L | F | D | T | R | def +| byte (b) | | I | I | I | I | I | I | - | - | - | - | - | - | - | - | - | I +| short (s) | E | | E | I | I | I | I | - | - | - | - | - | - | - | - | - | I +| char (c) | E | E | | I | I | I | I | - | - | - | - | - | - | - | E | - | I +| int (i) | E | E | E | | I | I | I | - | - | - | - | - | - | - | - | - | I +| long (j) | E | E | E | E | | I | I | - | - | - | - | - | - | - | - | - | I +| float (f) | E | E | E | E | E | | I | - | - | - | - | - | - | - | - | - | I +| double (d) | E | E | E | E | E | E | | - | - | - | - | - | - | - | - | - | I +| Byte (B) | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | - | I +| Short (S) | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | I +| Character (C) | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | I +| Integer (I) | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | I +| Long (L) | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | I +| Float (F) | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | I +| Double (D) | - | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | I +| String (T) | - | - | E | - | - | - | - | - | - | - | - | - | - | - | | - | I +| Reference ( R ) | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | @ | I +| def as byte | I | I | I | I | I | I | I | I | I | I | I | I | I | I | - | - | +| def as short | E | I | E | I | I | I | I | E | I | E | I | I | I | I | - | - | +| def as char | E | E | I | I | I | I | I | E | E | I | I | I | I | I | E | - | +| def as int | E | E | E | I | I | I | I | E | E | E | I | I | I | I | - | - | +| def as long | E | E | E | E | I | I | I | E | E | E | E | I | I | I | - | - | +| def as float | E | E | E | E | E | I | I | E | E | E | E | E | I | I | - | - | +| def as double | E | E | E | E | E | E | I | E | E | E | E | E | E | I | - | - | +| def as Byte | I | I | I | I | I | I | I | I | I | I | I | I | I | I | - | - | +| def as Short | E | I | E | I | I | I | I | E | I | E | I | I | I | I | - | - | +| def as Character | E | E | I | I | I | I | I | E | E | I | I | I | I | I | - | - | +| def as Integer | E | E | E | I | I | I | I | E | E | E | I | I | I | I | - | - | +| def as Long | E | E | E | E | I | I | I | E | E | E | E | I | I | I | - | - | +| def as Float | E | E | E | E | E | I | I | E | E | E | E | E | I | I | - | - | +| def as Double | E | E | E | E | E | E | I | E | E | E | E | E | E | I | - | - | +| def as String | - | - | E | - | - | - | - | - | - | - | - | - | - | - | I | - | +| def as Reference | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | @ | +|==== + +@ See <> for allowed reference + type casts. diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 3cd1e21b3ec46..1dbbe6d59209c 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -4,9 +4,8 @@ [[precedence]] ==== 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`. +Use the *precedence operator* to guarantee the order of evaluation and override +existing precedence relationships between operators. *Grammar:* [source,ANTLR4] From 26658353eb329666d18c86a74e17942980462b77 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 24 May 2018 13:02:21 -0700 Subject: [PATCH 32/55] Switch assign/access to store/load in examples. --- docs/painless/painless-casting.asciidoc | 153 +++++++++--------- .../painless-operators-general.asciidoc | 29 ++-- docs/painless/painless-types.asciidoc | 94 +++++------ docs/painless/painless-variables.asciidoc | 72 ++++----- 4 files changed, 180 insertions(+), 168 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 449d04810c222..52a0d6f7da2da 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -34,15 +34,15 @@ cast: '(' TYPE ')' expression + <1> declare `int i`; explicit cast `long 5` to `int 5` -> `int 5`; - assign `int 5` to `i` + store `int 5` to `i` <2> declare `Map m`; allocate `HashMap` instance -> `HashMap reference`; implicit cast `HashMap reference` to `Map reference` -> `Map reference`; - assign `Map reference` to `m` + store `Map reference` to `m` <3> declare `HashMap hm`; - access `m` -> `Map reference`; + load from `m` -> `Map reference`; explicit cast `Map reference` to `HashMap reference` -> `HashMap reference`; - assign `HashMap reference` to `hm` + store `HashMap reference` to `hm` [[numeric-type-casting]] ==== Numeric Type Casting @@ -81,19 +81,19 @@ following table: ---- + <1> declare `int a`; - assign `int 1` to `a` + store `int 1` to `a` <2> declare `long b`; - access `a` -> `int 1`; + load from `a` -> `int 1`; implicit cast `int 1` to `long 1` -> `long 1`; - assign `long 1` to `b` + store `long 1` to `b` <3> declare `short c`; - access `b` -> `long 1`; + load from `b` -> `long 1`; explicit cast `long 1` to `short 1` -> `short 1`; - assign `short 1` value to `c` + store `short 1` value to `c` <4> declare `double e`; - access `a` -> `int 1`; + load from `a` -> `int 1`; explicit cast `int 1` to `double 1.0`; - assign `double 1.0` to `e`; + store `double 1.0` to `e`; (note the explicit cast is extraneous since an implicit cast is valid) + * Invalid numeric type casts resulting in errors. @@ -109,9 +109,9 @@ following table: *error* -> cannot implicit cast `double 1.0` to `int 1`; (note an explicit cast is valid) <2> declare `int b`; - assign `int 2` to `b` + store `int 2` to `b` <3> declare byte `c`; - access `b` -> `int 2`; + load from `b` -> `int 2`; *error* -> cannot implicit cast `int 2` to `byte 2`; (note an explicit cast is valid) @@ -139,21 +139,21 @@ or the target type is a descendant of the original type. ---- + <1> declare `List x`; - assign default value `null` to `x` + store default value `null` to `x` <2> declare `ArrayList y`; allocate `ArrayList` instance -> `ArrayList reference`; - assign `ArrayList reference` to `y`; -<3> access `y` -> `ArrayList reference`; + store `ArrayList reference` to `y`; +<3> load from `y` -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; - assign `List reference` to `x`; + store `List reference` to `x`; (note `ArrayList` is a descendant of `List`) -<4> access `x` -> `List reference`; +<4> load from `x` -> `List reference`; explicit cast `List reference` to `ArrayList reference` -> `ArrayList reference`; - assign `ArrayList reference` to `y`; -<5> access `y` -> `ArrayList reference`; + store `ArrayList reference` to `y`; +<5> load from `y` -> `ArrayList reference`; explicit cast `ArrayList reference` to `List reference` -> `List reference`; - assign `List reference` to `x`; + store `List reference` to `x`; (note the explicit cast is extraneous, and an implicit cast is valid) + * Invalid reference type casts resulting in errors. @@ -168,13 +168,13 @@ or the target type is a descendant of the original type. <1> declare `List x`; allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; - assign `List reference` to `x` + store `List reference` to `x` <2> declare `ArrayList y`; - access `x` -> `List reference`; + load from `x` -> `List reference`; *error* -> cannot implicit cast `List reference` to `ArrayList reference`; (note an explicit cast is valid since `ArrayList` is a descendant of `List`) <3> declare `ArrayList y`; - access `x` -> `List reference`; + load from `x` -> `List reference`; *error* -> cannot explicit cast `List reference` to `Map reference`; (note no cast would be valid since neither `List` nor `Map` is a descendant of the other) @@ -209,24 +209,24 @@ based on the current type value the `def` type value represents. + <1> declare `def d0`; implicit cast `int 3` to `def`; - assign `int 3` to `d0` + store `int 3` to `d0` <2> allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `def` -> `def`; - assign `def` to `d0` + store `def` to `d0` <3> declare `Object o`; allocate `HashMap` instance -> `HashMap reference`; implicit cast `HashMap reference` to `Object reference` -> `Object reference`; - assign `Object reference` to `o` + store `Object reference` to `o` <4> declare `def d1`; - access `o` -> `Object reference`; + load from `o` -> `Object reference`; implicit cast `Object reference` to `def` -> `def`; - assign `def` to `d1` + store `def` to `d1` <5> declare `int i`; - access `d1` -> `def`; + load from `d1` -> `def`; implicit cast `def` to `HashMap reference` -> HashMap reference`; call `size` on `HashMap reference` -> `int 0`; - assign `int 0` to `i`; + store `int 0` to `i`; (note `def` was implicit cast to `HashMap reference` since `HashMap` is the child-most descendant type value that the `def` type value represents) @@ -245,29 +245,29 @@ based on the current type value the `def` type value represents. + <1> declare `def d`; implicit cast `double 1.0` to `def` -> `def`; - assign `def` to `d` + store `def` to `d` <2> declare `int i`; - access `d` -> `def`; + load from `d` -> `def`; implicit cast `def` to `double 1.0` -> `double 1.0`; explicit cast `double 1.0` to `int 1` -> `int 1`; - assign `int 1` to `i`; + store `int 1` to `i`; (note the explicit cast is necessary since a `double` value cannot be converted to an `int` value implicitly) -<3> assign `int 1` to `d`; +<3> store `int 1` to `d`; (note the switch in the type `d` represents from `double` to `int`) <4> declare `float i`; - access `d` -> `def`; + load from `d` -> `def`; implicit cast `def` to `int 1` -> `int 1`; implicit cast `int 1` to `float 1.0` -> `float 1.0`; - assign `float 1.0` to `f` + store `float 1.0` to `f` <5> allocate `ArrayList` instance -> `ArrayList reference`; - assign `ArrayList reference` to `d`; + store `ArrayList reference` to `d`; (note the switch in the type `d` represents from `int` to `ArrayList`) <6> declare `List l`; - access `d` -> `def`; + load from `d` -> `def`; implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; - assign `List reference` to `l` + store `List reference` to `l` + * Invalid dynamic type casts resulting in errors. + @@ -280,17 +280,17 @@ based on the current type value the `def` type value represents. ---- <1> declare `def d`; implicit cast `int 1` to `def` -> `def`; - assign `def` to `d` + store `def` to `d` <2> declare `short s`; - access `d` -> `def`; + load from `d` -> `def`; implicit cast `def` to `int 1` -> `int 1`; *error* -> cannot implicit cast `int 1` to `short 1`; (note an explicit cast is valid) <3> allocate `HashMap` instance -> `HashMap reference`; implicit cast `HashMap reference` to `def` -> `def`; - assign `def` to `d` + store `def` to `d` <4> declare `List l`; - access `d` -> `def`; + load from `d` -> `def`; implicit cast `def` to `HashMap reference`; *error* -> cannot implicit cast `HashMap reference` to `List reference`; (note no cast would be valid since neither `HashMap` nor `List` is a @@ -319,9 +319,9 @@ Use the *cast operator* to convert a <> value into a + <1> declare `char c`; explicit cast `String "C"` to `char C` -> `char C`; - assign `char C` to `c` + store `char C` to `c` <2> explicit cast `String 'c'` to `char c` -> `char c`; - assign `char c` to `c` + store `char c` to `c` + * Casting a `String` reference into a `char` value. + @@ -331,11 +331,11 @@ Use the *cast operator* to convert a <> value into a <2> char c = (char)s; ---- <1> declare `String s`; - assign `String "s"` to `s`; + store `String "s"` to `s`; <2> declare `char c` - access `s` -> `String "s"`; + load from `s` -> `String "s"`; explicit cast `String "s"` to `char s` -> `char s`; - assign `char s` to `c` + store `char s` to `c` [[boxing-unboxing]] ==== Boxing and Unboxing @@ -375,22 +375,22 @@ value and vice versa. + <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; - assign `ArrayList reference` to `l`; -<2> access `l` -> `List reference`; + store `ArrayList reference` to `l`; +<2> load from `l` -> `List reference`; implicit cast `int 1` to `def` -> `def`; call `add` on `List reference` with arguments (`def`); (note internally `int 1` is boxed to `Integer 1` to store as a `def` type value) <3> declare `Integer I`; call `valueOf` on `Integer` with arguments of (`int 0`) -> `Integer 0`; - assign `Integer 0` to `I`; + store `Integer 0` to `I`; <4> declare `int i`; - access `I` -> `Integer 0`; + load from `I` -> `Integer 0`; unbox `Integer 0` -> `int 0`; - access `l` -> `List reference`; + load from `l` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def`; implicit cast `def` to `int 1` -> `int 1`; - assign `int 1` to `i`; + store `int 1` to `i`; (note internally `int 1` is unboxed from `Integer 1` when loaded from a `def` type value) + @@ -444,44 +444,45 @@ type value is derived from what the `def` type value represents at run-time. promote `int 2` and `double 2.0 @0` -> `double 2.0 @0`; implicit cast `int 2` to `double 2.0 @1` -> `double 2.0 @1`; add `double 2.0 @1` and `double 2.0 @0` -> `double 4.0`; - assign `double 4.0` to `d` + store `double 4.0` to `d` <2> declare `def x`; implicit cast `int 1` to `def` -> `def`; - assign `def` to `x`; + store `def` to `x`; <3> declare `float f`; - access `x` -> `def`; + load from `x` -> `def`; implicit cast `def` to `int 1` -> `int 1`; promote `int 1` and `float 2.0` -> `float 2.0`; implicit cast `int 1` to `float 1.0` -> `float `1.0`; add `float 1.0` and `float 2.0` -> `float 3.0`; - assign `float 3.0` to `f`; + store `float 3.0` to `f`; (note this example illustrates promotion done at run-time as promotion done at compile-time would have resolved to a `def` type value) [[allowed-casts]] ==== Allowed Casts -The following table lists all allowed casts (with implicit as I, explicit as -E, and not allowed as -): +The following table lists all allowed casts read as row (original type) to +column (target type) with implicit as `I`, explicit as `E`, and not allowed as +`-`: [cols="<3,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1"] |==== | | b | s | c | i | j | f | d | B | S | C | I | L | F | D | T | R | def -| byte (b) | | I | I | I | I | I | I | - | - | - | - | - | - | - | - | - | I -| short (s) | E | | E | I | I | I | I | - | - | - | - | - | - | - | - | - | I -| char (c) | E | E | | I | I | I | I | - | - | - | - | - | - | - | E | - | I -| int (i) | E | E | E | | I | I | I | - | - | - | - | - | - | - | - | - | I -| long (j) | E | E | E | E | | I | I | - | - | - | - | - | - | - | - | - | I -| float (f) | E | E | E | E | E | | I | - | - | - | - | - | - | - | - | - | I -| double (d) | E | E | E | E | E | E | | - | - | - | - | - | - | - | - | - | I -| Byte (B) | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | - | I -| Short (S) | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | I -| Character (C) | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | I -| Integer (I) | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | I -| Long (L) | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | I -| Float (F) | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | I -| Double (D) | - | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | I -| String (T) | - | - | E | - | - | - | - | - | - | - | - | - | - | - | | - | I +| byte ( b ) | | I | I | I | I | I | I | - | - | - | - | - | - | - | - | - | I +| short ( s ) | E | | E | I | I | I | I | - | - | - | - | - | - | - | - | - | I +| char ( c ) | E | E | | I | I | I | I | - | - | - | - | - | - | - | E | - | I +| int ( i ) | E | E | E | | I | I | I | - | - | - | - | - | - | - | - | - | I +| long ( j ) | E | E | E | E | | I | I | - | - | - | - | - | - | - | - | - | I +| float ( f ) | E | E | E | E | E | | I | - | - | - | - | - | - | - | - | - | I +| double ( d ) | E | E | E | E | E | E | | - | - | - | - | - | - | - | - | - | I +| Byte ( B ) | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | - | I +| Short ( S ) | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | I +| Character ( C ) | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | I +| Integer ( I ) | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | I +| Long ( L ) | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | I +| Float ( F ) | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | I +| Double ( D ) | - | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | I +| String ( T ) | - | - | E | - | - | - | - | - | - | - | - | - | - | - | | - | I | Reference ( R ) | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | @ | I | def as byte | I | I | I | I | I | I | I | I | I | I | I | I | I | I | - | - | | def as short | E | I | E | I | I | I | I | E | I | E | I | I | I | I | - | - | diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 1dbbe6d59209c..69162a86bb54f 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -4,23 +4,34 @@ [[precedence]] ==== Precedence -Use the *precedence operator* to guarantee the order of evaluation and override -existing precedence relationships between operators. +Use the *precedence operator* to guarantee the order of evaluation for an +expression and override existing precedence relationships between operators. -*Grammar:* +*Grammar* [source,ANTLR4] ---- precedence: '(' expression ')'; ---- -*Examples:* -[source,Java] +*Examples* + +* Use of the precedence operator. ++ +[source,Painless] ---- -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 +<1> int x = (5+4)*6; +<2> int y = 12/(x-50); ---- ++ +<1> declare `int x`; + add `int 5` and `int 4` -> `int 9`; + multiply `int 9` and `int 6` -> `int 54`; + assign `int 54` to `x`; + (note the add is evaluated before the multiply due to the *precedence + operator*) +<2> declare `int y`; + load `x` + [[function-call]] ==== Function Call diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 0a8c030f36a97..0580a2a3c86ec 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -83,11 +83,11 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign `int 1` to `i` + store `int 1` to `i` <2> declare `double d`; - assign default `double 0.0` to `d` + store default `double 0.0` to `d` <3> declare `boolean b`; - assign `boolean true` to `b` + store `boolean true` to `b` + * Method call on a primitive type using the corresponding reference type. + @@ -98,8 +98,8 @@ logical quantity with two possible values of `true` and `false` ---- + <1> declare `int i`; - assign `int 1` to `i` -<2> access `i` -> `int 1`; + store `int 1` to `i` +<2> load from `i` -> `int 1`; box `int 1` -> `Integer 1 reference`; call `toString` on `Integer 1 reference` -> `String '1'` @@ -197,16 +197,16 @@ relationships. <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; - assign `List reference` to `l` -<2> access `l` -> `List reference`; + store `List reference` to `l` +<2> load from `l` -> `List reference`; implicit cast `int 1` to `def` -> `def` call `add` on `List reference` with arguments (`def`) <3> declare `int i`; - access `l` -> `List reference`; + load from `l` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def`; implicit cast `def` to `int 1` -> `int 1`; add `int 1` and `int 2` -> `int 3`; - assign `int 3` to `i` + store `int 3` to `i` + * Sharing a reference type instance. + @@ -222,26 +222,26 @@ relationships. <1> declare `List l0`; allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; - assign `List reference` to `l0` + store `List reference` to `l0` <2> declare `List l1`; - access `l0` -> `List reference`; - assign `List reference` to `l1` + load from `l0` -> `List reference`; + store `List reference` to `l1` (note `l0` and `l1` refer to the same instance known as a shallow-copy) -<3> access `l0` -> `List reference`; +<3> load from `l0` -> `List reference`; implicit cast `int 1` to `def` -> `def` call `add` on `List reference` with arguments (`def`) -<4> access `l1` -> `List reference`; +<4> load from `l1` -> `List reference`; implicit cast `int 2` to `def` -> `def` call `add` on `List reference` with arguments (`def`) <5> declare `int i`; - access `l0` -> `List reference`; + load from `l0` -> `List reference`; call `get` on `List reference` with arguments (`int 0`) -> `def @0`; implicit cast `def @0` to `int 1` -> `int 1`; - access `l1` -> `List reference`; + load from `l1` -> `List reference`; call `get` on `List reference` with arguments (`int 1`) -> `def @1`; implicit cast `def @1` to `int 2` -> `int 2`; add `int 1` and `int 2` -> `int 3`; - assign `int 3` to `i`; + store `int 3` to `i`; + * Using the static members of a reference type. + @@ -252,11 +252,11 @@ relationships. ---- + <1> declare `int i`; - access `MAX_VALUE` on `Integer` -> `int 2147483647`; - assign `int 2147483647` to `i` + load from `MAX_VALUE` on `Integer` -> `int 2147483647`; + store `int 2147483647` to `i` <2> declare `long l`; call `parseLong` on `Long` with arguments (`long 123`) -> `long 123`; - assign `long 123` to `l` + store `long 123` to `l` [[dynamic-types]] ==== Dynamic Types @@ -295,13 +295,13 @@ types and reference types directly when performance is critical. + <1> declare `def dp`; implicit cast `int 1` to `def` -> `def`; - assign `def` to `dp` + store `def` to `dp` <2> declare `def dr`; allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `def` -> `def`; - assign `def` to `dr` -<3> access `dp` -> `def`; - assign `def` to `dr`; + store `def` to `dr` +<3> load from `dp` -> `def`; + store `def` to `dr`; (note the switch in the type `dr` represents from `ArrayList` to `int`) + * A `def` type value representing the child-most descendant of a value. @@ -317,12 +317,12 @@ types and reference types directly when performance is critical. allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `Object reference` -> `Object reference`; - assign `Object reference` to `l` + store `Object reference` to `l` <2> declare `def d`; - access `l` -> `Object reference`; + load from `l` -> `Object reference`; implicit cast `Object reference` to `def` -> `def`; - assign `def` to `d`; -<3> access `d` -> `def`; + store `def` to `d`; +<3> load from `d` -> `def`; implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; call `ensureCapacity` on `ArrayList reference` with arguments (`int 10`); (note `def` was implicit cast to `ArrayList reference` @@ -350,15 +350,15 @@ explicit allocation. Use a <> to directly evaluate a ---- + <1> declare `String r`; - assign `String "some text"` to `r` + store `String "some text"` to `r` <2> declare `String s`; - assign `String 'some text'` to `s` + store `String 'some text'` to `s` <3> declare `String t`; allocate `String` instance with arguments (`String "some text"`) -> `String "some text"`; - assign `String "some text"` to `t` + store `String "some text"` to `t` <4> declare `String u`; - assign default `null` to `u` + store default `null` to `u` [[void-type]] ==== void Type @@ -426,24 +426,24 @@ the array type `int[][]`. ---- + <1> declare `int[] x`; - assign default `null` to `x` + store default `null` to `x` <2> declare `float[] y`; allocate `1-d float array` instance with `length [10]` -> `1-d float array reference`; - assign `1-d float array reference` to `y` + store `1-d float array reference` to `y` <3> declare `def z`; allocate `1-d float array` instance with `length [5]` -> `1-d float array reference`; implicit cast `1-d float array reference` to `def` -> `def`; - assign `def` to `z` -<4> access `y` -> `1-d float array reference`; - assign `float 1.0` to `index [9]` of `1-d float array reference` -<5> access `y` -> `1-d float array reference @0`; - access `index [9]` of `1-d float array reference @0` -> `float 1.0`; - access `z` -> `def`; + store `def` to `z` +<4> load from `y` -> `1-d float array reference`; + store `float 1.0` to `index [9]` of `1-d float array reference` +<5> load from `y` -> `1-d float array reference @0`; + load from `index [9]` of `1-d float array reference @0` -> `float 1.0`; + load from `z` -> `def`; implicit cast `def` to `1-d float array reference @1` -> `1-d float array reference @1`; - assign `float 1.0` to `index [0]` of `1-d float array reference @1` + store `float 1.0` to `index [0]` of `1-d float array reference @1` + * Use of a multi-dimensional array. + @@ -457,10 +457,10 @@ the array type `int[][]`. <1> declare `int[][][] ia`; allocate `3-d int array` instance with length `[2, 3, 4]` -> `3-d int array reference`; - assign `3-d int array reference` to `ia3` -<2> access `ia3` -> `3-d int array reference`; - assign `int 99` to `index [1, 2, 3]` of `3-d int array reference` + store `3-d int array reference` to `ia3` +<2> load from `ia3` -> `3-d int array reference`; + store `int 99` to `index [1, 2, 3]` of `3-d int array reference` <3> declare `int i`; - access `ia3` -> `3-d int array reference`; - access `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; - assign `int 99` to `i` + load from `ia3` -> `3-d int array reference`; + load from `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; + store `int 99` to `i` diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 8df0202773701..0ffeb7a190c87 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -45,23 +45,23 @@ assignment: '=' expression; ---- + <1> declare `int x`; - assign default `null` to `x` + store default `null` to `x` <2> declare `List y`; - assign default `null` to `y` + store default `null` to `y` <3> declare `int x`; - assign default `int 0` to `x`; + store default `int 0` to `x`; declare `int y`; - assign `int 5` to `y`; + store `int 5` to `y`; declare `int z`; - assign default `int 0` to `z`; + store default `int 0` to `z`; <4> declare `def d`; - assign default `null` to `d` + store default `null` to `d` <5> declare `int i`; - assign `int 10` to `i` + store `int 10` to `i` <6> declare `float[] f`; - assign default `null` to `f` + store default `null` to `f` <7> declare `Map[][] m`; - assign default `null` to `m` + store default `null` to `m` [[variable-assignment]] ==== Assignment @@ -92,8 +92,8 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign default `int 0` to `i` -<2> assign `int 10` to `i` + store default `int 0` to `i` +<2> store `int 10` to `i` + * Declaration combined with immediate assignment. + @@ -104,9 +104,9 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign `int 10` to `i` + store `int 10` to `i` <2> declare `double j`; - assign `double 2.0` to `j` + store `double 2.0` to `j` + * Assignment of one variable to another using primitive types. + @@ -117,10 +117,10 @@ assignment: ID '=' expression ---- + <1> declare `int i`; - assign `int 10` to `i` + store `int 10` to `i` <2> declare `int j`; - access `i` -> `int 10`; - assign `int 10` to `j` + load from `i` -> `int 10`; + store `int 10` to `j` + * Assignment with reference types using the *new instance operator*. + @@ -132,11 +132,11 @@ assignment: ID '=' expression + <1> declare `ArrayList l`; allocate `ArrayList` instance -> `ArrayList reference`; - assign `ArrayList reference` to `l` + store `ArrayList reference` to `l` <2> declare `Map m`; allocate `HashMap` instance -> `HashMap reference`; implicit cast `HashMap reference` to `Map reference` -> `Map reference`; - assign `Map reference` to `m` + store `Map reference` to `m` + * Assignment of one variable to another using reference types. + @@ -151,15 +151,15 @@ assignment: ID '=' expression <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; - assign `List reference` to `l` + store `List reference` to `l` <2> declare `List k`; - access `l` -> `List reference`; - assign `List reference` to `k`; + load from `l` -> `List reference`; + store `List reference` to `k`; (note `l` and `k` refer to the same instance known as a shallow-copy) <3> declare `List m`; - assign default `null` to `m` -<4> access `k` -> `List reference`; - assign `List reference` to `m`; + store default `null` to `m` +<4> load from `k` -> `List reference`; + store `List reference` to `m`; (note `l`, `k`, and `m` refer to the same instance) + * Assignment with an array type variable using the *new array operator*. @@ -176,24 +176,24 @@ assignment: ID '=' expression ---- + <1> declare `int[] ia1`; - assign default `null` to `ia1` + store default `null` to `ia1` <2> allocate `1-d int array` instance with `length [2]` -> `1-d int array reference`; - assign `1-d int array reference` to `ia1` -<3> access `ia1` -> `1-d int array reference`; - assign `int 1` to `index [0]` of `1-d int array reference` + store `1-d int array reference` to `ia1` +<3> load from `ia1` -> `1-d int array reference`; + store `int 1` to `index [0]` of `1-d int array reference` <4> declare `int[] ib1`; - access `ia1` -> `1-d int array reference`; - assign `1-d int array reference` to `ib1`; + load from `ia1` -> `1-d int array reference`; + store `1-d int array reference` to `ib1`; (note `ia1` and `ib1` refer to the same instance known as a shallow copy) <5> declare `int[][] ic2`; allocate `2-d int array` instance with `length [2, 5]` -> `2-d int array reference`; - assign `2-d int array reference` to `ic2` -<6> access `ic2` -> `2-d int array reference`; - assign `int 2` to `index [1, 3]` of `2-d int array reference` -<7> access `ia1` -> `1-d int array reference`; - access `ic2` -> `2-d int array reference`; - assign `1-d int array reference` to + store `2-d int array reference` to `ic2` +<6> load from `ic2` -> `2-d int array reference`; + store `int 2` to `index [1, 3]` of `2-d int array reference` +<7> load from `ia1` -> `1-d int array reference`; + load from `ic2` -> `2-d int array reference`; + store `1-d int array reference` to `index [0]` of `2-d int array reference`; (note `ia1`, `ib1`, and `index [0]` of `ia2` refer to the same instance) From aeb879b94ea055333bfc37011c89221253f17f8b Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 24 May 2018 16:50:00 -0700 Subject: [PATCH 33/55] Cleaned up some of the general operators. --- docs/painless/painless-casting.asciidoc | 92 ++++++----- .../painless-operators-general.asciidoc | 152 +++++++++++------- .../painless-operators-reference.asciidoc | 22 ++- 3 files changed, 172 insertions(+), 94 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 52a0d6f7da2da..02419c8f20b33 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -7,7 +7,7 @@ during certain <>. An explicit cast specifies the target type and forcefully occurs as its own operation. Use the *cast operator* to specify an explicit cast. -See the <> for a quick reference on all +Refer to the <> for a quick reference on all allowed casts. *Errors* @@ -441,7 +441,7 @@ type value is derived from what the `def` type value represents at run-time. <3> float f = x + 2.0F; ---- <1> declare `double d`; - promote `int 2` and `double 2.0 @0` -> `double 2.0 @0`; + promote `int 2` and `double 2.0 @0`: result `double`; implicit cast `int 2` to `double 2.0 @1` -> `double 2.0 @1`; add `double 2.0 @1` and `double 2.0 @0` -> `double 4.0`; store `double 4.0` to `d` @@ -451,7 +451,7 @@ type value is derived from what the `def` type value represents at run-time. <3> declare `float f`; load from `x` -> `def`; implicit cast `def` to `int 1` -> `int 1`; - promote `int 1` and `float 2.0` -> `float 2.0`; + promote `int 1` and `float 2.0`: result `float`; implicit cast `int 1` to `float 1.0` -> `float `1.0`; add `float 1.0` and `float 2.0` -> `float 3.0`; store `float 3.0` to `f`; @@ -461,45 +461,61 @@ type value is derived from what the `def` type value represents at run-time. [[allowed-casts]] ==== Allowed Casts -The following table lists all allowed casts read as row (original type) to +The following tables list all allowed casts read as row (original type) to column (target type) with implicit as `I`, explicit as `E`, and not allowed as `-`: -[cols="<3,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1"] +*Primitive/Reference Types* + +[cols="<3,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1"] +|==== +| | o | b | s | c | i | j | f | d | O | B | S | C | I | L | F | D | T | R | def +| boolean ( o ) | | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | I +| byte ( b ) | - | | I | I | I | I | I | I | - | - | - | - | - | - | - | - | - | - | I +| short ( s ) | - | E | | E | I | I | I | I | - | - | - | - | - | - | - | - | - | - | I +| char ( c ) | - | E | E | | I | I | I | I | - | - | - | - | - | - | - | - | E | - | I +| int ( i ) | - | E | E | E | | I | I | I | - | - | - | - | - | - | - | - | - | - | I +| long ( j ) | - | E | E | E | E | | I | I | - | - | - | - | - | - | - | - | - | - | I +| float ( f ) | - | E | E | E | E | E | | I | - | - | - | - | - | - | - | - | - | - | I +| double ( d ) | - | E | E | E | E | E | E | | - | - | - | - | - | - | - | - | - | - | I +| Boolean ( O ) | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | I +| Byte ( B ) | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | - | I +| Short ( S ) | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | I +| Character ( C ) | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | I +| Integer ( I ) | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | I +| Long ( L ) | - | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | I +| Float ( F ) | - | - | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | I +| Double ( D ) | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | I +| String ( T ) | - | - | - | E | - | - | - | - | - | - | - | - | - | - | - | - | | - | I +| Reference ( R ) | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | @ | I +|==== + +@ See <> for allowed reference + type casts. + +*`def` Type* + +[cols="<3,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1"] |==== -| | b | s | c | i | j | f | d | B | S | C | I | L | F | D | T | R | def -| byte ( b ) | | I | I | I | I | I | I | - | - | - | - | - | - | - | - | - | I -| short ( s ) | E | | E | I | I | I | I | - | - | - | - | - | - | - | - | - | I -| char ( c ) | E | E | | I | I | I | I | - | - | - | - | - | - | - | E | - | I -| int ( i ) | E | E | E | | I | I | I | - | - | - | - | - | - | - | - | - | I -| long ( j ) | E | E | E | E | | I | I | - | - | - | - | - | - | - | - | - | I -| float ( f ) | E | E | E | E | E | | I | - | - | - | - | - | - | - | - | - | I -| double ( d ) | E | E | E | E | E | E | | - | - | - | - | - | - | - | - | - | I -| Byte ( B ) | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | - | I -| Short ( S ) | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | - | I -| Character ( C ) | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | - | I -| Integer ( I ) | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | - | I -| Long ( L ) | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | - | I -| Float ( F ) | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | - | I -| Double ( D ) | - | - | - | - | - | - | - | - | - | - | - | - | - | | - | - | I -| String ( T ) | - | - | E | - | - | - | - | - | - | - | - | - | - | - | | - | I -| Reference ( R ) | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | @ | I -| def as byte | I | I | I | I | I | I | I | I | I | I | I | I | I | I | - | - | -| def as short | E | I | E | I | I | I | I | E | I | E | I | I | I | I | - | - | -| def as char | E | E | I | I | I | I | I | E | E | I | I | I | I | I | E | - | -| def as int | E | E | E | I | I | I | I | E | E | E | I | I | I | I | - | - | -| def as long | E | E | E | E | I | I | I | E | E | E | E | I | I | I | - | - | -| def as float | E | E | E | E | E | I | I | E | E | E | E | E | I | I | - | - | -| def as double | E | E | E | E | E | E | I | E | E | E | E | E | E | I | - | - | -| def as Byte | I | I | I | I | I | I | I | I | I | I | I | I | I | I | - | - | -| def as Short | E | I | E | I | I | I | I | E | I | E | I | I | I | I | - | - | -| def as Character | E | E | I | I | I | I | I | E | E | I | I | I | I | I | - | - | -| def as Integer | E | E | E | I | I | I | I | E | E | E | I | I | I | I | - | - | -| def as Long | E | E | E | E | I | I | I | E | E | E | E | I | I | I | - | - | -| def as Float | E | E | E | E | E | I | I | E | E | E | E | E | I | I | - | - | -| def as Double | E | E | E | E | E | E | I | E | E | E | E | E | E | I | - | - | -| def as String | - | - | E | - | - | - | - | - | - | - | - | - | - | - | I | - | -| def as Reference | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | @ | +| | o | b | s | c | i | j | f | d | O | B | S | C | I | L | F | D | T | R | def +| def as boolean | I | - | - | - | - | - | - | - | I | - | - | - | - | - | - | - | - | - | +| def as byte | - | I | I | I | I | I | I | I | - | I | I | I | I | I | I | I | - | - | +| def as short | - | E | I | E | I | I | I | I | - | E | I | E | I | I | I | I | - | - | +| def as char | - | E | E | I | I | I | I | I | - | E | E | I | I | I | I | I | E | - | +| def as int | - | E | E | E | I | I | I | I | - | E | E | E | I | I | I | I | - | - | +| def as long | - | E | E | E | E | I | I | I | - | E | E | E | E | I | I | I | - | - | +| def as float | - | E | E | E | E | E | I | I | - | E | E | E | E | E | I | I | - | - | +| def as double | - | E | E | E | E | E | E | I | - | E | E | E | E | E | E | I | - | - | +| def as Boolean | I | - | - | - | - | - | - | - | I | - | - | - | | - | - | - | - | - | +| def as Byte | - | I | I | I | I | I | I | I | - | I | I | I | I | I | I | I | - | - | +| def as Short | - | E | I | E | I | I | I | I | - | E | I | E | I | I | I | I | - | - | +| def as Character | - | E | E | I | I | I | I | I | - | E | E | I | I | I | I | I | - | - | +| def as Integer | - | E | E | E | I | I | I | I | - | E | E | E | I | I | I | I | - | - | +| def as Long | - | E | E | E | E | I | I | I | - | E | E | E | E | I | I | I | - | - | +| def as Float | - | E | E | E | E | E | I | I | - | E | E | E | E | E | I | I | - | - | +| def as Double | - | E | E | E | E | E | E | I | - | E | E | E | E | E | E | I | - | - | +| def as String | - | - | - | E | - | - | - | - | - | - | - | - | - | - | - | - | I | - | +| def as Reference | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | @ | |==== @ See <> for allowed reference diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 69162a86bb54f..6946d7acd2960 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -4,8 +4,10 @@ [[precedence]] ==== Precedence -Use the *precedence operator* to guarantee the order of evaluation for an -expression and override existing precedence relationships between operators. +An expression encapsulated within a *precedence operator* overrides +existing precedence relationships between operators and is evaluated +prior to other expressions in inward-to-outward order. Use the *precedence +operator* to guarantee the order of evaluation for an expression. *Grammar* [source,ANTLR4] @@ -15,7 +17,7 @@ precedence: '(' expression ')'; *Examples* -* Use of the precedence operator. +* Uses of the *precedence operator*. + [source,Painless] ---- @@ -26,87 +28,127 @@ precedence: '(' expression ')'; <1> declare `int x`; add `int 5` and `int 4` -> `int 9`; multiply `int 9` and `int 6` -> `int 54`; - assign `int 54` to `x`; + store `int 54` to `x`; (note the add is evaluated before the multiply due to the *precedence operator*) <2> declare `int y`; - load `x` - + load from `x` -> `int 54`; + subtract `int 50` from `int 54` -> `int 4`; + divide `int 12` by `int 4` -> `int 3`; + store `int 3` to `y`; + (note the subtract is evaluated before the divide due to the *precedence + operator*) [[function-call]] ==== Function Call -User-defined function calls can be made in Painless using the parenthesis -operator. See Function Calls [MARK] for more information. +A function call is defined within a script. Use the *function call operator* to +call an existing function. + +*Grammar* +[source,ANTLR4] +---- +function_call: ID '(' ( expression (',' expression)* )? ')''; +---- + +*Examples* + +* Use of the *function call operator*. ++ +[source,Painless] +---- +<1> int add(int x, int y) { + return x + y; + } + +<2> int z = add(1, 2); +---- ++ +<1> define function `add` that returns `int` and has parameters (`int x`, + `int y`) +<2> declare `int z`; + call `add` with arguments (`int 1`, `int 2`) -> `int 3`; + store `int 3` to `z` [[cast]] ==== Cast -The cast operator can be used to explicitly convert one type to another. See casting [MARK] for more information. +An explicit cast converts the value of an original type to the equivalent value +of a target type forcefully as an operation. Use the *cast operator* to specify +an explicit cast. Refer to <> for more information. [[conditional]] ==== 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. +A conditional 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. The second and third +expressions will be <> if the evaluated values are not the +same type. Use the *conditional operator* as a shortcut to avoid the need for a +full if/else branch in certain expressions. -*Grammar:* +*Errors* + +* If the first expression does not evaluate to a boolean type value. +* If the values for the second and third expressions cannot be promoted. + +*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* -Promotion Table: +[cols="<1,^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 +| | byte | short | char | int | long | float | double | Reference | 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 +| Reference | - | - | - | - | - | - | - | Object @ | def +| 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 +@ If the two reference type values are the same then this promotion will not +occur. -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]] -==== 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* -*Examples:* -[source,Java] +* Uses of the *conditional operator*. ++ +[source,Painless] ---- -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 +<1> boolean b = true; +<2> int x = b ? 1 : 2; +<3> List y = x > 1 ? new ArrayList() : null; +<4> def z = x < 2 ? x : 2.0; ---- ++ +<1> declare `boolean b`; + store `boolean true` to `b` +<2> declare `int x`; + load from `b` -> `boolean true` + evaluate 1st expression: `int 1` -> `int 1`; + store `int 1` to `x` +<3> declare `List y`; + load from `x` -> `int 1`; + `int 1` greater than `int 1` -> `boolean false`; + evaluate 2nd expression: `null` -> `null`; + store `null` to `y`; +<4> declare `def z`; + load from `x` -> `int 1`; + `int 1` less than `int 2` -> `boolean true`; + evaluate 1st expression: load from `x` -> `int 1`; + promote `int 1` and `double 2.0`: result `double`; + implicit cast `int 1` to `double 1.0` -> `double 1.0`; + implicit cast `double 1.0` to `def` -> `def`; + store `def` to `z`; [[assignment]] ==== Assignment diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 29216955a029e..b745690bfb6ac 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -318,4 +318,24 @@ String z = 4 + x; // declares the String variable z and sets it to the 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" ----- \ No newline at end of file +---- + +[[elvis]] +==== 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 +---- From b1d31d14c475dcda394471191b0159deb42fd90b Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 31 May 2018 14:03:11 -0700 Subject: [PATCH 34/55] Clean up of general operators. --- docs/painless/painless-identifiers.asciidoc | 2 +- docs/painless/painless-literals.asciidoc | 8 +- .../painless-operators-array.asciidoc | 8 +- .../painless-operators-boolean.asciidoc | 26 +- .../painless-operators-general.asciidoc | 282 +++++++++++++++--- .../painless-operators-numeric.asciidoc | 36 +-- .../painless-operators-reference.asciidoc | 20 +- docs/painless/painless-operators.asciidoc | 103 ++++--- docs/painless/painless-types.asciidoc | 65 ++-- docs/painless/painless-variables.asciidoc | 11 +- 10 files changed, 384 insertions(+), 177 deletions(-) diff --git a/docs/painless/painless-identifiers.asciidoc b/docs/painless/painless-identifiers.asciidoc index 7364e3a68ac99..779b405c1af6b 100644 --- a/docs/painless/painless-identifiers.asciidoc +++ b/docs/painless/painless-identifiers.asciidoc @@ -3,7 +3,7 @@ Use an identifier as a named token to specify a <>, <>, -<>, <>, or function. +<>, <>, or function. <> cannot be used as identifiers. *Grammar* diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index ebf7eaa07b657..f41e5fdd79ceb 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -4,7 +4,7 @@ Use a literal to specify a value directly in an <>. -[[integers]] +[[integer-literals]] ==== Integers Use an integer literal to specify an integer type value in decimal, octal, or @@ -44,7 +44,7 @@ HEX: '-'? '0' [xX] [0-9a-fA-F]+ [lL]?; <5> `int -18` in octal <6> `int 3882` in hex -[[floats]] +[[float-literals]] ==== Floats Use a floating point literal to specify a floating point type value of a @@ -78,7 +78,7 @@ EXPONENT: ( [eE] [+\-]? [0-9]+ ); <4> `double -126.34` <5> `float 89.9` -[[strings]] +[[string-literals]] ==== Strings Use a string literal to specify a <> value with @@ -114,7 +114,7 @@ STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) "double-quoted with non-escaped 'single-quotes'" ---- -[[characters]] +[[character-literals]] ==== Characters A character literal cannot be specified directly. Instead, use the diff --git a/docs/painless/painless-operators-array.asciidoc b/docs/painless/painless-operators-array.asciidoc index 2283a9e49fb0d..5f2e3d535046f 100644 --- a/docs/painless/painless-operators-array.asciidoc +++ b/docs/painless/painless-operators-array.asciidoc @@ -1,7 +1,7 @@ [[painless-operators-array]] === Operators: Array -[[array-initialization]] +[[array-initialization-operator]] ==== Array Initialization You create and initialize arrays using the brackets `[]` and braces `{}` @@ -52,7 +52,7 @@ def[] da = new def[] {i, l, f*d, s}; // Declare def array da and set it to // values i, l, f*d, and s ---- -[[array-access]] +[[array-access-operator]] ==== Array Access Elements in an array are stored and accessed using the brackets `[]` operator. @@ -100,7 +100,7 @@ return d[z]; // Access the 1st element of array d using the NOTE: The use of the `def` type in the second example means that the types cannot be resolved until runtime. -[[array-length]] +[[array-length-operator]] ==== 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. @@ -112,7 +112,7 @@ int[] x = new int[10]; // declares an int array variable x and sets it to a newl int l = x.length; // declares and int variable l and sets it to the field length of variable x ---- -[[new-array]] +[[new-array-operator]] ==== 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. diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc index 298577759b01b..7a2e17ef294d4 100644 --- a/docs/painless/painless-operators-boolean.asciidoc +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -1,7 +1,7 @@ [[painless-operators-boolean]] === Operators: Boolean -[[boolean-not]] +[[boolean-not-operator]] ==== 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. @@ -22,7 +22,7 @@ boolean y = !x; // declares the boolean variable y and sets it to the opposi def z = !y; // declares the def variable z and sets it to the opposite of the boolean variable y ---- -[[greater-than]] +[[greater-than-operator]] ==== 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. @@ -57,7 +57,7 @@ def z = y > 6.5; // declares the def variable z and sets it to the result of y 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-operator]] ==== 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. @@ -92,7 +92,7 @@ def z = y >= 6.5; // declares the def variable z and sets it to the result of 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-operator]] ==== 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. @@ -127,7 +127,7 @@ def z = y < 6.5; // declares the def variable z and sets it to the result of y 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-operator]] ==== 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. @@ -162,7 +162,7 @@ def z = y <= 6.5; // declares the def variable z and sets it to the result of 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]] +[[instance-of-operator]] ==== 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. @@ -184,7 +184,7 @@ boolean b = y instanceof Map; // declares the boolean variable b and sets it 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-operator]] ==== 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. @@ -245,7 +245,7 @@ result = null == dl; // compares null to dl with a boolean result of result = l1 == null; // compares l1 to null with a boolean result of false ---- -[[equality-not-equals]] +[[equality-not-equals-operator]] ==== 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. @@ -306,7 +306,7 @@ result = null != dl; // compares null to dl with a boolean result of result = l1 != null; // compares null to l1 with a boolean result of true ---- -[[identity-equals]] +[[identity-equals-operator]] ==== 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. @@ -368,7 +368,7 @@ result = null === dl; // compares null to dl with a boolean result of result = l1 === null; // compares null to l1 with a boolean result of false ---- -[[identity-not-equals]] +[[identity-not-equals-operator]] ==== 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. @@ -430,7 +430,7 @@ result = null !== dl; // compares null to dl with a boolean result of result = l1 !== null; // compares null to l1 with a boolean result of true ---- -[[boolean-xor]] +[[boolean-xor-operator]] ==== 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. @@ -459,7 +459,7 @@ boolean y = x ^ true; // declares the boolean variable y and sets it the result def z = y ^ x; // declares the def variable z and sets it to the result of y xor x ---- -[[boolean-and]] +[[boolean-and-operator]] ==== 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. @@ -486,7 +486,7 @@ boolean y = x && true; // declares the boolean variable y and sets it the result def z = y && x; // declares the def variable z and sets it to the result of y and x ---- -[[boolean-or]] +[[boolean-or-operator]] ==== 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. diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 6946d7acd2960..807a0d0ec0501 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -1,7 +1,7 @@ [[painless-operators-general]] === Operators: General -[[precedence]] +[[precedence-operator]] ==== Precedence An expression encapsulated within a *precedence operator* overrides @@ -39,7 +39,7 @@ precedence: '(' expression ')'; (note the subtract is evaluated before the divide due to the *precedence operator*) -[[function-call]] +[[function-call-operator]] ==== Function Call A function call is defined within a script. Use the *function call operator* to @@ -70,14 +70,14 @@ function_call: ID '(' ( expression (',' expression)* )? ')''; call `add` with arguments (`int 1`, `int 2`) -> `int 3`; store `int 3` to `z` -[[cast]] +[[cast-operator]] ==== Cast An explicit cast converts the value of an original type to the equivalent value of a target type forcefully as an operation. Use the *cast operator* to specify an explicit cast. Refer to <> for more information. -[[conditional]] +[[conditional-operator]] ==== Conditional A conditional consists of three expressions. The first expression is evaluated @@ -150,37 +150,112 @@ occur. implicit cast `double 1.0` to `def` -> `def`; store `def` to `z`; -[[assignment]] +[[assignment-operator]] ==== Assignment -Assignment can be used to assign a value to a variable. See Variable Assignment [MARK] for more information. +Use the *assignment operator* to store a value in a variable or reference type +member field for use in subsequent operations. Any operation +that produces a value can be assigned to any variable/field as long as the +<> are the same or the resultant type can be +<> to the variable/field type. -[[compound-assignment]] -==== Compound Assignment +See <> for examples using variables. + +*Errors* -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. +* If the type of value is unable to match the type of variable or field. -*Grammar:* +*Grammar* [source,ANTLR4] ---- -compund_assignment: ID (. ID)? '$=' expression; // $ is a placeholder for the operation symbol +assignment: field '=' expression +---- + +*Examples* + +The examples use the following reference type definition: + +---- +name: + Example + +non-static member fields: + * int x + * def y + * List z +---- + +* Uses of field assignment. ++ +[source,Painless] +---- +<1> Example example = new Example(); +<2> example.x = 1; +<3> example.y = 2.0; +<4> example.z = new ArrayList(); +---- ++ +<1> declare `Example example`; + allocate `Example` instance -> `Example reference`; + store `Example reference` to `example` +<2> load from `example` -> `Example reference`; + store `int 1` to `x` of `Example reference` +<3> load from `example` -> `Example reference`; + implicit cast `double 2.0` to `def` -> `def`; + store `def` to `y` of `Example reference` +<4> load from `example` -> `Example reference`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `z` of `Example reference` ++ +* Use of field assignment from a field access. ++ +[source,Painless] +---- +<1> Example example = new Example(); +<2> example.x = 1; +<3> example.y = example.x; ---- ++ +<1> declare `Example example`; + allocate `Example` instance -> `Example reference`; + store `Example reference` to `example` +<2> load from `example` -> `Example reference`; + store `int 1` to `x` of `Example reference` +<3> load from `example` -> `Example reference @0` + load from `example` -> `Example reference @1` + load from `x` of `Example reference @1` -> `int 1` + implicit cast `int 1` to `def` -> `def` + store `def` to `y` of `Example reference @0`; + (note `Example reference @0` and `Example reference @1` are the same) + +[[compound-assignment-operator]] +==== Compound Assignment -A compound assignment is equivalent to the expression below where V is the variable/field and T is the type of variable/member. +Use the *compound assignment operator* 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. + +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. +*Operators* + +The table below shows the available operators for use in a compound assignment. +Each operator follows the casting/promotion rules according to their regular +definition. For numeric operations their will be an extra implicit cast when +necessary to return the promoted numeric type value to the original numeric type +value of the variable/field and can result in data loss. |==== |Operator|Compound Symbol |Multiplication|*= |Division|/= |Remainder|%= -|String Concatenation|+= |Addition|+= |Subtraction|-= |Left Shift|<<= @@ -192,29 +267,158 @@ The table below shows all available operators for compound assignment. All oper |Boolean Xor|^= |Bitwise Or|\|= |Boolean Or|\|= +|String Concatenation|+= |==== -*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') ----- \ No newline at end of file +*Errors* + +* If the type of value is unable to match the type of variable or field. + +*Grammar* +[source,ANTLR4] +---- +compound_assignment: ( ID | field ) '$=' expression; +---- + +Note the use of the `$=` represents the use of any of the possible binary +operators. + +*Examples* + +* Uses of compound assignment for each numeric operator. ++ +[source,Painless] +---- +<1> int i = 10; +<2> i *= 2; +<3> i /= 5; +<4> i %= 3; +<5> i += 5; +<6> i -= 5; +<7> i <<= 2; +<8> i >>= 1; +<9> i >>>= 1; +<10> i &= 15; +<11> i ^= 12; +<12> i |= 2; +---- ++ +<1> declare `int i`; + store `int 10` to `i` +<2> load `i` -> `int 10`; + multiply `int 10` and `int 2` -> `int 20`; + store `int 20` to `i`; + (note this is equivalent to `i = i*2`) +<3> load `i` -> `int 20`; + divide `int 20` by `int 5` -> `int 4`; + store `int 4` to `i`; + (note this is equivalent to `i = i/5`) +<4> load `i` -> `int 4`; + remainder `int 4` by `int 3` -> `int 1`; + store `int 1` to `i`; + (note this is equivalent to `i = i%3`) +<5> load `i` -> `int 1`; + add `int 1` and `int 5` -> `int 6`; + store `int 6` to `i`; + (note this is equivalent to `i = i+5`) +<6> load `i` -> `int 6`; + subtract `int 5` from `int 6` -> `int 1`; + store `int 1` to `i`; + (note this is equivalent to `i = i-5`) +<7> load `i` -> `int 1`; + left shift `int 1` by `int 2` -> `int 4`; + store `int 4` to `i`; + (note this is equivalent to `i = i<<2`) +<8> load `i` -> `int 4`; + right shift `int 4` by `int 1` -> `int 2`; + store `int 2` to `i`; + (note this is equivalent to `i = i>>1`) +<9> load `i` -> `int 2`; + unsigned right shift `int 2` by `int 1` -> `int 1`; + store `int 1` to `i`; + (note this is equivalent to `i = i>>>1`) +<10> load `i` -> `int 1`; + bitwise and `int 1` and `int 15` -> `int 1`; + store `int 1` to `i`; + (note this is equivalent to `i = i&2`) +<11> load `i` -> `int 1`; + bitwise xor `int 1` and `int 12` -> `int 13`; + store `int 13` to `i`; + (note this is equivalent to `i = i^2`) +<12> load `i` -> `int 13`; + bitwise or `int 13` and `int 2` -> `int 15`; + store `int 15` to `i`; + (note this is equivalent to `i = i|2`) ++ +* Uses of compound assignment for each boolean operator. ++ +[source,Painless] +---- +<1> boolean b = true; +<2> b &= false; +<3> b ^= false; +<4> b |= true; +---- ++ +<1> declare `boolean b`; + store `boolean true` in `b`; +<2> load `b` -> `boolean true`; + boolean and `boolean true` and `boolean false` -> `boolean false`; + store `boolean false` to `b`; + (note this is equivalent to `b = b && false`) +<3> load `b` -> `boolean false`; + boolean xor `boolean false` and `boolean false` -> `boolean false`; + store `boolean false` to `b`; + (note this is equivalent to `b = b ^ false`) +<4> load `b` -> `boolean true`; + boolean or `boolean false` and `boolean true` -> `boolean true`; + store `boolean true` to `b`; + (note this is equivalent to `b = b || true`) ++ +* Use of compound assignment with the *string concatenation operator*. ++ +[source,Painless] +---- +<1> String s = 'compound'; +<2> s += ' assignment'; +---- +<1> declare `String s`; + store `String 'compound'` to `s`; +<2> load `s` -> `String 'compound'`; + string concat `String 'compound'` and `String ' assignment''` + -> `String 'compound assignment'`; + store `String 'compound assignment'` to `s`; + (note this is equivalent to `s = s + ' assignment'`) ++ +* Use of a compound assignment with the `def` type. ++ +[source,Painless] +---- +<1> def x = 1; +<2> x += 2; +---- +<1> declare `def x`; + implicit cast `int 1` to `def`; + store `def` to `x`; +<2> load `x` -> `def`; + implicit cast `def` to `int 1` -> `int 1`; + add `int 1` and `int 2` -> `int 3`; + implicit cast `int 3` to `def` -> `def`; + store `def` to `x`; + (note this is equivalent to `x = x+2`) ++ +* Use of a compound assignment with an extra implicit cast. ++ +[source,Painless] +---- +<1> byte b = 1; +<2> b += 2; +---- +<1> declare `byte b`; + store `byte 1` to `x`; +<2> load `x` -> `byte 1`; + implicit cast `byte 1 to `int 1` -> `int 1`; + add `int 1` and `int 2` -> `int 3`; + implicit cast `int 3` to `byte 3` -> `byte 3`; + store `byte 3` to `b`; + (note this is equivalent to `b = b+2`) \ No newline at end of file diff --git a/docs/painless/painless-operators-numeric.asciidoc b/docs/painless/painless-operators-numeric.asciidoc index d4ae04e947374..d3f3af34e77c5 100644 --- a/docs/painless/painless-operators-numeric.asciidoc +++ b/docs/painless/painless-operators-numeric.asciidoc @@ -1,7 +1,7 @@ [[painless-operators-numeric]] === Operators: Numeric -[[post-increment]] +[[post-increment-operator]] ==== 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. @@ -38,7 +38,7 @@ 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]] +[[post-decrement-operator]] ==== 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. @@ -75,7 +75,7 @@ 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]] +[[pre-increment-operator]] ==== 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. @@ -112,7 +112,7 @@ 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]] +[[pre-decrement-operator]] ==== 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. @@ -148,7 +148,7 @@ 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-operator]] ==== 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. @@ -183,7 +183,7 @@ 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-operator]] ==== Unary Negative Unary negative negates a numeric value using the minus operator. Format starts with a minus followed by a numerical expression. @@ -218,7 +218,7 @@ 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 ---- -[[bitwise-not]] +[[bitwise-not-operator]] ==== Bitwise Not Bitwise not will flip each bit of an integer type expression. The format is the tilde operator followed by an expression. @@ -253,7 +253,7 @@ def e; // declares the def variable e e = ~d; // sets e the negation of d ---- -[[multiplication]] +[[multiplication-operator]] ==== 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. @@ -288,7 +288,7 @@ def z = x*y; // declares the def variable z and sets it to the result of x 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]] +[[division-operator]] ==== 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. @@ -323,7 +323,7 @@ def z = x/y; // declares the def variable z and sets it to the result of x 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]] +[[remainder-operator]] ==== 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. @@ -358,7 +358,7 @@ def z = x%y; // declares the def variable z and sets it to the remainder of 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) ---- -[[addition]] +[[addition-operator]] ==== 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. @@ -393,7 +393,7 @@ def z = x + y; // declares the def variable z and sets it to the result of 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]] +[[subtraction-operator]] ==== 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. @@ -428,7 +428,7 @@ def z = x-y; // declares the def variable z and sets it to the result of y 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]] +[[left-shift-operator]] ==== 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. @@ -463,7 +463,7 @@ def z = x << y; // declares the def variable z and sets it to the result of x l def a = z << x; // declares the def variable a and sets it to the result of z left shifted by x ---- -[[right-shift]] +[[right-shift-operator]] ==== 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. @@ -498,7 +498,7 @@ def z = x >> y; // declares the def variable z and sets it to the result of x r def a = z >> x; // declares the def variable a and sets it to the result of z right shifted by x ---- -[[unsigned-right-shift]] +[[unsigned-right-shift-operator]] ==== 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. @@ -533,7 +533,7 @@ def z = x >> y; // declares the def variable z and sets it to the result of x u def a = z >> x; // declares the def variable a and sets it to the result of z unsigned right shifted by x ---- -[[bitwise-and]] +[[bitwise-and-operator]] ==== 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. @@ -576,7 +576,7 @@ def e; // declares the def variable e e = d & z; // sets e to the result of d and z ---- -[[bitwise-xor]] +[[bitwise-xor-operator]] ==== 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. @@ -619,7 +619,7 @@ def e; // declares the def variable e e = d ^ z; // sets e to the result of d xor z ---- -[[bitwise-or]] +[[bitwise-or-operator]] ==== 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. diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index b745690bfb6ac..6c5563685846f 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -1,7 +1,7 @@ [[painless-operators-reference]] === Operators: Reference -[[method-call]] +[[method-call-operator]] ==== Method Call You call reference type methods using the dot operator and the method id: @@ -76,7 +76,7 @@ casts between primitive types and reference types, see <>. ************************** -[[field-access]] +[[field-access-operator]] ==== Field Access 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 @@ -104,7 +104,7 @@ int value = ft.x + ft.y; // Declare variable value as an int, // assign the sum to the variable value ---- -[[null-safe]] +[[null-safe-operator]] ==== Null Safe The null safe operator `?.` can be used in place of the dot operator @@ -145,7 +145,7 @@ 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 ---- -[[list-initialization]] +[[list-initialization-operator]] ==== List Initialization You create and initialize lists using the brackets `[]` operator. The values @@ -176,7 +176,7 @@ 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 ---- -[[list-access]] +[[list-access-operator]] ==== List Access 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. @@ -213,7 +213,7 @@ return d[z]; // accesses the 1st element of the variable d using the 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. -[[map-initialization]] +[[map-initialization-operator]] ==== Map Initialization 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. @@ -244,7 +244,7 @@ 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 ---- -[[map-access]] +[[map-access-operator]] ==== Map Access 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. @@ -275,7 +275,7 @@ return d[z]; // accesses the value for the key value5 of t 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. -[[new-instance]] +[[new-instance-operator]] ==== New Instance 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. @@ -298,7 +298,7 @@ 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 ---- -[[string-concatenation]] +[[string-concatenation-operator]] ==== 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. @@ -320,7 +320,7 @@ z = z + d; // sets the String variable z to the concatenation of d = "con" + x + y + "cat"; // sets the def variable d to the concatenation of String constant "con", x, y, and the String constant "cat" ---- -[[elvis]] +[[elvis-operator]] ==== 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. diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index b257b2d95cb85..bafa3886616f0 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -1,7 +1,6 @@ [[painless-operators]] === Operators -<<<<<<< HEAD An operator is the most basic action that can be taken to evaluate values in a script. An expression is one-to-many consecutive operations. Precedence is the order in which an operator will be evaluated relative to another operator. @@ -11,55 +10,55 @@ is evaluated. The following table lists all available operators: [cols="<6,<3,^3,^2,^4"] |==== | *Operator* | *Category* | *Symbol(s)* | *Precedence* | *Associativity* -| <> | <> | () | 0 | left -> right -| <> | <> | . () | 1 | left -> right -| <> | <> | . | 1 | left -> right -| <> | <> | ?. | 1 | left -> right -| <> | <> | () | 1 | left -> right -| <> | <> | [] {} | 1 | left -> right -| <> | <> | [] | 1 | left -> right -| <> | <> | . | 1 | left -> right -| <> | <> | [] | 1 | left -> right -| <> | <> | [] | 1 | left -> right -| <> | <> | [:] | 1 | left -> right -| <> | <> | [] | 1 | left -> right -| <> | <> | ++ | 1 | left -> right -| <> | <> | -- | 1 | left -> right -| <> | <> | ++ | 2 | right -> left -| <> | <> | -- | 2 | right -> left -| <> | <> | + | 2 | right -> left -| <> | <> | - | 2 | right -> left -| <> | <> | ! | 2 | right -> left -| <> | <> | ~ | 2 | right -> left -| <> | <> | () | 3 | right -> left -| <> | <> | new () | 3 | right -> left -| <> | <> | new | 3 | right -> left -| <> | <> | * | 4 | left -> right -| <> | <> | / | 4 | left -> right -| <> | <> | % | 4 | left -> right -| <> | <> | + | 5 | left -> right -| <> | <> | + | 5 | left -> right -| <> | <> | - | 5 | left -> right -| <> | <> | << | 6 | left -> right -| <> | <> | >> | 6 | left -> right -| <> | <> | >>> | 6 | left -> right -| <> | <> | > | 7 | left -> right -| <> | <> | >= | 7 | left -> right -| <> | <> | < | 7 | left -> right -| <> | <> | <= | 7 | left -> right -| <> | <> | instanceof | 8 | left -> right -| <> | <> | == | 9 | left -> right -| <> | <> | != | 9 | left -> right -| <> | <> | === | 9 | left -> right -| <> | <> | !== | 9 | left -> right -| <> | <> | & | 10 | left -> right -| <> | <> | ^ | 11 | left -> right -| <> | <> | ^ | 11 | left -> right -| <> | <> | \| | 12 | left -> right -| <> | <> | && | 13 | left -> right -| <> | <> | \|\| | 14 | left -> right -| <> | <> | ? : | 15 | right -> left -| <> | <> | ?: | 16 | right -> left -| <> | <> | = | 17 | right -> left -| <> | <> | $= | 17 | right -> left +| <> | <> | () | 0 | left -> right +| <> | <> | . () | 1 | left -> right +| <> | <> | . | 1 | left -> right +| <> | <> | ?. | 1 | left -> right +| <> | <> | () | 1 | left -> right +| <> | <> | [] {} | 1 | left -> right +| <> | <> | [] | 1 | left -> right +| <> | <> | . | 1 | left -> right +| <> | <> | [] | 1 | left -> right +| <> | <> | [] | 1 | left -> right +| <> | <> | [:] | 1 | left -> right +| <> | <> | [] | 1 | left -> right +| <> | <> | ++ | 1 | left -> right +| <> | <> | -- | 1 | left -> right +| <> | <> | ++ | 2 | right -> left +| <> | <> | -- | 2 | right -> left +| <> | <> | + | 2 | right -> left +| <> | <> | - | 2 | right -> left +| <> | <> | ! | 2 | right -> left +| <> | <> | ~ | 2 | right -> left +| <> | <> | () | 3 | right -> left +| <> | <> | new () | 3 | right -> left +| <> | <> | new | 3 | right -> left +| <> | <> | * | 4 | left -> right +| <> | <> | / | 4 | left -> right +| <> | <> | % | 4 | left -> right +| <> | <> | + | 5 | left -> right +| <> | <> | + | 5 | left -> right +| <> | <> | - | 5 | left -> right +| <> | <> | << | 6 | left -> right +| <> | <> | >> | 6 | left -> right +| <> | <> | >>> | 6 | left -> right +| <> | <> | > | 7 | left -> right +| <> | <> | >= | 7 | left -> right +| <> | <> | < | 7 | left -> right +| <> | <> | <= | 7 | left -> right +| <> | <> | instanceof | 8 | left -> right +| <> | <> | == | 9 | left -> right +| <> | <> | != | 9 | left -> right +| <> | <> | === | 9 | left -> right +| <> | <> | !== | 9 | left -> right +| <> | <> | & | 10 | left -> right +| <> | <> | ^ | 11 | left -> right +| <> | <> | ^ | 11 | left -> right +| <> | <> | \| | 12 | left -> right +| <> | <> | && | 13 | left -> right +| <> | <> | \|\| | 14 | left -> right +| <> | <> | ? : | 15 | right -> left +| <> | <> | ?: | 16 | right -> left +| <> | <> | = | 17 | right -> left +| <> | <> | $= | 17 | right -> left |==== diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index 0580a2a3c86ec..ec09e751ef725 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -19,9 +19,9 @@ variable is listed as part of the definitions below. A primitive type value is copied during an assignment or as an argument for a method/function call. A primitive type has a corresponding reference type (also known as a boxed -type). Use the <> or -<> on a primitive type value to force -evaluation as its corresponding reference type value. +type). Use the <> or +<> on a primitive type value to +force evaluation as its corresponding reference type value. The following primitive types are available: @@ -112,9 +112,10 @@ multiple pieces of data (member fields) and logic to manipulate that data (API) for scripts. A reference type instance is a single set of data for one reference type -object allocated to the heap. Use the <> to -allocate a reference type instance. Use a reference type instance to load from, -store to, and manipulate complex data. +object allocated to the heap. Use the +<> to allocate a reference type +instance. Use a reference type instance to load from, store to, and manipulate +complex data. A reference type value refers to a reference type instance, and multiple reference type values may refer to the same reference type instance. A change to @@ -138,8 +139,8 @@ static member field:: A static member field is a named and typed piece of data. Each reference type *object* contains one set of data representative of its static member fields. -Use the <> in correspondence with the -reference type object name to access a static member field for loading and +Use the <> in correspondence with +the reference type object name to access a static member field for loading and storing to a specific reference type *object*. No reference type instance allocation is necessary to use a static member field. @@ -148,31 +149,32 @@ non-static member field:: A non-static member field is a named and typed piece of data. Each reference type *instance* contains one set of data representative of its reference type object's non-static member fields. Use the -<> for loading and storing to a non-static -member field of a specific reference type *instance*. An allocated reference -type instance is required to use a non-static member field. +<> for loading and storing to a +non-static member field of a specific reference type *instance*. An allocated +reference type instance is required to use a non-static member field. static member method:: A static member method is a function called on a reference type *object*. Use -the <> in correspondence with the reference -type object name to call a static member method. No reference type instance -allocation is necessary to use a static member method. +the <> in correspondence with the +reference type object name to call a static member method. No reference type +instance allocation is necessary to use a static member method. non-static member method:: A non-static member method is a function called on a reference type *instance*. A non-static member method called on a reference type instance can load from and store to non-static member fields of that specific reference type instance. Use -the <> in correspondence with a specific -reference type instance to call a non-static member method. An allocated -reference type instance is required to use a non-static member method. +the <> in correspondence with a +specific reference type instance to call a non-static member method. An +allocated reference type instance is required to use a non-static member method. constructor:: A constructor is a special type of function used to allocate a reference type *instance* defined by a specific reference type *object*. Use the -<> to allocate a reference type instance. +<> to allocate a reference type +instance. A reference type object follows a basic inheritance model. Consider types A and B. Type A is considered to be a parent of B, and B a child of A, if B inherits @@ -333,9 +335,10 @@ types and reference types directly when performance is critical. ==== String Type The `String` type is a specialized reference type that does not require -explicit allocation. Use a <> to directly evaluate a -`String` type value. While not required, the -<> can allocate `String` type instances. +explicit allocation. Use a <> to directly +evaluate a `String` type value. While not required, the +<> can allocate `String` type +instances. *Examples* @@ -386,12 +389,12 @@ type instance are of the same type. Each value is assigned an index from within the range `[0, length)` where length is the total number of values allocated for the array type instance. -Use the <> or the -<> to allocate an array -type instance. Declare an array type <> or access -an array type member field (from a reference type instance), and assign it an -array type value for evaluation during later operations. The default value for a -newly-declared array type variable is `null`. An array type value is +Use the <> or the +<> to allocate an +array type instance. Declare an array type <> or +access an array type member field (from a reference type instance), and assign +it an array type value for evaluation during later operations. The default value +for a newly-declared array type variable is `null`. An array type value is shallow-copied during an assignment or as an argument for a method/function call. Assign `null` to an array type variable to indicate the array type value refers to no array type instance. The JVM will garbage collect an array type @@ -399,10 +402,10 @@ instance when it is no longer referred to by any array type values. Pass `null` as an argument to a method/function call to indicate the argument refers to no array type instance. -Use the <> to retrieve the length of an -array type value as an int type value. Use the -<> to load from and store to individual -values within an array type value. +Use the <> to retrieve the length +of an array type value as an int type value. Use the +<> to load from and store to +individual values within an array type value. When an array type instance is allocated with multiple dimensions using the range `[2, d]` where `d >= 2`, each dimension in the range `[1, d-1]` is also diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 0ffeb7a190c87..89e267aedc2b3 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -4,7 +4,7 @@ A variable loads and stores a value for evaluation during <>. -[[declaration]] +[[variable-declaration]] ==== Declaration Declare a variable before use with the format of <> @@ -66,10 +66,11 @@ assignment: '=' expression; [[variable-assignment]] ==== Assignment -Use the *assignment operator* to store a value in a variable. Any operation -that produces a value can be assigned to any variable as long as the -<> are the same or the resultant type can be -<> to the variable type. +Use the *assignment operator* to store a value in a variable for use in +subsequent operations. Any operation that produces a value can be assigned to +any variable as long as the <> are the same or the +resultant type can be <> to the variable +type. *Errors* From 246c824a872507db53796378d1c044d0d8dad51c Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 31 May 2018 14:12:42 -0700 Subject: [PATCH 35/55] Fix examples with load from instead of load. --- .../painless-operators-general.asciidoc | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 807a0d0ec0501..752ba7c09f204 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -32,7 +32,7 @@ precedence: '(' expression ')'; (note the add is evaluated before the multiply due to the *precedence operator*) <2> declare `int y`; - load from `x` -> `int 54`; + load from `x` -> `int 54`; subtract `int 50` from `int 54` -> `int 4`; divide `int 12` by `int 4` -> `int 3`; store `int 3` to `y`; @@ -133,18 +133,18 @@ occur. <1> declare `boolean b`; store `boolean true` to `b` <2> declare `int x`; - load from `b` -> `boolean true` + load from `b` -> `boolean true` evaluate 1st expression: `int 1` -> `int 1`; store `int 1` to `x` <3> declare `List y`; - load from `x` -> `int 1`; + load from `x` -> `int 1`; `int 1` greater than `int 1` -> `boolean false`; evaluate 2nd expression: `null` -> `null`; store `null` to `y`; <4> declare `def z`; - load from `x` -> `int 1`; + load from `x` -> `int 1`; `int 1` less than `int 2` -> `boolean true`; - evaluate 1st expression: load from `x` -> `int 1`; + evaluate 1st expression: load from `x` -> `int 1`; promote `int 1` and `double 2.0`: result `double`; implicit cast `int 1` to `double 1.0` -> `double 1.0`; implicit cast `double 1.0` to `def` -> `def`; @@ -198,12 +198,12 @@ non-static member fields: <1> declare `Example example`; allocate `Example` instance -> `Example reference`; store `Example reference` to `example` -<2> load from `example` -> `Example reference`; +<2> load from `example` -> `Example reference`; store `int 1` to `x` of `Example reference` -<3> load from `example` -> `Example reference`; +<3> load from `example` -> `Example reference`; implicit cast `double 2.0` to `def` -> `def`; store `def` to `y` of `Example reference` -<4> load from `example` -> `Example reference`; +<4> load from `example` -> `Example reference`; allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; store `List reference` to `z` of `Example reference` @@ -220,11 +220,11 @@ non-static member fields: <1> declare `Example example`; allocate `Example` instance -> `Example reference`; store `Example reference` to `example` -<2> load from `example` -> `Example reference`; +<2> load from `example` -> `Example reference`; store `int 1` to `x` of `Example reference` -<3> load from `example` -> `Example reference @0` - load from `example` -> `Example reference @1` - load from `x` of `Example reference @1` -> `int 1` +<3> load from `example` -> `Example reference @0` + load from `example` -> `Example reference @1` + load from `x` of `Example reference @1` -> `int 1` implicit cast `int 1` to `def` -> `def` store `def` to `y` of `Example reference @0`; (note `Example reference @0` and `Example reference @1` are the same) @@ -305,47 +305,47 @@ operators. + <1> declare `int i`; store `int 10` to `i` -<2> load `i` -> `int 10`; +<2> load from `i` -> `int 10`; multiply `int 10` and `int 2` -> `int 20`; store `int 20` to `i`; (note this is equivalent to `i = i*2`) -<3> load `i` -> `int 20`; +<3> load from `i` -> `int 20`; divide `int 20` by `int 5` -> `int 4`; store `int 4` to `i`; (note this is equivalent to `i = i/5`) -<4> load `i` -> `int 4`; +<4> load from `i` -> `int 4`; remainder `int 4` by `int 3` -> `int 1`; store `int 1` to `i`; (note this is equivalent to `i = i%3`) -<5> load `i` -> `int 1`; +<5> load from `i` -> `int 1`; add `int 1` and `int 5` -> `int 6`; store `int 6` to `i`; (note this is equivalent to `i = i+5`) -<6> load `i` -> `int 6`; +<6> load from `i` -> `int 6`; subtract `int 5` from `int 6` -> `int 1`; store `int 1` to `i`; (note this is equivalent to `i = i-5`) -<7> load `i` -> `int 1`; +<7> load from `i` -> `int 1`; left shift `int 1` by `int 2` -> `int 4`; store `int 4` to `i`; (note this is equivalent to `i = i<<2`) -<8> load `i` -> `int 4`; +<8> load from `i` -> `int 4`; right shift `int 4` by `int 1` -> `int 2`; store `int 2` to `i`; (note this is equivalent to `i = i>>1`) -<9> load `i` -> `int 2`; +<9> load from `i` -> `int 2`; unsigned right shift `int 2` by `int 1` -> `int 1`; store `int 1` to `i`; (note this is equivalent to `i = i>>>1`) -<10> load `i` -> `int 1`; +<10> load from `i` -> `int 1`; bitwise and `int 1` and `int 15` -> `int 1`; store `int 1` to `i`; (note this is equivalent to `i = i&2`) -<11> load `i` -> `int 1`; +<11> load from `i` -> `int 1`; bitwise xor `int 1` and `int 12` -> `int 13`; store `int 13` to `i`; (note this is equivalent to `i = i^2`) -<12> load `i` -> `int 13`; +<12> load from `i` -> `int 13`; bitwise or `int 13` and `int 2` -> `int 15`; store `int 15` to `i`; (note this is equivalent to `i = i|2`) @@ -362,15 +362,15 @@ operators. + <1> declare `boolean b`; store `boolean true` in `b`; -<2> load `b` -> `boolean true`; +<2> load from `b` -> `boolean true`; boolean and `boolean true` and `boolean false` -> `boolean false`; store `boolean false` to `b`; (note this is equivalent to `b = b && false`) -<3> load `b` -> `boolean false`; +<3> load from `b` -> `boolean false`; boolean xor `boolean false` and `boolean false` -> `boolean false`; store `boolean false` to `b`; (note this is equivalent to `b = b ^ false`) -<4> load `b` -> `boolean true`; +<4> load from `b` -> `boolean true`; boolean or `boolean false` and `boolean true` -> `boolean true`; store `boolean true` to `b`; (note this is equivalent to `b = b || true`) @@ -384,7 +384,7 @@ operators. ---- <1> declare `String s`; store `String 'compound'` to `s`; -<2> load `s` -> `String 'compound'`; +<2> load from `s` -> `String 'compound'`; string concat `String 'compound'` and `String ' assignment''` -> `String 'compound assignment'`; store `String 'compound assignment'` to `s`; @@ -400,7 +400,7 @@ operators. <1> declare `def x`; implicit cast `int 1` to `def`; store `def` to `x`; -<2> load `x` -> `def`; +<2> load from `x` -> `def`; implicit cast `def` to `int 1` -> `int 1`; add `int 1` and `int 2` -> `int 3`; implicit cast `int 3` to `def` -> `def`; @@ -416,7 +416,7 @@ operators. ---- <1> declare `byte b`; store `byte 1` to `x`; -<2> load `x` -> `byte 1`; +<2> load from `x` -> `byte 1`; implicit cast `byte 1 to `int 1` -> `int 1`; add `int 1` and `int 2` -> `int 3`; implicit cast `int 3` to `byte 3` -> `byte 3`; From 4e2b89d463c3afa507c34a0b181cc7fd672e30f9 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 31 May 2018 14:47:16 -0700 Subject: [PATCH 36/55] Update structure for long-term spec goals. --- docs/painless/painless-functions.asciidoc | 13 +++ .../painless/painless-general-syntax.asciidoc | 81 ------------------- docs/painless/painless-lambdas.asciidoc | 15 ++++ docs/painless/painless-lang-spec.asciidoc | 10 ++- docs/painless/painless-regexes.asciidoc | 33 ++++++++ docs/painless/painless-scripts.asciidoc | 6 ++ docs/painless/painless-statements.asciidoc | 14 ++++ 7 files changed, 90 insertions(+), 82 deletions(-) create mode 100644 docs/painless/painless-functions.asciidoc delete mode 100644 docs/painless/painless-general-syntax.asciidoc create mode 100644 docs/painless/painless-lambdas.asciidoc create mode 100644 docs/painless/painless-regexes.asciidoc create mode 100644 docs/painless/painless-scripts.asciidoc create mode 100644 docs/painless/painless-statements.asciidoc diff --git a/docs/painless/painless-functions.asciidoc b/docs/painless/painless-functions.asciidoc new file mode 100644 index 0000000000000..801c7092b9179 --- /dev/null +++ b/docs/painless/painless-functions.asciidoc @@ -0,0 +1,13 @@ +[[painless-functions]] +=== Functions + +You can declare functions at the beginning of a Painless script, for example: + +[source,painless] +--------------------------------------------------------- +boolean isNegative(def x) { x < 0 } +... +if (isNegative(someVar)) { + ... +} +--------------------------------------------------------- \ No newline at end of file diff --git a/docs/painless/painless-general-syntax.asciidoc b/docs/painless/painless-general-syntax.asciidoc deleted file mode 100644 index 114bff80bfa70..0000000000000 --- a/docs/painless/painless-general-syntax.asciidoc +++ /dev/null @@ -1,81 +0,0 @@ -[[painless-general-syntax]] -=== General Syntax - -[[control-flow]] -==== Control flow - -Painless supports all of Java's https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html[ -control flow statements] except the `switch` statement. - -Painless also supports the `for in` syntax from Groovy: - -[source,painless] ---------------------------------------------------------- -for (item : list) { - ... -} ---------------------------------------------------------- - -[[functions]] -==== Functions - -You can declare functions at the beginning of a Painless script, for example: - -[source,painless] ---------------------------------------------------------- -boolean isNegative(def x) { x < 0 } -... -if (isNegative(someVar)) { - ... -} ---------------------------------------------------------- - -[[lambda-expressions]] -==== Lambda expressions -Lambda expressions and method references work the same as in https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Java]. - -[source,painless] ---------------------------------------------------------- -list.removeIf(item -> item == 2); -list.removeIf((int item) -> item == 2); -list.removeIf((int item) -> { item == 2 }); -list.sort((x, y) -> x - y); -list.sort(Integer::compare); ---------------------------------------------------------- - -You can make method references to functions within the script with `this`, -for example `list.sort(this::mycompare)`. - -[[patterns]] -==== Patterns - -Regular expression constants are directly supported. To ensure fast performance, -this is the only mechanism for creating patterns. Regular expressions -are always constants and compiled efficiently a single time. - -[source,painless] ---------------------------------------------------------- -Pattern p = /[aeiou]/ ---------------------------------------------------------- - -[[pattern-flags]] -===== Pattern flags - -You can define flags on patterns in Painless by adding characters after the -trailing `/` like `/foo/i` or `/foo \w #comment/iUx`. Painless exposes all of -the flags from Java's -https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html[ -Pattern class] using these characters: - -[cols="<,<,<",options="header",] -|======================================================================= -| Character | Java Constant | Example -|`c` | CANON_EQ | `'å' ==~ /å/c` (open in hex editor to see) -|`i` | CASE_INSENSITIVE | `'A' ==~ /a/i` -|`l` | LITERAL | `'[a]' ==~ /[a]/l` -|`m` | MULTILINE | `'a\nb\nc' =~ /^b$/m` -|`s` | DOTALL (aka single line) | `'a\nb\nc' =~ /.b./s` -|`U` | UNICODE_CHARACTER_CLASS | `'Ɛ' ==~ /\\w/U` -|`u` | UNICODE_CASE | `'Ɛ' ==~ /ɛ/iu` -|`x` | COMMENTS (aka extended) | `'a' ==~ /a #comment/x` -|======================================================================= diff --git a/docs/painless/painless-lambdas.asciidoc b/docs/painless/painless-lambdas.asciidoc new file mode 100644 index 0000000000000..e6694229a0cef --- /dev/null +++ b/docs/painless/painless-lambdas.asciidoc @@ -0,0 +1,15 @@ +[[painless-lambdas]] +=== Lambdas +Lambda expressions and method references work the same as in https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Java]. + +[source,painless] +--------------------------------------------------------- +list.removeIf(item -> item == 2); +list.removeIf((int item) -> item == 2); +list.removeIf((int item) -> { item == 2 }); +list.sort((x, y) -> x - y); +list.sort(Integer::compare); +--------------------------------------------------------- + +You can make method references to functions within the script with `this`, +for example `list.sort(this::mycompare)`. \ No newline at end of file diff --git a/docs/painless/painless-lang-spec.asciidoc b/docs/painless/painless-lang-spec.asciidoc index 66142618aa538..d50f3db2dc0d3 100644 --- a/docs/painless/painless-lang-spec.asciidoc +++ b/docs/painless/painless-lang-spec.asciidoc @@ -43,4 +43,12 @@ include::painless-operators-reference.asciidoc[] include::painless-operators-array.asciidoc[] -include::painless-general-syntax.asciidoc[] +include::painless-statements.asciidoc[] + +include::painless-scripts.asciidoc[] + +include::painless-functions.asciidoc[] + +include::painless-lambdas.asciidoc[] + +include::painless-regexes.asciidoc[] diff --git a/docs/painless/painless-regexes.asciidoc b/docs/painless/painless-regexes.asciidoc new file mode 100644 index 0000000000000..b4434208ab0ec --- /dev/null +++ b/docs/painless/painless-regexes.asciidoc @@ -0,0 +1,33 @@ +[[painless-regexes]] +=== Regexes + +Regular expression constants are directly supported. To ensure fast performance, +this is the only mechanism for creating patterns. Regular expressions +are always constants and compiled efficiently a single time. + +[source,painless] +--------------------------------------------------------- +Pattern p = /[aeiou]/ +--------------------------------------------------------- + +[[pattern-flags]] +==== Pattern flags + +You can define flags on patterns in Painless by adding characters after the +trailing `/` like `/foo/i` or `/foo \w #comment/iUx`. Painless exposes all of +the flags from Java's +https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html[ +Pattern class] using these characters: + +[cols="<,<,<",options="header",] +|======================================================================= +| Character | Java Constant | Example +|`c` | CANON_EQ | `'å' ==~ /å/c` (open in hex editor to see) +|`i` | CASE_INSENSITIVE | `'A' ==~ /a/i` +|`l` | LITERAL | `'[a]' ==~ /[a]/l` +|`m` | MULTILINE | `'a\nb\nc' =~ /^b$/m` +|`s` | DOTALL (aka single line) | `'a\nb\nc' =~ /.b./s` +|`U` | UNICODE_CHARACTER_CLASS | `'Ɛ' ==~ /\\w/U` +|`u` | UNICODE_CASE | `'Ɛ' ==~ /ɛ/iu` +|`x` | COMMENTS (aka extended) | `'a' ==~ /a #comment/x` +|======================================================================= \ No newline at end of file diff --git a/docs/painless/painless-scripts.asciidoc b/docs/painless/painless-scripts.asciidoc new file mode 100644 index 0000000000000..7b99c0f02b0fb --- /dev/null +++ b/docs/painless/painless-scripts.asciidoc @@ -0,0 +1,6 @@ +[[painless-scripts]] +=== Scripts + +Scripts are composed of one-to-many <> and are +run in a sandbox that determines what local variables are immediately available +along with what API's are whitelisted for use. \ No newline at end of file diff --git a/docs/painless/painless-statements.asciidoc b/docs/painless/painless-statements.asciidoc new file mode 100644 index 0000000000000..3bc4513baa733 --- /dev/null +++ b/docs/painless/painless-statements.asciidoc @@ -0,0 +1,14 @@ +[[painless-statements]] +=== Statements + +Painless supports all of Java's https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html[ +control flow statements] except the `switch` statement. + +Painless also supports the `for in` syntax from Groovy: + +[source,painless] +--------------------------------------------------------- +for (item : list) { + ... +} +--------------------------------------------------------- \ No newline at end of file From 8302de35f20f9a8244d8d5bbe33123a4be291169 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Fri, 1 Jun 2018 13:09:41 -0700 Subject: [PATCH 37/55] Clean up numerical operators. --- docs/painless/painless-casting.asciidoc | 1 + docs/painless/painless-comments.asciidoc | 1 + docs/painless/painless-identifiers.asciidoc | 5 +- docs/painless/painless-literals.asciidoc | 3 + .../painless-operators-general.asciidoc | 11 +- .../painless-operators-numeric.asciidoc | 1499 ++++++++++++----- docs/painless/painless-variables.asciidoc | 2 + 7 files changed, 1104 insertions(+), 418 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 02419c8f20b33..31ca64723dd67 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -16,6 +16,7 @@ allowed casts. * If an implicit cast is given, but an explicit cast is required. *Grammar* + [source,ANTLR4] ---- cast: '(' TYPE ')' expression diff --git a/docs/painless/painless-comments.asciidoc b/docs/painless/painless-comments.asciidoc index bde30e37e04e1..209faeeed382a 100644 --- a/docs/painless/painless-comments.asciidoc +++ b/docs/painless/painless-comments.asciidoc @@ -9,6 +9,7 @@ start anywhere on a line, and all characters in between the `/*` token and `*/` token are ignored. Comments can be included anywhere within a script. *Grammar* + [source,ANTLR4] ---- SINGLE_LINE_COMMENT: '//' .*? [\n\r]; diff --git a/docs/painless/painless-identifiers.asciidoc b/docs/painless/painless-identifiers.asciidoc index 779b405c1af6b..633fca28df293 100644 --- a/docs/painless/painless-identifiers.asciidoc +++ b/docs/painless/painless-identifiers.asciidoc @@ -3,8 +3,9 @@ Use an identifier as a named token to specify a <>, <>, -<>, <>, or function. -<> cannot be used as identifiers. +<>, <>, or +<>. <> cannot be used +as identifiers. *Grammar* [source,ANTLR4] diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index f41e5fdd79ceb..5dd6981a7e46e 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -16,6 +16,7 @@ to specify an integer literal as octal, and use `0x` or `0X` as a prefix to specify an integer literal as hex. *Grammar* + [source,ANTLR4] ---- INTEGER: '-'? ( '0' | [1-9] [0-9]* ) [lLfFdD]?; @@ -53,6 +54,7 @@ single letter designations to specify the primitive type: `f` or `F` for `float` and `d` or `D` for `double`. If not specified, the type defaults to `double`. *Grammar* + [source,ANTLR4] ---- DECIMAL: '-'? ( '0' | [1-9] [0-9]* ) (DOT [0-9]+)? EXPONENT? [fFdD]?; @@ -88,6 +90,7 @@ include a single-quote as part of a single-quoted string literal. Use a `\\` token to include a backslash as part of any string literal. *Grammar* + [source,ANTLR4] ---- STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 752ba7c09f204..5bea4ef2edcf6 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -10,6 +10,7 @@ prior to other expressions in inward-to-outward order. Use the *precedence operator* to guarantee the order of evaluation for an expression. *Grammar* + [source,ANTLR4] ---- precedence: '(' expression ')'; @@ -42,10 +43,11 @@ precedence: '(' expression ')'; [[function-call-operator]] ==== Function Call -A function call is defined within a script. Use the *function call operator* to -call an existing function. +A <> is defined within a script. Use the +*function call operator* to call an existing function. *Grammar* + [source,ANTLR4] ---- function_call: ID '(' ( expression (',' expression)* )? ')''; @@ -94,6 +96,7 @@ full if/else branch in certain expressions. * If the values for the second and third expressions cannot be promoted. *Grammar* + [source,ANTLR4] ---- conditional: expression '?' expression ':' expression; @@ -166,6 +169,7 @@ See <> for examples using variables. * If the type of value is unable to match the type of variable or field. *Grammar* + [source,ANTLR4] ---- assignment: field '=' expression @@ -247,7 +251,7 @@ V = (T)(V op expression); The table below shows the available operators for use in a compound assignment. Each operator follows the casting/promotion rules according to their regular -definition. For numeric operations their will be an extra implicit cast when +definition. For numeric operations there is an extra implicit cast when necessary to return the promoted numeric type value to the original numeric type value of the variable/field and can result in data loss. @@ -275,6 +279,7 @@ value of the variable/field and can result in data loss. * If the type of value is unable to match the type of variable or field. *Grammar* + [source,ANTLR4] ---- compound_assignment: ( ID | field ) '$=' expression; diff --git a/docs/painless/painless-operators-numeric.asciidoc b/docs/painless/painless-operators-numeric.asciidoc index d3f3af34e77c5..bc31cfbc496e3 100644 --- a/docs/painless/painless-operators-numeric.asciidoc +++ b/docs/painless/painless-operators-numeric.asciidoc @@ -4,660 +4,1333 @@ [[post-increment-operator]] ==== 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. +Use the *post increment operator* to increase the value of numerical type +variable/field by `1`. There is an extra implicit cast when necessary to return +the promoted numeric type value to the original numeric type value of the +variable/field and can result in data loss. If a variable/field is read as part +of an expression the value is loaded prior to the increment. + +*Errors* + +* If the evaluated variable/field is a non-numeric type. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- -post_increment: ( variable | member ) '++' +post_increment: ( variable | field ) '++'; ---- -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: +*Promotion* +[options="header",cols="<1,<1,<1"] |==== -|from|to|downcast -|byte|int|byte -|short|int|short -|char|int|char -|int|int| -|long|long| -|float|float| -|double|double| -|def|def| +| original | promoted | implicit +| 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 ----- +*Examples* + +* Use of the *post increment operator*. ++ +[source,Painless] +---- +<1> short i = 0; +<2> i++; +<3> long j = 1; +<4> long k; +<5> k = j++; +---- ++ +<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` ++ +* Use of the *post increment operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 1; +<2> x++; +---- ++ +<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 -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. +Use the *post decrement operator* to decrease the value of numerical type +variable/field by `1`. There is an extra implicit cast when necessary to return +the promoted numeric type value to the original numeric type value of the +variable/field and can result in data loss. If a variable/field is read as part +of an expression the value is loaded prior to the decrement. + +*Errors* + +* If the evaluated variable/field is a non-numeric type. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- -post_increment: ( variable | member ) '--' +post_decrement: ( variable | field ) '--'; ---- -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: +*Promotion* +[options="header",cols="<1,<1,<1"] |==== -|from|to|downcast -|byte|int|byte -|short|int|short -|char|int|char -|int|int| -|long|long| -|float|float| -|double|double| -|def|def| +| original | promoted | implicit +| 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 ----- +*Examples* + +* Use of the *post decrement operator*. ++ +[source,Painless] +---- +<1> short i = 0; +<2> i--; +<3> long j = 1; +<4> long k; +<5> k = j--; +---- ++ +<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` ++ +* Use of the *post decrement operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 1; +<2> x--; +---- ++ +<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 -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. +Use the *pre increment operator* to increase the value of numerical type +variable/field by `1`. There is an extra implicit cast when necessary to return +the promoted numeric type value to the original numeric type value of the +variable/field and can result in data loss. If a variable/field is read as part +of an expression the value is loaded after the increment. + +*Errors* + +* If the evaluated variable/field is a non-numeric type. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- -pre_increment: '++' ( variable | member ) +pre_increment: '++' ( variable | field ); ---- -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: +*Promotion* +[options="header",cols="<1,<1,<1"] |==== -|from|to|downcast -|byte|int|byte -|short|int|short -|char|int|char -|int|int| -|long|long| -|float|float| -|double|double| -|def|def| +| original | promoted | implicit +| 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) ----- +*Examples* + +* Use of the *pre increment operator*. ++ +[source,Painless] +---- +<1> short i = 0; +<2> ++i; +<3> long j = 1; +<4> long k; +<5> k = ++j; +---- ++ +<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` ++ +* Use of the *post increment operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 1; +<2> ++x; +---- ++ +<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 -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. +Use the *pre decrement operator* to decrease the value of numerical type +variable/field by `1`. There is an extra implicit cast when necessary to return +the promoted numeric type value to the original numeric type value of the +variable/field and can result in data loss. If a variable/field is read as part +of an expression the value is loaded after the decrement. + +*Errors* + +* If the evaluated variable/field is a non-numeric type. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- -pre_decrement: '--' ( variable | member ) +pre_increment: '--' ( variable | field ); ---- -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* -Promotion Table: +[options="header",cols="<1,<1,<1"] |==== -|from|to|downcast -|byte|int|byte -|short|int|short -|char|int|char -|int|int| -|long|long| -|float|float| -|double|double| -|def|def| +| original | promoted | implicit +| 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) ----- +*Examples* + +* Use of the *pre decrement operator*. ++ +[source,Painless] +---- +<1> short i = 0; +<2> --i; +<3> long j = 1; +<4> long k; +<5> k = --j; +---- ++ +<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`; ++ +* Use of the *pre decrement operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 1; +<2> --x; +---- ++ +<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 -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. +Use the *unary positive operator* to the retrieve the identity of a numeric +value. -*Grammar:* -[source,ANTLR4] ----- -unary_positive: '+' expression ----- +*Errors* -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. +* If the evaluated value is a non-numeric type. -Promotion Table: -|==== -|from|to -|byte|int -|short|int -|char|int -|int|int -|long|long -|float|float -|double|double -|def|def -|==== +*Grammar* -*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 +[source,ANTLR4] ---- +unary_positive: '+' expression; +---- + +*Examples* + +* Use of the *unary positive operator*. ++ +[source,Painless] +---- +<1> int x = +1; +<2> long y = +x; +---- ++ +<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` ++ +* Use of the *unary positive operator* with the `def` type. ++ +[source,Painless] +---- +<1> def z = +1; +<2> int i = +z; +---- +<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 -Unary negative negates a numeric value using the minus operator. Format starts with a minus followed by a numerical expression. +Use the *unary negative operator* to negate a numeric type value. -*Grammar:* -[source,ANTLR4] ----- -unary_negative: '-' expression ----- +*Errors* -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. +* If the evaluated value is a non-numeric type. -Promotion Table: -|==== -|from|to -|byte|int -|short|int -|char|int -|int|int -|long|long -|float|float -|double|double -|def|def -|==== +*Grammar* -*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 +[source,ANTLR4] ---- +unary_negative: '-' expression; +---- + +*Examples* + +* Use of the *unary negative operator*. ++ +[source,Painless] +---- +<1> int x = -1; +<2> long y = -x; +---- ++ +<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` ++ +* Use of the *unary negative operator* with the `def` type. ++ +[source,Painless] +---- +<1> def z = -1; +<2> int i = -z; +---- +<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 -Bitwise not will flip each bit of an integer type expression. The format is the tilde operator followed by an expression. +Use the *bitwise not operator* to flip each bit in an integer type value where +if a bit is `1` it becomes `0` and if a bit is `0` it becomes `1`. + +*Errors* + +* If the evaluated value is a non-integer type. + +*Bits* + +[options="header",cols="^1,^1,"] +|==== +| original | result +| 1 | 0 +| 0 | 1 +|==== + +*Grammar* -*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* -Promotion Table: +[options="header",cols="<1,<1"] |==== -|from|to -|byte|int -|short|int -|char|int -|int|int -|long|long -|def|def +| original | promoted +| 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 ----- +*Examples* + +* Uses of the *bitwise not operator*. ++ +[source,Painless] +---- +<1> byte b = 1; +<2> int i = ~b; +<3> long l = ~i; +---- ++ +<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` ++ +* Uses of the *bitwise not operator* with the `def` type. ++ +[source,Painless] +---- +<1> def d = 1; +<2> def e = ~d; +---- ++ +<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 -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. +Use the *multiplication operator* to multiply together two numerical +values. Rules for resultant overflow and NaN values follow the JVM +specification. + +*Errors* + +* If either of the evaluated values is a non-numeric type. + +*Grammar* -*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* -Promotion Table: +[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 +| | 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) ----- +*Examples* + +* Uses of the *multiplication operator*. ++ +[source,Painless] +---- +<1> int i = 5*4; +<2> double d = i*7.0; +---- ++ +<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` ++ +* Uses of the *multiplication operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 5*4; +<2> def y = x*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 -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. +Use the *division operator* to divide two numerical values. 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 evaluated 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* -*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* -Promotion Table: +[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 +| | 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) ----- +*Examples* + +* Uses of the *division operator*. ++ +[source,Painless] +---- +<1> int i = 29/4; +<2> double d = i/7.0; +---- ++ +<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` ++ +* Uses of the *division operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 5/4; +<2> def y = x/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 -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. +Use the *remainder operator* to calculate the remainder for division between +two numerical values. Rules for NaN values and division by zero follow the JVM +specification. + +*Errors* + +* If either of the evaluated values is a non-numeric type. + +*Grammar* -*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* -Promotion Table: +[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 +| | 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) ----- +*Examples* + +* Uses of the *remainder operator*. ++ +[source,Painless] +---- +<1> int i = 29%4; +<2> double d = i%7.0; +---- ++ +<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` ++ +* Uses of the *remainder operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 5%4; +<2> def y = x%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 -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. +Use the *addition operator* to add together two numerical values. Rules for +resultant overflow and NaN values follow the JVM specification. + +*Errors* + +* If either of the evaluated values is a non-numeric type. + +*Grammar* -*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* -Promotion Table: +[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 +| | 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) ----- +*Examples* + +* Uses of the *addition operator*. ++ +[source,Painless] +---- +<1> int i = 29+4; +<2> double d = i+7.0; +---- ++ +<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` ++ +* Uses of the *addition operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 5+4; +<2> def y = x+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 -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. +Use the *subtraction operator* to subtract a right-hand side numerical value +from a left-hand side numerical value. Rules for resultant overflow and NaN +values follow the JVM specification. + +*Errors* + +* If either of the evaluated values is a non-numeric type. + +*Grammar* -*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* -Promotion Table: +[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 +| | 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) ----- +*Examples* + +* Uses of the *subtraction operator*. ++ +[source,Painless] +---- +<1> int i = 29-4; +<2> double d = i-7.5; +---- ++ +<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` ++ +* Uses of the *subtraction operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 5-4; +<2> def y = x-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 -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. +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 evaluated values is a non-integer type. +* If the evaluated right-hand side value cannot be cast to an int type. + +*Grammar* -*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* + +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. -Promotion Table: +[options="header",cols="<1,<1"] |==== -|from|to -|byte|int -|short|int -|char|int -|int|int -|long|long -|def|def +| original | promoted +| 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 ----- +*Examples* + +* Uses of the *left shift operator*. ++ +[source,Painless] +---- +<1> int i = 4 << 1; +<2> long l = i << 2L; +---- ++ +<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` ++ +* Uses of the *left shift operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 4 << 2; +<2> def y = x << 1; +---- +<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 -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. +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 evaluated values is a non-integer type. +* If the evaluated right-hand side value cannot be cast to an int type. + +*Grammar* -*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* + +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. -Promotion Table: +[options="header",cols="<1,<1"] |==== -|from|to -|byte|int -|short|int -|char|int -|int|int -|long|long -|def|def +| original | promoted +| 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 ----- +*Examples* + +* Uses of the *right shift operator*. ++ +[source,Painless] +---- +<1> int i = 32 >> 1; +<2> long l = i >> 2L; +---- ++ +<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` ++ +* Uses of the *right shift operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 16 >> 2; +<2> def y = x >> 1; +---- +<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 -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. +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 evaluated values is a non-integer type. +* If the evaluated right-hand side value cannot be cast to an int type. + +*Grammar* -*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* + +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. -Promotion Table: +[options="header",cols="<1,<1"] |==== -|from|to -|byte|int -|short|int -|char|int -|int|int -|long|long -|def|def +| original | promoted +| 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 ----- +*Examples* + +* Uses of the *unsigned right shift operator*. ++ +[source,Painless] +---- +<1> int i = -1 >>> 29; +<2> long l = i >>> 2L; +---- ++ +<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` ++ +* Uses of the *unsigned right shift operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 16 >>> 2; +<2> def y = x >>> 1; +---- +<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 -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. +Use the *bitwise and operator* to bitwise and together each bit within two +integer type values where if both bits at the same index are `1` the resultant +bit is `1` otherwise the resultant bit is `0`. + +*Errors* + +* If either of the evaluated values is a non-integer type. + +*Bits* + +The following table illustrates the resultant bit from the anding of two bits. +[cols="^1,^1,^1"] |==== -||1|0 -|1|1|0 -|0|0|0 +| | 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* -*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* -Promotion Table: +[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|def|def +| | 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:* -[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 ----- +*Examples* + +* Uses of the *bitwise and operator*. ++ +[source,Painless] +---- +<1> int i = 5 & 6; +<2> long l = i & 5L; +---- ++ +<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` ++ +* Uses of the *bitwise and operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 15 & 6; +<2> def y = x & 5; +---- +<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 -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. +Use the *bitwise xor operator* to bitwise 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 evaluated values is a non-integer type. +*Bits* + +The following table illustrates the resultant bit from the anding of two bits. + +[cols="^1,^1,^1"] |==== -||1|0 -|1|0|1 -|0|1|0 +| | 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* -*Grammar:* [source,ANTLR4] ---- -bitwise_xor: expression '^' expression; +bitwise_and: 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* -Promotion Table: +[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|def|def +| | 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:* -[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 ----- +*Examples* + +* Uses of the *bitwise xor operator*. ++ +[source,Painless] +---- +<1> int i = 5 ^ 6; +<2> long l = i ^ 5L; +---- ++ +<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` ++ +* Uses of the *bitwise xor operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 15 ^ 6; +<2> def y = x ^ 5; +---- +<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 -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. +Use the *bitwise or operator* to bitwise 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 evaluated values is a non-integer type. +*Bits* + +The following table illustrates the resultant bit from the anding of two bits. + +[cols="^1,^1,^1"] |==== -||1|0 -|1|1|1 -|0|1|0 +| | 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* -*Grammar:* [source,ANTLR4] ---- -bitwise_or: expression '|' expression; +bitwise_and: 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* -Promotion Table: +[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|def|def +| | 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:* -[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 ----- \ No newline at end of file +*Examples* + +* Uses of the *bitwise or operator*. ++ +[source,Painless] +---- +<1> int i = 5 | 6; +<2> long l = i | 8L; +---- ++ +<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` ++ +* Uses of the *bitwise or operator* with the `def` type. ++ +[source,Painless] +---- +<1> def x = 5 ^ 6; +<2> def y = x ^ 8; +---- +<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` \ No newline at end of file diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 89e267aedc2b3..3da88ffa6ab2d 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -22,6 +22,7 @@ value will have a default value assigned implicitly based on the type. * If a variable is used prior to or without declaration. *Grammar* + [source,ANTLR4] ---- declaration : type ID assignment? (',' ID assignment?)*; @@ -77,6 +78,7 @@ type. * If the type of value is unable to match the type of variable. *Grammar* + [source,ANTLR4] ---- assignment: ID '=' expression From 0696c831fe5986da2b6c7e927be00d6ab9e2b730 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Fri, 1 Jun 2018 16:59:35 -0700 Subject: [PATCH 38/55] Partially completed clean up of reference type operators. --- docs/painless/painless-casting.asciidoc | 26 +- docs/painless/painless-comments.asciidoc | 2 +- docs/painless/painless-functions.asciidoc | 11 + docs/painless/painless-identifiers.asciidoc | 7 +- docs/painless/painless-keywords.asciidoc | 10 +- docs/painless/painless-literals.asciidoc | 2 +- .../painless-operators-general.asciidoc | 80 +-- .../painless-operators-reference.asciidoc | 547 ++++++++++++------ docs/painless/painless-operators.asciidoc | 2 +- docs/painless/painless-types.asciidoc | 30 +- docs/painless/painless-variables.asciidoc | 8 +- 11 files changed, 482 insertions(+), 243 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 31ca64723dd67..fdba99384a52b 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -177,8 +177,8 @@ or the target type is a descendant of the original type. <3> declare `ArrayList y`; load from `x` -> `List reference`; *error* -> cannot explicit cast `List reference` to `Map reference`; - (note no cast would be valid since neither `List` nor `Map` is a descendant - of the other) + (note no cast is valid since neither `List` nor `Map` is a descendant of the + other) [[dynamic-type-casting]] ==== Dynamic Type Casting @@ -252,8 +252,8 @@ based on the current type value the `def` type value represents. implicit cast `def` to `double 1.0` -> `double 1.0`; explicit cast `double 1.0` to `int 1` -> `int 1`; store `int 1` to `i`; - (note the explicit cast is necessary since a `double` value cannot be - converted to an `int` value implicitly) + (note the explicit cast is necessary since a `double` type value is not + converted to an `int` type value implicitly) <3> store `int 1` to `d`; (note the switch in the type `d` represents from `double` to `int`) <4> declare `float i`; @@ -294,8 +294,8 @@ based on the current type value the `def` type value represents. load from `d` -> `def`; implicit cast `def` to `HashMap reference`; *error* -> cannot implicit cast `HashMap reference` to `List reference`; - (note no cast would be valid since neither `HashMap` nor `List` is a - descendant of the other) + (note no cast is valid since neither `HashMap` nor `List` is a descendant of + the other) [[string-character-casting]] ==== String to Character Casting @@ -324,7 +324,7 @@ Use the *cast operator* to convert a <> value into a <2> explicit cast `String 'c'` to `char c` -> `char c`; store `char c` to `c` + -* Casting a `String` reference into a `char` value. +* Casting a `String` reference into a `char` type value. + [source,Painless] ---- @@ -347,12 +347,12 @@ reference type to its corresponding primitive type. Implicit boxing/unboxing occurs during the following operations: -* Conversions between a `def` type and a primitive type will be implicitly +* Conversions between a `def` type and a primitive type are implicitly boxed/unboxed as necessary, though this is referred to as an implicit cast throughout the documentation. -* Method/function call arguments will be implicitly boxed/unboxed as necessary. -* A primitive type value will be implicitly boxed when a reference type method - call is invoked on it. +* Method/function call arguments are implicitly boxed/unboxed as necessary. +* A primitive type value is implicitly boxed when a reference type method call + is invoked on it. Explicit boxing/unboxing is not allowed. Use the reference type API to explicitly convert a primitive type value to its respective reference type @@ -423,8 +423,8 @@ Promotion is when a single value is implicitly cast to a certain type or multiple values are implicitly cast to the same type as required for evaluation by certain operations. Each operation that requires promotion has a promotion table that shows all required implicit casts based on the type(s) of value(s). A -value can be promoted to a `def` type at compile-time; however, the promoted -type value is derived from what the `def` type value represents at run-time. +value is promoted to a `def` type at compile-time; however, the promoted type +value is derived from what the `def` type value represents at run-time. *Errors* diff --git a/docs/painless/painless-comments.asciidoc b/docs/painless/painless-comments.asciidoc index 209faeeed382a..bfd3594431ebd 100644 --- a/docs/painless/painless-comments.asciidoc +++ b/docs/painless/painless-comments.asciidoc @@ -6,7 +6,7 @@ anywhere on a line to specify a single-line comment. All characters from the `//` token to the end of the line are ignored. Use an opening `/*` token and a closing `*/` token to specify a multi-line comment. Multi-line comments can start anywhere on a line, and all characters in between the `/*` token and `*/` -token are ignored. Comments can be included anywhere within a script. +token are ignored. A comment is included anywhere within a script. *Grammar* diff --git a/docs/painless/painless-functions.asciidoc b/docs/painless/painless-functions.asciidoc index 801c7092b9179..485378fa7ee32 100644 --- a/docs/painless/painless-functions.asciidoc +++ b/docs/painless/painless-functions.asciidoc @@ -1,6 +1,17 @@ [[painless-functions]] === Functions +A function is a named piece of code comprised of one-to-many statements to +perform a specific task. A function is called multiple times in a single script +to repeat its specific task. A parameter is a named type value available as a +<> within the statement(s) of a function. A +function specifies zero-to-many parameters, and when a function is called a +value is specified per parameter. An argument is a value passed into a function +as the point of call. A function specifies a return type value, though if the +type is <> then no value is returned. Any non-void type return +value is available for use within an <> or is +discarded otherwise. + You can declare functions at the beginning of a Painless script, for example: [source,painless] diff --git a/docs/painless/painless-identifiers.asciidoc b/docs/painless/painless-identifiers.asciidoc index 633fca28df293..d2678b528ea51 100644 --- a/docs/painless/painless-identifiers.asciidoc +++ b/docs/painless/painless-identifiers.asciidoc @@ -4,8 +4,11 @@ Use an identifier as a named token to specify a <>, <>, <>, <>, or -<>. <> cannot be used -as identifiers. +<>. + +*Errors* + +If a <> is used as an identifier. *Grammar* [source,ANTLR4] diff --git a/docs/painless/painless-keywords.asciidoc b/docs/painless/painless-keywords.asciidoc index 39a2201fd2b4b..9463902c8d346 100644 --- a/docs/painless/painless-keywords.asciidoc +++ b/docs/painless/painless-keywords.asciidoc @@ -1,9 +1,13 @@ [[painless-keywords]] === Keywords -Keywords are reserved tokens for built-in language features and cannot be used -as <> within a script. The following are -keywords: +Keywords are reserved tokens for built-in language features. + +*Errors* + +If a keyword is used as an <>. + +*Keywords* [cols="^1,^1,^1,^1,^1"] |==== diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index 5dd6981a7e46e..0be67968dbe62 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -120,6 +120,6 @@ STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) [[character-literals]] ==== Characters -A character literal cannot be specified directly. Instead, use the +A character literal is not specified directly. Instead, use the <> to convert a `String` type value into a `char` type value. diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 5bea4ef2edcf6..b4f9c8b2e3a2f 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -33,7 +33,7 @@ precedence: '(' expression ')'; (note the add is evaluated before the multiply due to the *precedence operator*) <2> declare `int y`; - load from `x` -> `int 54`; + load from `x` -> `int 54`; subtract `int 50` from `int 54` -> `int 4`; divide `int 12` by `int 4` -> `int 3`; store `int 3` to `y`; @@ -83,12 +83,12 @@ an explicit cast. Refer to <> for more information. ==== Conditional A conditional 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. The second and third -expressions will be <> if the evaluated values are not the -same type. Use the *conditional operator* as a shortcut to avoid the need for a -full if/else branch in certain expressions. +with an expected `boolean` result type. If the first expression evaluates to +`true` then the second expression is evaluated. If the first expression +evaluates to `false` then the third expression is evaluated. The second and +third expressions are <> if the evaluated values are not +the same type. Use the *conditional operator* as a shortcut to avoid the need +for a full if/else branch in certain expressions. *Errors* @@ -136,18 +136,18 @@ occur. <1> declare `boolean b`; store `boolean true` to `b` <2> declare `int x`; - load from `b` -> `boolean true` + load from `b` -> `boolean true` evaluate 1st expression: `int 1` -> `int 1`; store `int 1` to `x` <3> declare `List y`; - load from `x` -> `int 1`; + load from `x` -> `int 1`; `int 1` greater than `int 1` -> `boolean false`; evaluate 2nd expression: `null` -> `null`; store `null` to `y`; <4> declare `def z`; - load from `x` -> `int 1`; + load from `x` -> `int 1`; `int 1` less than `int 2` -> `boolean true`; - evaluate 1st expression: load from `x` -> `int 1`; + evaluate 1st expression: load from `x` -> `int 1`; promote `int 1` and `double 2.0`: result `double`; implicit cast `int 1` to `double 1.0` -> `double 1.0`; implicit cast `double 1.0` to `def` -> `def`; @@ -157,10 +157,10 @@ occur. ==== Assignment Use the *assignment operator* to store a value in a variable or reference type -member field for use in subsequent operations. Any operation -that produces a value can be assigned to any variable/field as long as the -<> are the same or the resultant type can be -<> to the variable/field type. +member field for use in subsequent operations. Any operation that produces a +value is assigned to any variable/field as long as the <> +are the same or an <> of the resultant type to +the variable/field type is possible. See <> for examples using variables. @@ -202,12 +202,12 @@ non-static member fields: <1> declare `Example example`; allocate `Example` instance -> `Example reference`; store `Example reference` to `example` -<2> load from `example` -> `Example reference`; +<2> load from `example` -> `Example reference`; store `int 1` to `x` of `Example reference` -<3> load from `example` -> `Example reference`; +<3> load from `example` -> `Example reference`; implicit cast `double 2.0` to `def` -> `def`; store `def` to `y` of `Example reference` -<4> load from `example` -> `Example reference`; +<4> load from `example` -> `Example reference`; allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; store `List reference` to `z` of `Example reference` @@ -224,12 +224,12 @@ non-static member fields: <1> declare `Example example`; allocate `Example` instance -> `Example reference`; store `Example reference` to `example` -<2> load from `example` -> `Example reference`; +<2> load from `example` -> `Example reference`; store `int 1` to `x` of `Example reference` -<3> load from `example` -> `Example reference @0` - load from `example` -> `Example reference @1` - load from `x` of `Example reference @1` -> `int 1` - implicit cast `int 1` to `def` -> `def` +<3> load from `example` -> `Example reference @0`; + load from `example` -> `Example reference @1`; + load from `x` of `Example reference @1` -> `int 1`; + implicit cast `int 1` to `def` -> `def`; store `def` to `y` of `Example reference @0`; (note `Example reference @0` and `Example reference @1` are the same) @@ -310,47 +310,47 @@ operators. + <1> declare `int i`; store `int 10` to `i` -<2> load from `i` -> `int 10`; +<2> load from `i` -> `int 10`; multiply `int 10` and `int 2` -> `int 20`; store `int 20` to `i`; (note this is equivalent to `i = i*2`) -<3> load from `i` -> `int 20`; +<3> load from `i` -> `int 20`; divide `int 20` by `int 5` -> `int 4`; store `int 4` to `i`; (note this is equivalent to `i = i/5`) -<4> load from `i` -> `int 4`; +<4> load from `i` -> `int 4`; remainder `int 4` by `int 3` -> `int 1`; store `int 1` to `i`; (note this is equivalent to `i = i%3`) -<5> load from `i` -> `int 1`; +<5> load from `i` -> `int 1`; add `int 1` and `int 5` -> `int 6`; store `int 6` to `i`; (note this is equivalent to `i = i+5`) -<6> load from `i` -> `int 6`; +<6> load from `i` -> `int 6`; subtract `int 5` from `int 6` -> `int 1`; store `int 1` to `i`; (note this is equivalent to `i = i-5`) -<7> load from `i` -> `int 1`; +<7> load from `i` -> `int 1`; left shift `int 1` by `int 2` -> `int 4`; store `int 4` to `i`; (note this is equivalent to `i = i<<2`) -<8> load from `i` -> `int 4`; +<8> load from `i` -> `int 4`; right shift `int 4` by `int 1` -> `int 2`; store `int 2` to `i`; (note this is equivalent to `i = i>>1`) -<9> load from `i` -> `int 2`; +<9> load from `i` -> `int 2`; unsigned right shift `int 2` by `int 1` -> `int 1`; store `int 1` to `i`; (note this is equivalent to `i = i>>>1`) -<10> load from `i` -> `int 1`; +<10> load from `i` -> `int 1`; bitwise and `int 1` and `int 15` -> `int 1`; store `int 1` to `i`; (note this is equivalent to `i = i&2`) -<11> load from `i` -> `int 1`; +<11> load from `i` -> `int 1`; bitwise xor `int 1` and `int 12` -> `int 13`; store `int 13` to `i`; (note this is equivalent to `i = i^2`) -<12> load from `i` -> `int 13`; +<12> load from `i` -> `int 13`; bitwise or `int 13` and `int 2` -> `int 15`; store `int 15` to `i`; (note this is equivalent to `i = i|2`) @@ -367,15 +367,15 @@ operators. + <1> declare `boolean b`; store `boolean true` in `b`; -<2> load from `b` -> `boolean true`; +<2> load from `b` -> `boolean true`; boolean and `boolean true` and `boolean false` -> `boolean false`; store `boolean false` to `b`; (note this is equivalent to `b = b && false`) -<3> load from `b` -> `boolean false`; +<3> load from `b` -> `boolean false`; boolean xor `boolean false` and `boolean false` -> `boolean false`; store `boolean false` to `b`; (note this is equivalent to `b = b ^ false`) -<4> load from `b` -> `boolean true`; +<4> load from `b` -> `boolean true`; boolean or `boolean false` and `boolean true` -> `boolean true`; store `boolean true` to `b`; (note this is equivalent to `b = b || true`) @@ -389,7 +389,7 @@ operators. ---- <1> declare `String s`; store `String 'compound'` to `s`; -<2> load from `s` -> `String 'compound'`; +<2> load from `s` -> `String 'compound'`; string concat `String 'compound'` and `String ' assignment''` -> `String 'compound assignment'`; store `String 'compound assignment'` to `s`; @@ -405,7 +405,7 @@ operators. <1> declare `def x`; implicit cast `int 1` to `def`; store `def` to `x`; -<2> load from `x` -> `def`; +<2> load from `x` -> `def`; implicit cast `def` to `int 1` -> `int 1`; add `int 1` and `int 2` -> `int 3`; implicit cast `int 3` to `def` -> `def`; @@ -421,7 +421,7 @@ operators. ---- <1> declare `byte b`; store `byte 1` to `x`; -<2> load from `x` -> `byte 1`; +<2> load from `x` -> `byte 1`; implicit cast `byte 1 to `int 1` -> `int 1`; add `int 1` and `int 2` -> `int 3`; implicit cast `int 3` to `byte 3` -> `byte 3`; diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 6c5563685846f..67579aefcf99d 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -4,221 +4,440 @@ [[method-call-operator]] ==== Method Call -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. +Use the *method call operator* to call a member method on a +<> value. Implicit +<> is evaluated as necessary per argument. +When a method call is made on a `def` type value, the parameters and return +type value are considered to also be of the `def` type and are evaluated at +run-time. -*Grammar:* -[source,ANTLR4] ----- -method_call: ID '.' ID '(' (expression (',' expression)*)? ')'; ----- +An overloaded method is one that shares the same name with two or more methods. +A method is overloaded based on arity where the same name is re-used for +multiple methods as long as the number of parameters differs. -*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: +*Errors* -[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. +* If the reference type value is `null`. +* If the member method name doesn't exist for a given reference type value. +* If the number of arguments passed in is different from the number of specified + parameters. +* If the arguments cannot be implicitly cast or implicitly boxed/unboxed to the + correct type values for the parameters. -Assume for a minute that the Map method arguments were described as Integers: +*Grammar* -[source,Java] ----- -put(Integer, Integer) -get(Integer) +[source,ANTLR4] ---- - -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 <>. -************************** +method_call: callable '.' ID arguments; +callable: (variable | field | type); +arguments: '(' (expression (',' expression)*)? ')'; +---- + +*Examples* + +* Uses of method calls. ++ +[source,Painless] +---- +<1> Map m = new HashMap(); +<2> m.put(1, 2); +<3> int z = m.get(1); +<4> def d = new ArrayList(); +<5> d.add(1); +<6> int i = Integer.parseInt(d.get(0).toString()); +---- ++ +<1> declare `Map m`; + allocate `HashMap` instance -> `HashMap reference`; + store `HashMap reference` to `m` +<2> load from `m` -> `Map reference`; + implicit cast `int 1` to `def` -> `def`; + implicit cast `int 2` to `def` -> `def`; + call `put` on `Map reference` with arguments (`int 1`, `int 2`) +<3> declare `int z`; + load from `m` -> `Map reference`; + call `get` on `Map reference` with arguments (`int 1`) -> `def`; + implicit cast `def` to `int 2` -> `int 2`; + store `int 2` to `z` +<4> declare `def d`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList` to `def` -> `def`; + store `def` to `d` +<5> load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference` + call `add` on `ArrayList reference` with arguments (`int 1`); +<6> declare `int i`; + load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference` + call `get` on `ArrayList reference` with arguments (`int 1`) -> `def`; + implicit cast `def` to `Integer 1 reference` -> `Integer 1 reference`; + call `toString` on `Integer 1 reference` -> `String '1'`; + call `parseInt` on `Integer` with arguments (`String '1'`) -> `int 1`; + store `int 1` in `i`; [[field-access-operator]] ==== Field Access -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; ----- +Use the *field access operator* to store a value to or load a value from a +<> member field. -*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 +*Errors* + +* If the reference type value is `null`. +* If the member field name doesn't exist for a given reference type value. + +*Grammar* + +[source,ANTLR4] ---- +field_access: accessible '.' ID; +accessible: (variable | field | type); +---- + +*Examples* + +The examples use the following reference type definition: + +---- +name: + Example + +non-static member fields: + * int x + * def y + * List z +---- + +* Uses of the *field access operator*. ++ +[source,Painless] +---- +<1> Example example = new Example(); +<2> example.x = 1; +<3> example.y = example.x; +<4> example.z = new ArrayList(); +<5> example.z.add(1); +<6> example.x = example.z.get(0); +---- ++ +<1> declare `Example example`; + allocate `Example` instance -> `Example reference`; + store `Example reference` to `example` +<2> load from `example` -> `Example reference`; + store `int 1` to `x` of `Example reference` +<3> load from `example` -> `Example reference @0`; + load from `example` -> `Example reference @1`; + load from `x` of `Example reference @1` -> `int 1`; + implicit cast `int 1` to `def` -> `def`; + store `def` to `y` of `Example reference @0`; + (note `Example reference @0` and `Example reference @1` are the same) +<4> load from `example` -> `Example reference`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `z` of `Example reference` +<5> load from `example` -> `Example reference`; + load from `z` of `Example reference` -> `List reference`; + call `add` on `List reference` with arguments (`int 1`) +<6> load from `example` -> `Example reference @0`; + load from `example` -> `Example reference @1`; + load from `z` of `Example reference @1` -> `List reference`; + call `get` on `List reference` with arguments (`int 0`) -> `int 1`; + store `int 1` in `x` of `List reference @0`; + (note `Example reference @0` and `Example reference @1` are the same) [[null-safe-operator]] ==== 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. +Use the *null safe operator* instead of the *method call operator* or *field +access operator* to ensure a reference type value is not `null` before +a method call or field access. A `null` value will be returned if the reference +type value is `null`, otherwise the method call or field access is evaluated. -// 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. +*Errors* + +* If the method call return type value or the field access type value is not + a reference type value and is not implicitly castable to a reference type + value. + +*Grammar* -*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)*)? ')'; + +null_safe_field_access: accessible '?.' ID; +accessible: (variable | field | type); + +null_safe_method_call: callable '?.' ID arguments; +callable: (variable | field | type); +arguments: '(' (expression (',' expression)*)? ')'; ---- -*Examples:* -[source,Java] +*Examples* + +The examples use the following reference type definition: + ---- -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 +name: + Example -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 +non-static member methods: + * List factory() -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 +non-static member fields: + * List x ---- +* Use of the *null safe operator* without a `null` value. ++ +[source,Painless] +---- +<1> Example example = new Example(); +<2> List x = example?.factory(); +---- ++ +<1> declare `Example example`; + allocate `Example` instance -> `Example reference`; + store `Example reference` to `example` +<2> declare `List x`; + load from `example` -> `Example reference`; + null safe call `factory` on `Example reference` -> `List reference`; + store `List reference` to `x`; ++ +* Use of the *null safe operator* with a `null` value; ++ +[source,Painless] +---- +<1> Example example = null; +<2> List x = example?.x; +---- +<1> declare `Example example`; + store `null` to `example` +<2> declare `List x`; + load from `example` -> `Example reference`; + null safe access `x` on `Example reference` -> `null`; + store `null` to `x`; + (note the *null safe operator* returned `null` because `example` is `null`) + [[list-initialization-operator]] ==== List Initialization -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. +Use the *list initialization operator* to allocate an ArrayList type value with +a set of pre-defined values. Each value used to initialize the ArrayList type +value is converted to a `def` type value when inserted into the ArrayList type +value using the `add` method. The order of specified values is maintained upon +insertion. + +*Grammar* -*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 ----- +*Examples* + +* Use of the *list initialization operator* to create an empty List type value. ++ +[source,Painless] +---- +<1> List empty = []; +---- ++ +<1> declare `List empty`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `empty` ++ +* Use of the *list initialization operator* with static values. ++ +[source,Painless] +---- +<1> List list = [1, 2, 3]; +---- ++ +<1> declare `List list`; + allocate `ArrayList` instance -> `ArrayList reference`; + call `add` on `ArrayList reference` with arguments(`int 1`); + call `add` on `ArrayList reference` with arguments(`int 2`); + call `add` on `ArrayList reference` with arguments(`int 3`); + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `list` ++ +* Use of the *list initialization operator* with non-static values. ++ +[source,Painless] +---- +<1> int i = 1; +<2> long l = 2L; +<3> float f = 3.0F; +<4> double d = 4.0; +<5> String s = "5"; +<6> List list = [i, l, f*d, s]; +---- ++ +<1> declare `int i`; + store `int 1` to `i` +<2> declare `long l`; + store `long 2` to `l` +<3> declare `float f`; + store `float 3.0` to `f` +<4> declare `double d`; + store `double 4.0` to `d` +<5> declare `String s`; + store `String "5"` to `s` +<6> declare `List list`; + allocate `ArrayList` instance -> `ArrayList reference`; + load from `i` -> `int 1`; + call `add` on `ArrayList reference` with arguments(`int 1`); + load from `l` -> `long 2`; + call `add` on `ArrayList reference` with arguments(`long 2`); + load from `f` -> `float 3.0`; + load from `d` -> `double 4.0`; + promote `float 3.0` and `double 4.0`: result `double`; + implicit cast `float 3.0` to `double 3.0` -> `double 3.0`; + multiply `double 3.0` and `double 4.0` -> `double 12.0`; + call `add` on `ArrayList reference` with arguments(`double 12.0`); + load from `s` -> `String "5"`; + call `add` on `ArrayList reference` with arguments(`String "5"`); + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `list` [[list-access-operator]] ==== List Access -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. +Use the *list access operator* as a shortcut for an `set` method call or `get` +method call made on a List type value. + +*Errors* + +* Use of the *list access operator* on a value that is not a List type value. +* Use of a non-integer type value as an index for an `set` method call or `get` + method call. + +*Grammar* -*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. +*Examples* + +* Uses of the *list access operator*. ++ +[source,Painless] +---- +<1> List list = new ArrayList(); +<2> list.add(1); +<3> list.add(2); +<4> list.add(3); +<5> list[0] = 2; +<6> list[1] = 5; +<7> int x = list[0] + list[1]; +<8> int y = 1; +<9> int z = list[y]; +---- ++ +<1> declare `List list`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `list` +<2> load from `list` -> `List reference`; + call `add` on `List reference` with arguments(`int 1`) +<3> load from `list` -> `List reference`; + call `add` on `List reference` with arguments(`int 2`) +<4> load from `list` -> `List reference`; + call `add` on `List reference` with arguments(`int 3`) +<5> load from `list` -> `List reference`; + call `set` on `List reference` with arguments(`int 0`, `int 2`) +<6> load from `list` -> `List reference`; + call `set` on `List reference` with arguments(`int 1`, `int 5`) +<7> declare `int x`; + load from `list` -> `List reference`; + call `get` on `List reference` with arguments(`int 0`); -> `def`; + implicit cast `def` to `int 2` -> `int 2`; + load from `list` -> `List reference`; + call `get` on `List reference` with arguments(`int 1`); -> `def`; + implicit cast `def` to `int 5` -> `int 5`; + add `int 2` and `int 5` -> `int 7`; + store `int 7` to `x` +<8> declare `int y`; + store `int 1` int `y` +<9> declare `int z`; + load from `list` -> `List reference`; + load from `y` -> `int 1`; + call `get` on `List reference` with arguments(`int 1`); -> `def`; + implicit cast `def` to `int 5` -> `int 5`; + store `int 5` to `z` ++ +* Uses of the *list access operator* with the `def` type. ++ +[source,Painless] +---- +<1> def d = new ArrayList(); +<2> d.add(1); +<3> d.add(2); +<4> d.add(3); +<5> d[0] = 2; +<6> d[1] = 5; +<7> def x = d[0] + d[1]; +<8> def y = 1; +<9> def z = d[y]; +---- ++ +<1> declare `List d`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `def` -> `def`; + store `def` to `d` +<2> load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `add` on `ArrayList reference` with arguments(`int 1`) +<3> load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `add` on `ArrayList reference` with arguments(`int 2`) +<4> load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `add` on `ArrayList reference` with arguments(`int 3`) +<5> load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `set` on `ArrayList reference` with arguments(`int 0`, `int 2`) +<6> load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `set` on `ArrayList reference` with arguments(`int 1`, `int 5`) +<7> declare `def x`; + load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `get` on `ArrayList reference` with arguments(`int 0`); -> `def`; + implicit cast `def` to `int 2` -> `int 2`; + load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `get` on `ArrayList reference` with arguments(`int 1`); -> `def`; + implicit cast `def` to `int 2` -> `int 2`; + add `int 2` and `int 5` -> `int 7`; + store `int 7` to `x` +<8> declare `int y`; + store `int 1` int `y` +<9> declare `int z`; + load from `d` -> `ArrayList reference`; + load from `y` -> `def`; + implicit cast `def` to `int 1` -> `int 1`; + call `get` on `ArrayList reference` with arguments(`int 1`); -> `def`; + store `def` to `z` [[map-initialization-operator]] ==== Map Initialization -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. +Use the *map initialization operator* to allocate a HashMap type value with +a set of pre-defined values. Each pair of values used to initialize the HashMap +type value are converted to `def` type values when inserted into the HashMap +type value using the `put` method. The order of specified values is maintained +upon insertion. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- map_initialization: '[' key_pair (',' key_pair)* ']' @@ -226,10 +445,10 @@ 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* + + -*Examples:* [source,Java] ---- Map empty = [:]; // declares the Map variable empty and sets it to a newly initialized empty Map diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index bafa3886616f0..6e6743a43117b 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -9,7 +9,7 @@ is evaluated. The following table lists all available operators: [cols="<6,<3,^3,^2,^4"] |==== -| *Operator* | *Category* | *Symbol(s)* | *Precedence* | *Associativity* +| *Operator* | *Category* | *Symbol(s)* | *Precedence* | *Associativity* | <> | <> | () | 0 | left -> right | <> | <> | . () | 1 | left -> right | <> | <> | . | 1 | left -> right diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index ec09e751ef725..a1f6aeec6ce58 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -155,26 +155,28 @@ reference type instance is required to use a non-static member field. static member method:: -A static member method is a function called on a reference type *object*. Use -the <> in correspondence with the -reference type object name to call a static member method. No reference type -instance allocation is necessary to use a static member method. +A static member method is a <> called on a +reference type *object*. Use the <> +in correspondence with the reference type object name to call a static member +method. No reference type instance allocation is necessary to use a static +member method. non-static member method:: -A non-static member method is a function called on a reference type *instance*. -A non-static member method called on a reference type instance can load from and -store to non-static member fields of that specific reference type instance. Use -the <> in correspondence with a -specific reference type instance to call a non-static member method. An -allocated reference type instance is required to use a non-static member method. +A non-static member method is a <> called on a +reference type *instance*. A non-static member method called on a reference type +instance can load from and store to non-static member fields of that specific +reference type instance. Use the <> +in correspondence with a specific reference type instance to call a non-static +member method. An allocated reference type instance is required to use a +non-static member method. constructor:: -A constructor is a special type of function used to allocate a reference type -*instance* defined by a specific reference type *object*. Use the -<> to allocate a reference type -instance. +A constructor is a special type of <> used to +allocate a reference type *instance* defined by a specific reference type +*object*. Use the <> to allocate +a reference type instance. A reference type object follows a basic inheritance model. Consider types A and B. Type A is considered to be a parent of B, and B a child of A, if B inherits diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 3da88ffa6ab2d..b29908635b68b 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -68,10 +68,10 @@ assignment: '=' expression; ==== Assignment Use the *assignment operator* to store a value in a variable for use in -subsequent operations. Any operation that produces a value can be assigned to -any variable as long as the <> are the same or the -resultant type can be <> to the variable -type. +subsequent operations. Any operation that produces a value is assigned to any +variable as long as the <> are the same or an +<> of the resultant type to the variable type +is possible. *Errors* From 46a868e5265859e376868c2354cf9d60a5636500 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Fri, 1 Jun 2018 18:21:16 -0700 Subject: [PATCH 39/55] Completion of clean up of reference type operators. --- .../painless-operators-general.asciidoc | 4 +- .../painless-operators-reference.asciidoc | 383 ++++++++++++++---- 2 files changed, 301 insertions(+), 86 deletions(-) diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index b4f9c8b2e3a2f..df12307636a24 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -88,7 +88,7 @@ with an expected `boolean` result type. If the first expression evaluates to evaluates to `false` then the third expression is evaluated. The second and third expressions are <> if the evaluated values are not the same type. Use the *conditional operator* as a shortcut to avoid the need -for a full if/else branch in certain expressions. +for a full if/else branch. *Errors* @@ -426,4 +426,4 @@ operators. add `int 1` and `int 2` -> `int 3`; implicit cast `int 3` to `byte 3` -> `byte 3`; store `byte 3` to `b`; - (note this is equivalent to `b = b+2`) \ No newline at end of file + (note this is equivalent to `b = b+2`) diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 67579aefcf99d..8808a3d92c13b 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -6,10 +6,10 @@ Use the *method call operator* to call a member method on a <> value. Implicit -<> is evaluated as necessary per argument. -When a method call is made on a `def` type value, the parameters and return -type value are considered to also be of the `def` type and are evaluated at -run-time. +<> is evaluated as necessary per argument +during the method call. When a method call is made on a `def` type value, the +parameters and return type value are considered to also be of the `def` type and +are evaluated at run-time. An overloaded method is one that shares the same name with two or more methods. A method is overloaded based on arity where the same name is re-used for @@ -28,8 +28,7 @@ multiple methods as long as the number of parameters differs. [source,ANTLR4] ---- -method_call: callable '.' ID arguments; -callable: (variable | field | type); +method_call: '.' ID arguments; arguments: '(' (expression (',' expression)*)? ')'; ---- @@ -90,8 +89,7 @@ Use the *field access operator* to store a value to or load a value from a [source,ANTLR4] ---- -field_access: accessible '.' ID; -accessible: (variable | field | type); +field_access: '.' ID; ---- *Examples* @@ -163,15 +161,14 @@ type value is `null`, otherwise the method call or field access is evaluated. [source,ANTLR4] ---- -null_safe: null_safe_field_access - | null_safe_method_call; +null_safe: null_safe_method_call + | null_safe_field_access + ; -null_safe_field_access: accessible '?.' ID; -accessible: (variable | field | type); - -null_safe_method_call: callable '?.' ID arguments; -callable: (variable | field | type); +null_safe_method_call: '?.' ID arguments; arguments: '(' (expression (',' expression)*)? ')'; + +null_safe_field_access: '?.' ID; ---- *Examples* @@ -239,7 +236,8 @@ list_initialization: '[' expression (',' expression)* ']' *Examples* -* Use of the *list initialization operator* to create an empty List type value. +* Use of the *list initialization operator* to create an empty ArrayList type + value. + [source,Painless] ---- @@ -308,7 +306,7 @@ list_initialization: '[' expression (',' expression)* ']' [[list-access-operator]] ==== List Access -Use the *list access operator* as a shortcut for an `set` method call or `get` +Use the *list access operator* as a shortcut for a `set` method call or `get` method call made on a List type value. *Errors* @@ -357,10 +355,10 @@ list_access: '[' expression ']' call `set` on `List reference` with arguments(`int 1`, `int 5`) <7> declare `int x`; load from `list` -> `List reference`; - call `get` on `List reference` with arguments(`int 0`); -> `def`; + call `get` on `List reference` with arguments(`int 0`) -> `def`; implicit cast `def` to `int 2` -> `int 2`; load from `list` -> `List reference`; - call `get` on `List reference` with arguments(`int 1`); -> `def`; + call `get` on `List reference` with arguments(`int 1`) -> `def`; implicit cast `def` to `int 5` -> `int 5`; add `int 2` and `int 5` -> `int 7`; store `int 7` to `x` @@ -369,7 +367,7 @@ list_access: '[' expression ']' <9> declare `int z`; load from `list` -> `List reference`; load from `y` -> `int 1`; - call `get` on `List reference` with arguments(`int 1`); -> `def`; + call `get` on `List reference` with arguments(`int 1`) -> `def`; implicit cast `def` to `int 5` -> `int 5`; store `int 5` to `z` + @@ -410,11 +408,11 @@ list_access: '[' expression ']' <7> declare `def x`; load from `d` -> `def`; implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; - call `get` on `ArrayList reference` with arguments(`int 0`); -> `def`; + call `get` on `ArrayList reference` with arguments(`int 0`) -> `def`; implicit cast `def` to `int 2` -> `int 2`; load from `d` -> `def`; implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; - call `get` on `ArrayList reference` with arguments(`int 1`); -> `def`; + call `get` on `ArrayList reference` with arguments(`int 1`) -> `def`; implicit cast `def` to `int 2` -> `int 2`; add `int 2` and `int 5` -> `int 7`; store `int 7` to `x` @@ -424,7 +422,7 @@ list_access: '[' expression ']' load from `d` -> `ArrayList reference`; load from `y` -> `def`; implicit cast `def` to `int 1` -> `int 1`; - call `get` on `ArrayList reference` with arguments(`int 1`); -> `def`; + call `get` on `ArrayList reference` with arguments(`int 1`) -> `def`; store `def` to `z` [[map-initialization-operator]] @@ -447,114 +445,331 @@ key_pair: expression ':' expression *Examples* - - -[source,Java] +* Use of the *map initialization operator* to create an empty HashMap type +value. ++ +[source,Painless] ---- -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 +<1> Map empty = [:]; ---- ++ +<1> declare `Map empty`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `Map reference` -> `Map reference`; + store `Map reference` to `empty` ++ +* Use of the *map initialization operator* with non-static values. ++ +[source,Painless] +---- +<1> Map map = [1:2, 3:4, 5:6]; +---- ++ +<1> declare `Map map`; + allocate `HashMap` instance -> `HashMap reference`; + call `put` on `HashMap reference` with arguments(`int 1`, `int 2`); + call `put` on `HashMap reference` with arguments(`int 3`, `int 4`); + call `put` on `HashMap reference` with arguments(`int 5`, `int 6`); + implicit cast `HashMap reference` to `Map reference` -> `Map reference`; + store `Map reference` to `map` ++ +* Use of the *map initialization operator* with non-static values. ++ +[source,Painless] +---- +<1> byte b = 0; +<2> int i = 1; +<3> long l = 2L; +<4> float f = 3.0F; +<5> double d = 4.0; +<6> String s = "5"; +<7> Map map = [b:i, l:f*d, d:s]; +---- ++ +<1> declare `byte b`; + store `byte 0` to `b` +<2> declare `int i`; + store `int 1` to `i` +<3> declare `long l`; + store `long 2` to `l` +<4> declare `float f`; + store `float 3.0` to `f` +<5> declare `double d`; + store `double 4.0` to `d` +<6> declare `String s`; + store `String "5"` to `s` +<7> declare `Map map`; + allocate `HashMap` instance -> `HashMap reference`; + load from `b` -> `byte 0`; + load from `i` -> `int 1`; + call `put` on `HashMap reference` with arguments(`byte 0`, `int 1`); + load from `l` -> `long 2`; + load from `f` -> `float 3.0`; + load from `d` -> `double 4.0`; + promote `float 3.0` and `double 4.0`: result `double`; + implicit cast `float 3.0` to `double 3.0` -> `double 3.0`; + multiply `double 3.0` and `double 4.0` -> `double 12.0`; + call `put` on `HashMap reference` with arguments(`long 2`, `double 12.0`); + load from `d` -> `double 4.0`; + load from `s` -> `String "5"`; + call `put` on `HashMap reference` with + arguments(`double 4.0`, `String "5"`); + implicit cast `HashMap reference` to `Map reference` -> `Map reference`; + store `Map reference` to `map` [[map-access-operator]] ==== Map Access -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. +Use the *map access operator* as a shortcut for a `put` method call or `get` +method call made on a Map type value. -*Grammar:* +*Errors* + +* Use of the *map access operator* on a value that is not a Map type value. + +*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 +*Examples* -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 +* Uses of the *map access operator*. ++ +[source,Painless] ---- - -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. +<1> Map map = new HashMap(); +<2> map['value2'] = 2; +<3> map['value5'] = 5; +<4> int x = map['value2'] + map['value5']; +<5> String y = 'value5'; +<6> int z = x[z]; +---- ++ +<1> declare `Map map`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `Map reference` -> `Map reference`; + store `Map reference` to `map` +<2> load from `map` -> `Map reference`; + call `put` on `Map reference` with arguments(`String 'value2'`, `int 2`) +<3> load from `map` -> `Map reference`; + call `put` on `Map reference` with arguments(`String 'value5'`, `int 5`) +<4> declare `int x`; + load from `map` -> `Map reference`; + call `get` on `Map reference` with arguments(`String 'value2'`) -> `def`; + implicit cast `def` to `int 2` -> `int 2`; + load from `map` -> `Map reference`; + call `get` on `Map reference` with arguments(`String 'value5'`) -> `def`; + implicit cast `def` to `int 5` -> `int 5`; + add `int 2` and `int 5` -> `int 7`; + store `int 7` to `x` +<5> declare `String y`; + store `String 'value5'` to `y` +<6> declare `int z`; + load from `map` -> `Map reference`; + load from `y` -> `String 'value5'`; + call `get` on `Map reference` with arguments(`String 'value5'`) -> `def`; + implicit cast `def` to `int 5` -> `int 5`; + store `int 5` to `z` ++ +* Uses of the *map access operator* using the `def` type. ++ +[source,Painless] +---- +<1> def d = new HashMap(); +<2> d['value2'] = 2; +<3> d['value5'] = 5; +<4> int x = d['value2'] + d['value5']; +<5> String y = 'value5'; +<6> def z = d[y]; +---- ++ +<1> declare `def d`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `def` -> `def`; + store `def` to `d` +<2> load from `d` -> `def`; + implicit cast `def` to `HashMap reference` -> `HashMap reference`; + call `put` on `HashMap reference` with arguments(`String 'value2'`, `int 2`) +<3> load from `d` -> `def`; + implicit cast `def` to `HashMap reference` -> `HashMap reference`; + call `put` on `HashMap reference` with arguments(`String 'value5'`, `int 5`) +<4> declare `int x`; + load from `d` -> `def`; + implicit cast `def` to `HashMap reference` -> `HashMap reference`; + call `get` on `HashMap reference` with arguments(`String 'value2'`) + -> `def`; + implicit cast `def` to `int 2` -> `int 2`; + load from `d` -> `def`; + call `get` on `HashMap reference` with arguments(`String 'value5'`) + -> `def`; + implicit cast `def` to `int 5` -> `int 5`; + add `int 2` and `int 5` -> `int 7`; + store `int 7` to `x` +<5> declare `String y`; + store `String 'value5'` to `y` +<6> declare `def z`; + load from `d` -> `def`; + load from `y` -> `String 'value5'`; + call `get` on `HashMap reference` with arguments(`String 'value5'`) + -> `def`; + store `def` to `z` [[new-instance-operator]] ==== New Instance -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. +Use the *new instance operator* to allocate a +<> instance to the heap and call a specified +constructor. Implicit <> is evaluated as +necessary per argument during the constructor call. + +An overloaded constructor is one that shares the same name with two or more +constructors. A constructor is overloaded based on arity where the same +reference type name is re-used for multiple constructors as long as the number +of parameters differs. + +*Errors* + +* If the reference type name doesn't exist for instance allocation. +* If the number of arguments passed in is different from the number of specified + parameters. +* If the arguments cannot be implicitly cast or implicitly boxed/unboxed to the + correct type values for the parameters. -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* -*Grammar:* [source,ANTLR4] ---- -constructor_call: 'new' TYPE '(' (expression (',' expression)*)? ')'; +new_instance: 'new' type '(' (expression (',' expression)*)? ')'; ---- -*Examples:* -[source,Java] +*Examples* + +* Uses of the *new instance operator*. + +[source,Painless] ---- -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 +<1> Map m = new HashMap(); +<2> def d = new ArrayList(); +<3> def e = new HashMap(m); ---- +<1> declare `Map m`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `Map reference` -> `Map reference`; + store `Map reference` to `m`; +<2> declare `def d`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `def` -> `def`; + store `def` to `d`; +<3> declare `def e`; + load from `m` -> `Map reference`; + allocate `HashMap` instance with arguments (`Map reference`) + -> `HashMap reference`; + implicit cast `HashMap reference` to `def` -> `def`; + store `def` to `e`; [[string-concatenation-operator]] ==== 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. +Use the *string concatenation operator* to concatenate two values together where +at least one of the values is of the <>. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- concatenate: expression '+' expression; ---- -*Examples:* -[source,Java] +*Examples* + +* Uses of the *string concatenation operator*. ++ +[source,Painless] ---- -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" +<1> String x = "con"; +<2> String y = x + "cat"; +<3> String z = 4 + 5 + x; ---- ++ +<1> declare `String x`; + store `String "con"` to `x`; +<2> declare `String y`; + load from `x` -> `String "con"`; + concat `String "con"` and `String "cat"` -> `String "concat"`; + store `String "concat"` to `y` +<3> declare `String z`; + add `int 4` and `int 5` -> `int 9`; + concat `int 9` and `String "9concat"`; + store `String "9concat"` to `z`; + (note the addition is done prior to the concatenation due to precedence and + associativity of the specific operations) ++ +* Uses of the *string concatenation operator* with the `def` type. ++ +[source,Painless] +---- +<1> def d = 2; +<2> d = "con" + d + "cat"; +---- ++ +<1> declare `def`; + implicit cast `int 2` to `def` -> `def`; + store `def` in `d`; +<2> concat `String "con"` and `int 9` -> `String "con9"`; + concat `String "con9"` and `String "con"` -> `String "con9cat"` + implicit cast `String "con9cat"` to `def` -> `def`; + store `def` to `d`; + (note the switch in type of `d` from `int` to `String`) [[elvis-operator]] ==== 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. +An elvis consists of two expressions. The first expression is evaluated +with to check for a `null` value. If the first expression evaluates to +`null` then the second expression is evaluated and its value used. If the first +expression evaluates to not `null` then the resultant value of the first +expression is used. Use the *elvis operator* as a shortcut for the *conditional +operator*. + +*Errors* + +* If the first expression or second expression cannot produce a `null` value. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- elvis: expression '?:' expression; ---- -*Examples:* -[source,Java] +*Examples* + +* Uses of the *elvis operator*. ++ +[source,Painless] ---- -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 +<1> List x = new ArrayList(); +<2> List y = x ?: new ArrayList(); +<3> y = null; +<4> List z = y ?: new ArrayList(); ---- ++ +<1> declare `List x`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `x`; +<2> declare `List y`; + load `x` -> `List reference`; + `List reference` equals `null` -> `false`; + evaluate 1st expression: `List reference` -> `List reference`; + store `List reference` to `y` +<3> store `null` to `y`; +<4> declare `List z`; + load `y` -> `List reference`; + `List reference` equals `null` -> `true`; + evaluate 2nd expression: + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `z`; From 15aac91f6e0093f09ed5b7a9816cc3893dff6491 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Fri, 1 Jun 2018 20:51:41 -0700 Subject: [PATCH 40/55] Clean up of array operators section. --- .../painless-operators-array.asciidoc | 337 +++++++++++++----- .../painless-operators-reference.asciidoc | 20 +- .../elasticsearch/painless/AdditionTests.java | 2 + 3 files changed, 261 insertions(+), 98 deletions(-) diff --git a/docs/painless/painless-operators-array.asciidoc b/docs/painless/painless-operators-array.asciidoc index 5f2e3d535046f..70a36d9ea34a6 100644 --- a/docs/painless/painless-operators-array.asciidoc +++ b/docs/painless/painless-operators-array.asciidoc @@ -4,130 +4,289 @@ [[array-initialization-operator]] ==== Array Initialization -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:* +Use the *array initialization operator* to allocate a single-dimensional +<> value with a set of pre-defined values. Each value +used to initialize the array type value is cast to the specified type value when +inserted into the array type value. The order of specified values is maintained +upon insertion. + +*Errors* + +* If a value is not castable to the specified type value. + +*Grammar* + [source,ANTLR4] ---- -declare_array: TYPE ('[' ']')+; - -array_initialization: 'new' TYPE '[' ']' '{' expression (',' expression) '}' +array_initialization: 'new' TYPE '[' ']' '{' expression_list '}' | 'new' TYPE '[' ']' '{' '}'; +expression_list: expression (',' expression); ---- -*Examples:* -[source,Java] +*Example:* + +* Use of the *array initialization operator* with static values. ++ +[source,Painless] ---- -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 +<1> int[] x = new int[] {1, 2, 3}; ---- ++ +<1> declare `int[] x`; + allocate `1-d int array` instance with `length [3]` + -> `1-d int array reference`; + store `int 1` to `index [0]` of `1-d int array reference`; + store `int 2` to `index [1]` of `1-d int array reference`; + store `int 3` to `index [2]` of `1-d int array reference`; + store `1-d int array reference` to `x`; ++ +* Use of the *array initialization operator* with non-static values. ++ +[source,Painless] +---- +<1> int i = 1; +<2> long l = 2L; +<3> float f = 3.0F; +<4> double d = 4.0; +<5> String s = "5"; +<6> def array = new def[] {i, l, f*d, s}; +---- ++ +<1> declare `int i`; + store `int 1` to `i` +<2> declare `long l`; + store `long 2` to `l` +<3> declare `float f`; + store `float 3.0` to `f` +<4> declare `double d`; + store `double 4.0` to `d` +<5> declare `String s`; + store `String "5"` to `s` +<6> declare `def array`; + allocate `1-d def array` instance with `length [4]` + -> `1-d def array reference`; + load from `i` -> `int 1`; + implicit cast `int 1` to `def` -> `def`; + store `def` to `index [0]` of `1-d def array reference`; + load from `l` -> `long 2`; + implicit cast `long 2` to `def` -> `def`; + store `def` to `index [1]` of `1-d def array reference`; + load from `f` -> `float 3.0`; + load from `d` -> `double 4.0`; + promote `float 3.0` and `double 4.0`: result `double`; + implicit cast `float 3.0` to `double 3.0` -> `double 3.0`; + multiply `double 3.0` and `double 4.0` -> `double 12.0`; + implicit cast `double 12.0` to `def` -> `def`; + store `def` to `index [2]` of `1-d def array reference`; + load from `s` -> `String "5"`; + implicit cast `String "5"` to `def` -> `def`; + store `def` to `index [3]` of `1-d def array reference`; + implicit cast `1-d int array reference` to `def` -> `def`; + store `def` to `array` [[array-access-operator]] ==== Array Access -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`. +Use the *array access operator* to store a value to or load a value from an +<> value. Each value of an array type value is accessed +with an int type value to specify the index to store/load. The range of values +within an array that are accessible is `[0, size)` where size is the number of +values specified at the time of allocation. Use a negative int type value as an +index to access an value in reverse from the end of an array type value within a +range of `[-size, -1]`. + +*Errors* -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. +* If a value other than an int type value or a value that is castable to an int + type value is provided as an index. +* If a value is accessed outside of the valid ranges. + +*Grammar* -*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 +*Examples* -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 +* Uses of the *array access operator*. ++ +[source,Painless] ---- - -NOTE: The use of the `def` type in the second example means that the types -cannot be resolved until runtime. +<1> int[] x = new int[2]; +<2> x[0] = 2; +<3> x[1] = 5; +<4> int y = x[0] + x[1]; +<5> int z = 1; +<6> int i = x[z]; +---- ++ +<1> declare `int[] x`; + allocate `1-d int array` instance with `length [2]` + -> `1-d int array reference`; + store `1-d int array reference` to `x` +<2> load from `x` -> `1-d int array reference`; + store `int 2` to `index [0]` of `1-d int array reference`; +<3> load from `x` -> `1-d int array reference`; + store `int 5` to `index [1]` of `1-d int array reference`; +<4> declare `int y`; + load from `x` -> `1-d int array reference`; + load from `index [0]` of `1-d int array reference` -> `int 2`; + load from `x` -> `1-d int array reference`; + load from `index [1]` of `1-d int array reference` -> `int 5`; + add `int 2` and `int 5` -> `int 7`; + store `int 7` to `y` +<5> declare `int z`; + store `int 1` to `z`; +<6> declare `int i`; + load from `x` -> `1-d int array reference`; + load from `z` -> `int 1`; + load from `index [1]` of `1-d int array reference` -> `int 5`; + store `int 5` to `i`; ++ +* Uses of the *array access operator* with the `def` type. ++ +[source,Painless] +---- +<1> def d = new int[2]; +<2> d[0] = 2; +<3> d[1] = 5; +<4> def x = d[0] + d[1]; +<5> def y = 1; +<6> def z = d[y]; +---- ++ +<1> declare `def d`; + allocate `1-d int array` instance with `length [2]` + -> `1-d int array reference`; + implicit cast `1-d int array reference` to `def` -> `def`; + store `def` to `d` +<2> load from `d` -> `def` + implicit cast `def` to `1-d int array reference` + -> `1-d int array reference`; + store `int 2` to `index [0]` of `1-d int array reference`; +<3> load from `d` -> `def` + implicit cast `def` to `1-d int array reference` + -> `1-d int array reference`; + store `int 5` to `index [1]` of `1-d int array reference`; +<4> declare `int x`; + load from `d` -> `def` + implicit cast `def` to `1-d int array reference` + -> `1-d int array reference`; + load from `index [0]` of `1-d int array reference` -> `int 2`; + load from `d` -> `def` + implicit cast `def` to `1-d int array reference` + -> `1-d int array reference`; + load from `index [1]` of `1-d int array reference` -> `int 5`; + add `int 2` and `int 5` -> `int 7`; + implicit cast `int 7` to `def` -> `def`; + store `def` to `x` +<5> declare `def y`; + implicit cast `int 1` to `def` -> `def`; + store `def ` to `y`; +<6> declare `int i`; + load from `d` -> `def` + implicit cast `def` to `1-d int array reference` + -> `1-d int array reference`; + load from `y` -> `def`; + implicit cast `def` to `int 1` -> `int 1`; + load from `index [1]` of `1-d int array reference` -> `int 5`; + implicit cast `int 5` to `def`; + store `def` to `z`; ++ +* Uses of the *array access operator* with a multi-dimensional array. ++ +[source,Painless] +---- +<1> int[][][] ia3 = new int[2][3][4]; +<2> ia3[1][2][3] = 99; +<3> int i = ia3[1][2][3]; +---- ++ +<1> declare `int[][][] ia`; + allocate `3-d int array` instance with length `[2, 3, 4]` + -> `3-d int array reference`; + store `3-d int array reference` to `ia3` +<2> load from `ia3` -> `3-d int array reference`; + store `int 99` to `index [1, 2, 3]` of `3-d int array reference` +<3> declare `int i`; + load from `ia3` -> `3-d int array reference`; + load from `index [1, 2, 3]` of `3-d int array reference` -> `int 99`; + store `int 99` to `i` [[array-length-operator]] ==== 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. +Array type values contain a read-only member field named `length`. The field +`length` is an int type value storing the size of the array. Use the +<> to load the field `length` +from an array type value. -*Examples:* -[source,Java] +*Examples* + +* Use of the `length` field. ++ +[source,Painless] ---- -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 +<1> int[] x = new int[10]; +<2> int l = x.length; ---- +<1> declare `int[] x`; + allocate `1-d int array` instance with `length [2]` + -> `1-d int array reference`; + store `1-d int array reference` to `x` +<2> declare `int l`; + load `x` -> `1-d int array reference`; + load `length` from `1-d int array reference` -> `int 10`; + store `int 10` to `l`; [[new-array-operator]] ==== 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. +Use the *new array operator* to allocate a new array type instance to the heap. +Specify each dimension with the `[` and `]` tokens following the type name. The +size of each dimension is specified by an int type value in between the `[` and +`]` tokens. + +*Errors* + +* If a value other than an int type value or a value that is castable to an int + type value is specified for for a dimension's size. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- new_array: 'new' TYPE ('[' expression ']')+; ---- -*Examples:* -[source,Java] +*Examples* + +* Uses of the *new array operator*. ++ +[source,Painless] +---- +<1> int[] x = new int[5]; +<2> x = new int[10]; +<3> int y = 2; +<4> def z = new def[y][y*2]; ---- -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 ----- \ No newline at end of file ++ +<1> declare `int[] x`; + allocate `1-d int array` instance with `length [5]` + -> `1-d int array reference`; + store `1-d int array reference` to `x` +<2> allocate `1-d int array` instance with `length [10]` + -> `1-d int array reference`; + store `1-d int array reference` to `x` +<3> declare `int y`; + store `int 2` to `y`; +<4> declare `def z`; + load from `y` -> `int 2 @0`; + load from `y` -> `int 2 @1`; + multiply `int 2 @1` by `int 2 @2` -> `int 4`; + allocate `2-d int array` instance with length `[2, 4]` + -> `2-d int array reference`; + implicit cast `2-d int array reference` to `def` -> `def`; + store `def` to `z`; diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 8808a3d92c13b..0d7110619172e 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -222,8 +222,8 @@ non-static member fields: Use the *list initialization operator* to allocate an ArrayList type value with a set of pre-defined values. Each value used to initialize the ArrayList type -value is converted to a `def` type value when inserted into the ArrayList type -value using the `add` method. The order of specified values is maintained upon +value is cast to a `def` type value when inserted into the ArrayList type value +using the `add` method. The order of specified values is maintained upon insertion. *Grammar* @@ -311,9 +311,11 @@ method call made on a List type value. *Errors* -* Use of the *list access operator* on a value that is not a List type value. -* Use of a non-integer type value as an index for an `set` method call or `get` - method call. +* If the *list access operator* is used on a value that is not a List type + value. +* If a value other than an int type value or a value that is castable to an int + type value is provided as an index for a `set` method call or `get` method + call. *Grammar* @@ -430,9 +432,9 @@ list_access: '[' expression ']' Use the *map initialization operator* to allocate a HashMap type value with a set of pre-defined values. Each pair of values used to initialize the HashMap -type value are converted to `def` type values when inserted into the HashMap -type value using the `put` method. The order of specified values is maintained -upon insertion. +type value are cast to `def` type values when inserted into the HashMap type +value using the `put` method. The order of specified values is maintained upon +insertion. *Grammar* @@ -641,7 +643,7 @@ of parameters differs. [source,ANTLR4] ---- -new_instance: 'new' type '(' (expression (',' expression)*)? ')'; +new_instance: 'new' TYPE '(' (expression (',' expression)*)? ')'; ---- *Examples* diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java index f124d088bf2f2..39a1223bdec20 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java @@ -24,6 +24,8 @@ public class AdditionTests extends ScriptTestCase { public void testBasics() throws Exception { + assertEquals(3.0, exec("int i = 1; long l = 2L; float f = 3.0F; " + + "double d = 4.0; String s = '5'; def array = new def[] {i, l, f*d, s}; return array[0]")); assertEquals(3.0, exec("double x = 1; byte y = 2; return x + y;")); } From f85e235e576c5f138ace1edc1392da44ecfe4899 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sat, 2 Jun 2018 11:27:26 -0700 Subject: [PATCH 41/55] Partially completed boolean operators clean up. --- docs/painless/painless-functions.asciidoc | 2 +- .../painless-operators-array.asciidoc | 22 +- .../painless-operators-boolean.asciidoc | 523 ++++++++++++++---- .../painless-operators-numeric.asciidoc | 15 +- .../painless-operators-reference.asciidoc | 4 +- 5 files changed, 433 insertions(+), 133 deletions(-) diff --git a/docs/painless/painless-functions.asciidoc b/docs/painless/painless-functions.asciidoc index 485378fa7ee32..20f3e821f1edd 100644 --- a/docs/painless/painless-functions.asciidoc +++ b/docs/painless/painless-functions.asciidoc @@ -7,7 +7,7 @@ to repeat its specific task. A parameter is a named type value available as a <> within the statement(s) of a function. A function specifies zero-to-many parameters, and when a function is called a value is specified per parameter. An argument is a value passed into a function -as the point of call. A function specifies a return type value, though if the +at the point of call. A function specifies a return type value, though if the type is <> then no value is returned. Any non-void type return value is available for use within an <> or is discarded otherwise. diff --git a/docs/painless/painless-operators-array.asciidoc b/docs/painless/painless-operators-array.asciidoc index 70a36d9ea34a6..c495136344796 100644 --- a/docs/painless/painless-operators-array.asciidoc +++ b/docs/painless/painless-operators-array.asciidoc @@ -89,16 +89,16 @@ expression_list: expression (',' expression); Use the *array access operator* to store a value to or load a value from an <> value. Each value of an array type value is accessed -with an int type value to specify the index to store/load. The range of values +with an `int` type value to specify the index to store/load. The range of values within an array that are accessible is `[0, size)` where size is the number of -values specified at the time of allocation. Use a negative int type value as an -index to access an value in reverse from the end of an array type value within a -range of `[-size, -1]`. +values specified at the time of allocation. Use a negative `int` type value as +an index to access an value in reverse from the end of an array type value +within a range of `[-size, -1]`. *Errors* -* If a value other than an int type value or a value that is castable to an int - type value is provided as an index. +* If a value other than an `int` type value or a value that is castable to an + `int` type value is provided as an index. * If a value is accessed outside of the valid ranges. *Grammar* @@ -219,7 +219,7 @@ brace_access: '[' expression ']' ==== Array Length Array type values contain a read-only member field named `length`. The field -`length` is an int type value storing the size of the array. Use the +`length` is an `int` type value storing the size of the array. Use the <> to load the field `length` from an array type value. @@ -246,13 +246,13 @@ from an array type value. Use the *new array operator* to allocate a new array type instance to the heap. Specify each dimension with the `[` and `]` tokens following the type name. The -size of each dimension is specified by an int type value in between the `[` and -`]` tokens. +size of each dimension is specified by an `int` type value in between the `[` +and `]` tokens. *Errors* -* If a value other than an int type value or a value that is castable to an int - type value is specified for for a dimension's size. +* If a value other than an `int` type value or a value that is castable to an + `int` type value is specified for for a dimension's size. *Grammar* diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc index 7a2e17ef294d4..249729cbeb17e 100644 --- a/docs/painless/painless-operators-boolean.asciidoc +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -4,185 +4,484 @@ [[boolean-not-operator]] ==== 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. +Use the *boolean not operator* to flip a `boolean` type value from `true` to +`false` or `false` to `true`. + +*Errors* + +* If a value other than a `boolean` type value or a value that is castable to a + `boolean` type value is given. + +*Truth* + +[options="header",cols="<1,<1"] +|==== +| original | result +| true | false +| false | true +|==== + +*Grammar* -*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 ----- +*Examples* + +* Uses of the *boolean not operator*. ++ +[source,Painless] +---- +<1> boolean x = !false; +<2> boolean y = !x; +---- +<1> declare `boolean x`; + boolean not `boolean false` -> `boolean true`; + store `boolean true` to `x` +<2> declare `boolean y`; + load from `x` -> `boolean true`; + boolean not `boolean true` -> `boolean false`; + store `boolean false` to `y` ++ +* Uses of the *boolean not operator* with the `def` type. ++ +[source,Painless] +---- +<1> def y = true; +<2> def z = !y; +---- ++ +<1> declare `def y`; + implicit cast `boolean true` to `def` -> `def`; + store `true` to `y` +<2> declare `def z`; + load from `y` -> `def`; + implicit cast `def` to `boolean true` -> boolean `true`; + boolean not `boolean true` -> `boolean false`; + implicit cast `boolean false` to `def` -> `def`; + store `def` to `z` [[greater-than-operator]] ==== 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. +Use the *greater than operator* to compare two numeric type values where a +resultant `boolean` type value is `true` if the left-hand side value is greater +than to the right-hand side value and `false` otherwise. + +*Errors* + +* If either the evaluated left-hand side or the evaluated right-hand side is a + non-numeric value. + +*Grammar* -*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* -Promotion Table: +[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 +| | 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) ----- +*Examples* + +* Uses of the *greater than operator*. ++ +[source,Painless] +---- +<1> boolean x = 5 > 4; +<2> double y = 6.0; +<3> x = 6 > y; +---- ++ +<1> declare `boolean x`; + greater than `int 5` and `int 4` -> `boolean true`; + store `boolean true` to `x`; +<2> declare `double y`; + store `double 6.0` to `y`; +<3> load from `y` -> `double 6.0 @0`; + promote `int 6` and `double 6.0`: result `double`; + implicit cast `int 6` to `double 6.0 @1` -> `double 6.0 @1`; + greater than `double 6.0 @1` and `double 6.0 @0` -> `boolean false`; + store `boolean false` to `x` ++ +* Uses of the *greater than operator* with the `def` type. ++ +[source,Painless] +---- +<1> int x = 5; +<2> def y = 7.0; +<3> def z = y > 6.5; +<4> def a = x > y; +---- ++ +<1> declare `int x`; + store `int 5` to `x` +<2> declare `def y`; + implicit cast `double 7.0` to `def` -> `def`; + store `def` to `y` +<3> declare `def z`; + load from `y` -> `def`; + implicit cast `def` to `double 7.0` -> `double 7.0`; + greater than `double 7.0` and `double 6.5` -> `boolean true`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `z` +<4> declare `def a`; + load from `y` -> `def`; + implicit cast `def` to `double 7.0` -> `double 7.0`; + load from `x` -> `int 5`; + promote `int 5` and `double 7.0`: result `double`; + implicit cast `int 5` to `double 5.0` -> `double 5.0`; + greater than `double 5.0` and `double 7.0` -> `boolean false`; + implicit cast `boolean false` to `def` -> `def`; + store `def` to `z` [[greater-than-or-equal-operator]] ==== 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. +Use the *greater than or equal operator* to compare two numeric type values +where a resultant `boolean` type value is `true` if the left-hand side value is +greater than or equal to the right-hand side value and `false` otherwise. + +*Errors* + +* If either the evaluated left-hand side or the evaluated right-hand side is a + non-numeric value. + +*Grammar* -*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* -Promotion Table: +[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 +| | 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) ----- +*Examples* + +* Uses of the *greater than or equal operator*. ++ +[source,Painless] +---- +<1> boolean x = 5 >= 4; +<2> double y = 6.0; +<3> x = 6 >= y; +---- ++ +<1> declare `boolean x`; + greater than or equal `int 5` and `int 4` -> `boolean true`; + store `boolean true` to `x` +<2> declare `double y`; + store `double 6.0` to `y` +<3> load from `y` -> `double 6.0 @0`; + promote `int 6` and `double 6.0`: result `double`; + implicit cast `int 6` to `double 6.0 @1` -> `double 6.0 @1`; + greater than or equal `double 6.0 @1` and `double 6.0 @0` -> `boolean true`; + store `boolean true` to `x` ++ +* Uses of the *greater than operator or equal* with the `def` type. ++ +[source,Painless] +---- +<1> int x = 5; +<2> def y = 7.0; +<3> def z = y >= 7.0; +<4> def a = x >= y; +---- ++ +<1> declare `int x`; + store `int 5` to `x`; +<2> declare `def y` + implicit cast `double 7.0` to `def` -> `def`; + store `def` to `y` +<3> declare `def z`; + load from `y` -> `def`; + implicit cast `def` to `double 7.0 @0` -> `double 7.0 @0`; + greater than or equal `double 7.0 @0` and `double 7.0 @1` -> `boolean true`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `z` +<4> declare `def a`; + load from `y` -> `def`; + implicit cast `def` to `double 7.0` -> `double 7.0`; + load from `x` -> `int 5`; + promote `int 5` and `double 7.0`: result `double`; + implicit cast `int 5` to `double 5.0` -> `double 5.0`; + greater than or equal `double 5.0` and `double 7.0` -> `boolean false`; + implicit cast `boolean false` to `def` -> `def`; + store `def` to `z` [[less-than-operator]] ==== 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. +Use the *less than operator* to compare two numeric type values where a +resultant `boolean` type value is `true` if the left-hand side value is less +than to the right-hand side value and `false` otherwise. + +*Errors* + +* If either the evaluated left-hand side or the evaluated right-hand side is a + non-numeric value. + +*Grammar* -*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* -Promotion Table: +[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 +| | 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) ----- +*Examples* + +* Uses of the *less than operator*. ++ +[source,Painless] +---- +<1> boolean x = 5 < 4; +<2> double y = 6.0; +<3> x = 6 < y; +---- ++ +<1> declare `boolean x`; + less than `int 5` and `int 4` -> `boolean false`; + store `boolean false` to `x` +<2> declare `double y`; + store `double 6.0` to `y` +<3> load from `y` -> `double 6.0 @0`; + promote `int 6` and `double 6.0`: result `double`; + implicit cast `int 6` to `double 6.0 @1` -> `double 6.0 @1`; + less than `double 6.0 @1` and `double 6.0 @0` -> `boolean false`; + store `boolean false` to `x` ++ +* Uses of the *less than operator* with the `def` type. ++ +[source,Painless] +---- +<1> int x = 5; +<2> def y = 7.0; +<3> def z = y < 6.5; +<4> def a = x < y; +---- ++ +<1> declare `int x`; + store `int 5` to `x` +<2> declare `def y`; + implicit cast `double 7.0` to `def` -> `def`; + store `def` to `y` +<3> declare `def z`; + load from `y` -> `def`; + implicit cast `def` to `double 7.0` -> `double 7.0`; + less than `double 7.0` and `double 6.5` -> `boolean false`; + implicit cast `boolean false` to `def` -> `def`; + store `def` to `z` +<4> declare `def a`; + load from `y` -> `def`; + implicit cast `def` to `double 7.0` -> `double 7.0`; + load from `x` -> `int 5`; + promote `int 5` and `double 7.0`: result `double`; + implicit cast `int 5` to `double 5.0` -> `double 5.0`; + less than `double 5.0` and `double 7.0` -> `boolean true`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `z` [[less-than-or-equal-operator]] ==== 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. +Use the *less than or equal operator* to compare two numeric type values +where a resultant `boolean` type value is `true` if the left-hand side value is +less than or equal to the right-hand side value and `false` otherwise. + +*Errors* + +* If either the evaluated left-hand side or the evaluated right-hand side is a + non-numeric value. + +*Grammar* -*Grammar:* [source,ANTLR4] ---- -less_than_or_equal: expression '<=' expression; +greater_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* -Promotion Table: +[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 +| | 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-operator]] -==== 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. +*Examples* + +* Uses of the *less than or equal operator*. ++ +[source,Painless] +---- +<1> boolean x = 5 <= 4; +<2> double y = 6.0; +<3> x = 6 <= y; +---- ++ +<1> declare `boolean x`; + less than or equal `int 5` and `int 4` -> `boolean false`; + store `boolean true` to `x` +<2> declare `double y`; + store `double 6.0` to `y` +<3> load from `y` -> `double 6.0 @0`; + promote `int 6` and `double 6.0`: result `double`; + implicit cast `int 6` to `double 6.0 @1` -> `double 6.0 @1`; + less than or equal `double 6.0 @1` and `double 6.0 @0` -> `boolean true`; + store `boolean true` to `x` ++ +* Uses of the *less than operator or equal* with the `def` type. ++ +[source,Painless] +---- +<1> int x = 5; +<2> def y = 7.0; +<3> def z = y <= 7.0; +<4> def a = x <= y; +---- ++ +<1> declare `int x`; + store `int 5` to `x`; +<2> declare `def y`; + implicit cast `double 7.0` to `def` -> `def`; + store `def` to `y`; +<3> declare `def z`; + load from `y` -> `def`; + implicit cast `def` to `double 7.0 @0` -> `double 7.0 @0`; + less than or equal `double 7.0 @0` and `double 7.0 @1` -> `boolean true`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `z` +<4> declare `def a`; + load from `y` -> `def`; + implicit cast `def` to `double 7.0` -> `double 7.0`; + load from `x` -> `int 5`; + promote `int 5` and `double 7.0`: result `double`; + implicit cast `int 5` to `double 5.0` -> `double 5.0`; + less than or equal `double 5.0` and `double 7.0` -> `boolean true`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `z` + +[[instanceof-operator]] +==== Instanceof + +Use the *instanceof operator* to compare the variable/field type to a +specified reference type using the reference type name where a resultant +`boolean` type value is `true` if the variable/field type is the same as or a +descendant of the specified reference type and false otherwise. + +*Errors* + +* If the reference type name doesn't exist as specified by the right-hand side. + +*Grammar* -*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 ----- +*Examples* + +* Uses of the *instanceof operator*. ++ +[source,Painless] +---- +<1> Map m = new HashMap(); +<2> boolean a = m instanceof HashMap; +<3> boolean b = m instanceof Map; +---- ++ +<1> declare `Map m`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `Map reference`; + store `Map reference` to `m` +<2> declare `boolean a`; + load from `m` -> `Map reference`; + implicit cast `Map reference` to `HashMap reference` -> `HashMap reference`; + instanceof `HashMap reference` and `HashMap` -> `true`; + store `true` to `a` +<3> declare `boolean b`; + load from `m` -> `Map reference`; + implicit cast `Map reference` to `HashMap reference` -> `HashMap reference`; + instanceof `HashMap reference` and `Map` -> `true`; + store `true` to `b`; + (note `HashMap` is a descendant of `Map`) ++ +* Uses of the *instanceof operator* with the `def` type. ++ +[source,Painless] +---- +<1> def d = new ArrayList(); +<2> boolean a = d instanceof List; +<3> boolean b = d instanceof Map; +---- ++ +<1> declare `def d`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `def` -> `def`; + store `def` to `d` +<2> declare `boolean a`; + load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + instanceof `ArrayList reference` and `List` -> `true`; + store `true` to `a`; + (note `ArrayList` is a descendant of `List`) +<3> declare `boolean b`; + load from `d` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + instanceof `ArrayList reference` and `Map` -> `false`; + store `false` to `a`; + (note `ArrayList` is not a descendant of `Map`) [[equality-equals-operator]] ==== Equality Equals diff --git a/docs/painless/painless-operators-numeric.asciidoc b/docs/painless/painless-operators-numeric.asciidoc index bc31cfbc496e3..f4a2762302c8a 100644 --- a/docs/painless/painless-operators-numeric.asciidoc +++ b/docs/painless/painless-operators-numeric.asciidoc @@ -446,7 +446,7 @@ if a bit is `1` it becomes `0` and if a bit is `0` it becomes `1`. *Bits* -[options="header",cols="^1,^1,"] +[options="header",cols="<1,<1"] |==== | original | result | 1 | 0 @@ -881,7 +881,7 @@ side integer type value. *Errors* * If either of the evaluated values is a non-integer type. -* If the evaluated right-hand side value cannot be cast to an int type. +* If the evaluated right-hand side value cannot be cast to an `int` type. *Grammar* @@ -894,7 +894,7 @@ left_shift: expression '<<' expression; 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. +`int` type value and truncated to the number of bits of the promoted type value. [options="header",cols="<1,<1"] |==== @@ -956,7 +956,7 @@ type value is preserved. *Errors* * If either of the evaluated values is a non-integer type. -* If the evaluated right-hand side value cannot be cast to an int type. +* If the evaluated right-hand side value cannot be cast to an `int` type. *Grammar* @@ -969,7 +969,7 @@ right_shift: expression '>>' expression; 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. +`int` type value and truncated to the number of bits of the promoted type value. [options="header",cols="<1,<1"] |==== @@ -1031,7 +1031,8 @@ integer type value is *not* preserved. *Errors* * If either of the evaluated values is a non-integer type. -* If the evaluated right-hand side value cannot be cast to an int type. +* If the evaluated right-hand side is a value other than an `int` type value or + a value that is castable to an `int` type value. *Grammar* @@ -1044,7 +1045,7 @@ unsigned_right_shift: expression '>>>' expression; 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. +`int` type value and truncated to the number of bits of the promoted type value. [options="header",cols="<1,<1"] |==== diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 0d7110619172e..dd24bf31fde28 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -313,8 +313,8 @@ method call made on a List type value. * If the *list access operator* is used on a value that is not a List type value. -* If a value other than an int type value or a value that is castable to an int - type value is provided as an index for a `set` method call or `get` method +* If a value other than an `int` type value or a value that is castable to an + `int` type value is given as an index for a `set` method call or `get` method call. *Grammar* From 6f160580a609052791627ef5b277177fce6f8498 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sat, 2 Jun 2018 12:50:04 -0700 Subject: [PATCH 42/55] More clean up. --- .../painless-operators-boolean.asciidoc | 461 ++++++++++++++---- .../painless-operators-reference.asciidoc | 8 +- docs/painless/painless-operators.asciidoc | 2 +- .../elasticsearch/painless/AdditionTests.java | 3 +- 4 files changed, 377 insertions(+), 97 deletions(-) diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc index 249729cbeb17e..9759af457a91e 100644 --- a/docs/painless/painless-operators-boolean.asciidoc +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -486,124 +486,405 @@ instance_of: ID 'instanceof' TYPE; [[equality-equals-operator]] ==== 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. +Use the *equality equals operator* to compare two values where a resultant +`boolean` type value is `true` if the two expressions are equal and `false` +otherwise. The member method, `equals`, is implicitly called when the values are +reference type values where the first value is the target of the call and the +second value is the argument. This operation is null-safe where if both values +are `null` the resultant `boolean` type value is `true`, and if only one value +is `null` the resultant `boolean` type value is `false`. A valid comparison is +between boolean type values, numeric type values, or reference type values. + +*Errors* + +* If a comparison is made between a `boolean` type value and numeric type value. +* If a comparison is made between a primitive type value and a reference type + value. + +*Grammar* -*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* -Promotion Table: +[cols="<1,^1,^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 +| | boolean | byte | short | char | int | long | float | double | Reference | def +| boolean | boolean | - | - | - | - | - | - | - | - | 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 +| Reference | - | - | - | - | - | - | - | - | Object | def +| def | 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 +*Examples* -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 +* Uses of the *equality equals operator* with `boolean` type values. ++ +[source,Painless] +---- +<1> boolean a = true; +<2> boolean b = false; +<3> a = a == false; +<4> b = a == b; +---- ++ +<1> declare `boolean a`; + store `boolean true` to `a` +<2> declare `boolean b`; + store `boolean false` to `b` +<3> load from `a` -> `boolean true`; + equality equals `boolean true` and `boolean false` -> `boolean false`; + store `boolean false` to `a` +<4> load from `a` -> `boolean false @0`; + load from `b` -> `boolean false @1`; + equality equals `boolean false @0` and `boolean false @1` + -> `boolean false`; + store `boolean false` to `b` ++ +* Uses of the *equality equals operator* with primitive type values. ++ +[source,Painless] +---- +<1> int a = 1; +<2> double b = 2.0; +<3> boolean c = a == b; +<4> c = 1 == a; +---- ++ +<1> declare `int a`; + store `int 1` to `a` +<2> declare `double b`; + store `double 1.0` to `b` +<3> declare `boolean c`; + load from `a` -> `int 1`; + load from `b` -> `double 2.0`; + promote `int 1` and `double 2.0`: result `double`; + implicit cast `int 1` to `double 1.0` -> `double `1.0`; + equality equals `double 1.0` and `double 2.0` -> `boolean false`; + store `boolean false` to `c` +<4> load from `a` -> `int 1 @1`; + equality equals `int 1 @0` and `int 1 @1` -> `boolean true`; + store `boolean true` to `c` ++ +* Uses of the *equality equals operator* with reference type values. ++ +[source,Painless] +---- +<1> List a = new ArrayList(); +<2> List b = new ArrayList(); +<3> a.add(1); +<4> boolean c = a == b; +<5> b.add(1); +<6> c = a == b; ---- ++ +<1> declare `List a`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `a` +<2> declare `List b`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `b` +<3> load from `a` -> `List reference`; + call `add` on `List reference` with arguments (`int 1)` +<4> declare `boolean c`; + load from `a` -> `List reference @0`; + load from `b` -> `List reference @1`; + call `equals` on `List reference @0` with arguments (`List reference @1`) + -> `boolean false`; + store `false` to `c` +<5> load from `b` -> `List reference`; + call `add` on `List reference` with arguments (`int 1`) +<6> load from `a` -> `List reference @0`; + load from `b` -> `List reference @1`; + call `equals` on `List reference @0` with arguments (`List reference @1`) + -> `boolean true`; + store `boolean true` to `c` ++ +* Uses of the *equality equals operator* with `null` values. ++ +[source,Painless] +---- +<1> Object a = null; +<2> Object b = null; +<3> boolean c = a == null; +<4> c = a == b; +<5> b = new Object(); +<6> c = a == b; +---- ++ +<1> declare `Object a`; + store `null` to `a` +<2> declare `Object b`; + store `null` to `b` +<3> declare `boolean c`; + load from `a` -> `null @0`; + equality equals `null @0` and `null @1` -> `boolean true`; + store `boolean true` to `c` +<4> load from `a` -> `null @0`; + load from `b` -> `null @1`; + equality equals `null @0` and `null @1` -> `boolean true`; + store `boolean true` to `c` +<5> allocate `Object` instance -> `Object reference`; + store `Object reference` to `b` +<6> load from `a` -> `Object reference`; + load from `b` -> `null`; + call `equals` on `Object reference` with arguments (`null`) + -> `boolean false`; + store `boolean false` to `c` ++ +* Uses of the *equality equals operator* with the `def` type. ++ +[source, Painless] +---- +<1> def a = 0; +<2> def b = 1; +<3> boolean c = a == b; +<4> def d = new HashMap(); +<5> def e = new ArrayList(); +<6> c = d == e; +---- ++ +<1> declare `def a`; + implicit cast `int 0` to `def` -> `def`; + store `def` to `a`; +<2> declare `def b`; + implicit cast `int 1` to `def` -> `def`; + store `def` to `b`; +<3> declare `boolean c`; + load from `a` -> `def`; + implicit cast `a` to `int 0` -> `int 0`; + load from `b` -> `def`; + implicit cast `b` to `int 1` -> `int 1`; + equality equals `int 0` and `int 1` -> `boolean false`; + store `boolean false` to `c` +<4> declare `def d`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `def` -> `def` + store `def` to `d`; +<5> declare `def e`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `def` -> `def` + store `def` to `d`; +<6> load from `d` -> `def`; + implicit cast `def` to `HashMap reference` -> `HashMap reference`; + load from `e` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `equals` on `HashMap reference` with arguments (`ArrayList reference`) + -> `boolean false`; + store `boolean false` to `c` [[equality-not-equals-operator]] ==== 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. +Use the *equality not equals operator* to compare two values where a resultant +`boolean` type value is `true` if the two expressions are not equal and `false` +otherwise. The member method, `equals`, is implicitly called when the values are +reference type values where the first value is the target of the call and the +second value is the argument with the resultant `boolean` type value flipped. +This operation is null-safe where if both values are `null` the resultant +`boolean` type value is `false`, and if only one value is `null` the resultant +`boolean` type value is `true`. A valid comparison is between boolean type +values, numeric type values, or reference type values. + +*Errors* + +* If a comparison is made between a `boolean` type value and numeric type value. +* If a comparison is made between a primitive type value and a reference type + value. + +*Grammar* -*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* -Promotion Table: +[cols="<1,^1,^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 +| | boolean | byte | short | char | int | long | float | double | Reference | def +| boolean | boolean | - | - | - | - | - | - | - | - | 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 +| Reference | - | - | - | - | - | - | - | - | Object | def +| def | 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 +*Examples* -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 +* Uses of the *equality equals operator* with `boolean` type values. ++ +[source,Painless] +---- +<1> boolean a = true; +<2> boolean b = false; +<3> a = a == false; +<4> b = a == b; +---- ++ +<1> declare `boolean a`; + store `boolean true` to `a` +<2> declare `boolean b`; + store `boolean false` to `b` +<3> load from `a` -> `boolean true`; + equality equals `boolean true` and `boolean false` -> `boolean false`; + store `boolean false` to `a` +<4> load from `a` -> `boolean false @0`; + load from `b` -> `boolean false @1`; + equality equals `boolean false @0` and `boolean false @1` + -> `boolean false`; + store `boolean false` to `b` ++ +* Uses of the *equality equals operator* with primitive type values. ++ +[source,Painless] +---- +<1> int a = 1; +<2> double b = 2.0; +<3> boolean c = a == b; +<4> c = 1 == a; +---- ++ +<1> declare `int a`; + store `int 1` to `a` +<2> declare `double b`; + store `double 1.0` to `b` +<3> declare `boolean c`; + load from `a` -> `int 1`; + load from `b` -> `double 2.0`; + promote `int 1` and `double 2.0`: result `double`; + implicit cast `int 1` to `double 1.0` -> `double `1.0`; + equality equals `double 1.0` and `double 2.0` -> `boolean false`; + store `boolean false` to `c` +<4> load from `a` -> `int 1 @1`; + equality equals `int 1 @0` and `int 1 @1` -> `boolean true`; + store `boolean true` to `c` ++ +* Uses of the *equality equals operator* with reference type values. ++ +[source,Painless] +---- +<1> List a = new ArrayList(); +<2> List b = new ArrayList(); +<3> a.add(1); +<4> boolean c = a == b; +<5> b.add(1); +<6> c = a == b; ---- ++ +<1> declare `List a`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `a` +<2> declare `List b`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `b` +<3> load from `a` -> `List reference`; + call `add` on `List reference` with arguments (`int 1)` +<4> declare `boolean c`; + load from `a` -> `List reference @0`; + load from `b` -> `List reference @1`; + call `equals` on `List reference @0` with arguments (`List reference @1`) + -> `boolean false`; + store `false` to `c` +<5> load from `b` -> `List reference`; + call `add` on `List reference` with arguments (`int 1`) +<6> load from `a` -> `List reference @0`; + load from `b` -> `List reference @1`; + call `equals` on `List reference @0` with arguments (`List reference @1`) + -> `boolean true`; + store `boolean true` to `c` ++ +* Uses of the *equality equals operator* with `null` values. ++ +[source,Painless] +---- +<1> Object a = null; +<2> Object b = null; +<3> boolean c = a == null; +<4> c = a == b; +<5> b = new Object(); +<6> c = a == b; +---- ++ +<1> declare `Object a`; + store `null` to `a` +<2> declare `Object b`; + store `null` to `b` +<3> declare `boolean c`; + load from `a` -> `null @0`; + equality equals `null @0` and `null @1` -> `boolean true`; + store `boolean true` to `c` +<4> load from `a` -> `null @0`; + load from `b` -> `null @1`; + equality equals `null @0` and `null @1` -> `boolean true`; + store `boolean true` to `c` +<5> allocate `Object` instance -> `Object reference`; + store `Object reference` to `b` +<6> load from `a` -> `Object reference`; + load from `b` -> `null`; + call `equals` on `Object reference` with arguments (`null`) + -> `boolean false`; + store `boolean false` to `c` ++ +* Uses of the *equality equals operator* with the `def` type. ++ +[source, Painless] +---- +<1> def a = 0; +<2> def b = 1; +<3> boolean c = a == b; +<4> def d = new HashMap(); +<5> def e = new ArrayList(); +<6> c = d == e; +---- ++ +<1> declare `def a`; + implicit cast `int 0` to `def` -> `def`; + store `def` to `a`; +<2> declare `def b`; + implicit cast `int 1` to `def` -> `def`; + store `def` to `b`; +<3> declare `boolean c`; + load from `a` -> `def`; + implicit cast `a` to `int 0` -> `int 0`; + load from `b` -> `def`; + implicit cast `b` to `int 1` -> `int 1`; + equality equals `int 0` and `int 1` -> `boolean false`; + store `boolean false` to `c` +<4> declare `def d`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `def` -> `def` + store `def` to `d`; +<5> declare `def e`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `def` -> `def` + store `def` to `d`; +<6> load from `d` -> `def`; + implicit cast `def` to `HashMap reference` -> `HashMap reference`; + load from `e` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + call `equals` on `HashMap reference` with arguments (`ArrayList reference`) + -> `boolean false`; + store `boolean false` to `c` [[identity-equals-operator]] ==== Identity Equals diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index dd24bf31fde28..f9fb4c4c60cfd 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -4,12 +4,12 @@ [[method-call-operator]] ==== Method Call -Use the *method call operator* to call a member method on a +Use the *method call operator* to call a member method on a target <> value. Implicit <> is evaluated as necessary per argument -during the method call. When a method call is made on a `def` type value, the -parameters and return type value are considered to also be of the `def` type and -are evaluated at run-time. +during the method call. When a method call is made on a target `def` type value, +the parameters and return type value are considered to also be of the `def` type +and are evaluated at run-time. An overloaded method is one that shares the same name with two or more methods. A method is overloaded based on arity where the same name is re-used for diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index 6e6743a43117b..42c11707b6b82 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -46,7 +46,7 @@ is evaluated. The following table lists all available operators: | <> | <> | >= | 7 | left -> right | <> | <> | < | 7 | left -> right | <> | <> | <= | 7 | left -> right -| <> | <> | instanceof | 8 | left -> right +| <> | <> | instanceof | 8 | left -> right | <> | <> | == | 9 | left -> right | <> | <> | != | 9 | left -> right | <> | <> | === | 9 | left -> right diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java index 39a1223bdec20..86de8b7242107 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java @@ -24,8 +24,7 @@ public class AdditionTests extends ScriptTestCase { public void testBasics() throws Exception { - assertEquals(3.0, exec("int i = 1; long l = 2L; float f = 3.0F; " + - "double d = 4.0; String s = '5'; def array = new def[] {i, l, f*d, s}; return array[0]")); + assertEquals(false, exec("HashMap x = null; ArrayList y = null; x == y")); assertEquals(3.0, exec("double x = 1; byte y = 2; return x + y;")); } From 775cfff69282b96165cb359225d9d1cb241e7e7b Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sat, 2 Jun 2018 13:24:25 -0700 Subject: [PATCH 43/55] More clean up. --- .../painless-operators-boolean.asciidoc | 430 ++++++++++++------ 1 file changed, 301 insertions(+), 129 deletions(-) diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc index 9759af457a91e..ff7650e698972 100644 --- a/docs/painless/painless-operators-boolean.asciidoc +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -448,12 +448,12 @@ instance_of: ID 'instanceof' TYPE; <2> declare `boolean a`; load from `m` -> `Map reference`; implicit cast `Map reference` to `HashMap reference` -> `HashMap reference`; - instanceof `HashMap reference` and `HashMap` -> `true`; - store `true` to `a` + instanceof `HashMap reference` and `HashMap` -> `boolean true`; + store `boolean true` to `a` <3> declare `boolean b`; load from `m` -> `Map reference`; implicit cast `Map reference` to `HashMap reference` -> `HashMap reference`; - instanceof `HashMap reference` and `Map` -> `true`; + instanceof `HashMap reference` and `Map` -> `boolean true`; store `true` to `b`; (note `HashMap` is a descendant of `Map`) + @@ -473,21 +473,21 @@ instance_of: ID 'instanceof' TYPE; <2> declare `boolean a`; load from `d` -> `def`; implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; - instanceof `ArrayList reference` and `List` -> `true`; - store `true` to `a`; + instanceof `ArrayList reference` and `List` -> `boolean true`; + store `boolean true` to `a`; (note `ArrayList` is a descendant of `List`) <3> declare `boolean b`; load from `d` -> `def`; implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; - instanceof `ArrayList reference` and `Map` -> `false`; - store `false` to `a`; + instanceof `ArrayList reference` and `Map` -> `boolean false`; + store `boolean false` to `a`; (note `ArrayList` is not a descendant of `Map`) [[equality-equals-operator]] ==== Equality Equals Use the *equality equals operator* to compare two values where a resultant -`boolean` type value is `true` if the two expressions are equal and `false` +`boolean` type value is `true` if the two values are equal and `false` otherwise. The member method, `equals`, is implicitly called when the values are reference type values where the first value is the target of the call and the second value is the argument. This operation is null-safe where if both values @@ -602,7 +602,7 @@ equality_equals: expression '==' expression; load from `b` -> `List reference @1`; call `equals` on `List reference @0` with arguments (`List reference @1`) -> `boolean false`; - store `false` to `c` + store `boolean false` to `c` <5> load from `b` -> `List reference`; call `add` on `List reference` with arguments (`int 1`) <6> load from `a` -> `List reference @0`; @@ -688,7 +688,7 @@ equality_equals: expression '==' expression; ==== Equality Not Equals Use the *equality not equals operator* to compare two values where a resultant -`boolean` type value is `true` if the two expressions are not equal and `false` +`boolean` type value is `true` if the two values are not equal and `false` otherwise. The member method, `equals`, is implicitly called when the values are reference type values where the first value is the target of the call and the second value is the argument with the resultant `boolean` type value flipped. @@ -729,14 +729,14 @@ equality_not_equals: expression '!=' expression; *Examples* -* Uses of the *equality equals operator* with `boolean` type values. +* Uses of the *equality not equals operator* with `boolean` type values. + [source,Painless] ---- <1> boolean a = true; <2> boolean b = false; -<3> a = a == false; -<4> b = a == b; +<3> a = a != false; +<4> b = a != b; ---- + <1> declare `boolean a`; @@ -744,22 +744,21 @@ equality_not_equals: expression '!=' expression; <2> declare `boolean b`; store `boolean false` to `b` <3> load from `a` -> `boolean true`; - equality equals `boolean true` and `boolean false` -> `boolean false`; - store `boolean false` to `a` -<4> load from `a` -> `boolean false @0`; - load from `b` -> `boolean false @1`; - equality equals `boolean false @0` and `boolean false @1` - -> `boolean false`; - store `boolean false` to `b` + equality not equals `boolean true` and `boolean false` -> `boolean true`; + store `boolean true` to `a` +<4> load from `a` -> `boolean true`; + load from `b` -> `boolean false`; + equality not equals `boolean true` and `boolean false` -> `boolean true`; + store `boolean true` to `b` + -* Uses of the *equality equals operator* with primitive type values. +* Uses of the *equality not equals operator* with primitive type values. + [source,Painless] ---- <1> int a = 1; <2> double b = 2.0; -<3> boolean c = a == b; -<4> c = 1 == a; +<3> boolean c = a != b; +<4> c = 1 != a; ---- + <1> declare `int a`; @@ -771,13 +770,13 @@ equality_not_equals: expression '!=' expression; load from `b` -> `double 2.0`; promote `int 1` and `double 2.0`: result `double`; implicit cast `int 1` to `double 1.0` -> `double `1.0`; - equality equals `double 1.0` and `double 2.0` -> `boolean false`; - store `boolean false` to `c` -<4> load from `a` -> `int 1 @1`; - equality equals `int 1 @0` and `int 1 @1` -> `boolean true`; + equality not equals `double 1.0` and `double 2.0` -> `boolean true`; store `boolean true` to `c` +<4> load from `a` -> `int 1 @1`; + equality not equals `int 1 @0` and `int 1 @1` -> `boolean false`; + store `boolean false` to `c` + -* Uses of the *equality equals operator* with reference type values. +* Uses of the *equality not equals operator* with reference type values. + [source,Painless] ---- @@ -804,16 +803,18 @@ equality_not_equals: expression '!=' expression; load from `b` -> `List reference @1`; call `equals` on `List reference @0` with arguments (`List reference @1`) -> `boolean false`; - store `false` to `c` + boolean not `boolean false` -> `boolean true` + store `boolean true` to `c` <5> load from `b` -> `List reference`; call `add` on `List reference` with arguments (`int 1`) <6> load from `a` -> `List reference @0`; load from `b` -> `List reference @1`; call `equals` on `List reference @0` with arguments (`List reference @1`) -> `boolean true`; - store `boolean true` to `c` + boolean not `boolean true` -> `boolean false`; + store `boolean false` to `c` + -* Uses of the *equality equals operator* with `null` values. +* Uses of the *equality not equals operator* with `null` values. + [source,Painless] ---- @@ -831,21 +832,22 @@ equality_not_equals: expression '!=' expression; store `null` to `b` <3> declare `boolean c`; load from `a` -> `null @0`; - equality equals `null @0` and `null @1` -> `boolean true`; - store `boolean true` to `c` + equality not equals `null @0` and `null @1` -> `boolean false`; + store `boolean false` to `c` <4> load from `a` -> `null @0`; load from `b` -> `null @1`; - equality equals `null @0` and `null @1` -> `boolean true`; - store `boolean true` to `c` + equality not equals `null @0` and `null @1` -> `boolean false`; + store `boolean false` to `c` <5> allocate `Object` instance -> `Object reference`; store `Object reference` to `b` <6> load from `a` -> `Object reference`; load from `b` -> `null`; call `equals` on `Object reference` with arguments (`null`) -> `boolean false`; - store `boolean false` to `c` + boolean not `boolean false` -> `boolean true`; + store `boolean true` to `c` + -* Uses of the *equality equals operator* with the `def` type. +* Uses of the *equality not equals operator* with the `def` type. + [source, Painless] ---- @@ -889,126 +891,296 @@ equality_not_equals: expression '!=' expression; [[identity-equals-operator]] ==== 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. +Use the *identity equals operator* to compare two values where a resultant +`boolean` type value is `true` if the two values are equal and `false` +otherwise. A reference type value is equal to another reference type value if +both values refer to same instance on the heap or if both values are `null`. A +valid comparison is between boolean type values, numeric type values, or +reference type values. + +*Errors* + +* If a comparison is made between a `boolean` type value and numeric type value. +* If a comparison is made between a primitive type value and a reference type + value. + +*Grammar* -*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* -Promotion Table: +[cols="<1,^1,^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 +| | boolean | byte | short | char | int | long | float | double | Reference | def +| boolean | boolean | - | - | - | - | - | - | - | - | 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 +| Reference | - | - | - | - | - | - | - | - | Object | def +| def | 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 +*Examples* -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 +* Uses of the *identity equals operator* with reference type values. ++ +[source,Painless] +---- +<1> List a = new ArrayList(); +<2> List b = new ArrayList(); +<3> List c = a; +<4> boolean c = a === b; +<5> c = a === c; +---- ++ +<1> declare `List a`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `a` +<2> declare `List b`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `b` +<3> load from `a` -> `List reference`; + store `List reference` to `c` +<4> declare `boolean c`; + load from `a` -> `List reference @0`; + load from `b` -> `List reference @1`; + identity equals `List reference @0` and `List reference @1` + -> `boolean false` + store `boolean false` to `c` +<5> load from `a` -> `List reference @0`; + load from `c` -> `List reference @1`; + identity equals `List reference @0` and `List reference @1` + -> `boolean true` + store `boolean true` to `c` + (note `List reference @0` and `List reference @1` refer to the same + instance) ++ +* Uses of the *identity equals operator* with `null` values. ++ +[source,Painless] ---- +<1> Object a = null; +<2> Object b = null; +<3> boolean c = a === null; +<4> c = a === b; +<5> b = new Object(); +<6> c = a === b; +---- ++ +<1> declare `Object a`; + store `null` to `a` +<2> declare `Object b`; + store `null` to `b` +<3> declare `boolean c`; + load from `a` -> `null @0`; + identity equals `null @0` and `null @1` -> `boolean true`; + store `boolean true` to `c` +<4> load from `a` -> `null @0`; + load from `b` -> `null @1`; + identity equals `null @0` and `null @1` -> `boolean true`; + store `boolean true` to `c` +<5> allocate `Object` instance -> `Object reference`; + store `Object reference` to `b` +<6> load from `a` -> `Object reference`; + load from `b` -> `null`; + identity equals `Object reference` and `null` -> `boolean false`; + store `boolean false` to `c` ++ +* Uses of the *identity equals operator* with the `def` type. ++ +[source, Painless] +---- +<1> def a = new HashMap(); +<2> def b = new ArrayList(); +<3> boolean c = a === b; +<4> b = a; +<5> c = a === b; +---- ++ +<1> declare `def d`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `def` -> `def` + store `def` to `d` +<2> declare `def e`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `def` -> `def` + store `def` to `d` +<3> declare `boolean c`; + load from `a` -> `def`; + implicit cast `def` to `HashMap reference` -> `HashMap reference`; + load from `b` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + identity equals `HashMap reference` and `ArrayList reference` + -> `boolean false`; + store `boolean false` to `c` +<4> load from `a` -> `def`; + store `def` to `b` +<5> load from `a` -> `def`; + implicit cast `def` to `HashMap reference @0` -> `HashMap reference @0`; + load from `b` -> `def`; + implicit cast `def` to `HashMap reference @1` -> `HashMap reference @1`; + identity equals `HashMap reference @0` and `HashMap reference @1` + -> `boolean true`; + store `boolean true` to `b`; + (note `HashMap reference @0` and `HashMap reference @1` refer to the same + instance) [[identity-not-equals-operator]] ==== 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. +Use the *identity not equals operator* to compare two values where a resultant +`boolean` type value is `true` if the two values are not equal and `false` +otherwise. A reference type value is not equal to another reference type value +if both values refer to different instances on the heap or if one value is +`null` and the other is not. A valid comparison is between boolean type values, +numeric type values, or reference type values. + +*Errors* + +* If a comparison is made between a `boolean` type value and numeric type value. +* If a comparison is made between a primitive type value and a reference type + value. + +*Grammar* -*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* -Promotion Table: +[cols="<1,^1,^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 +| | boolean | byte | short | char | int | long | float | double | Reference | def +| boolean | boolean | - | - | - | - | - | - | - | - | 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 +| Reference | - | - | - | - | - | - | - | - | Object | def +| def | def | def | def | def | def | def | def | def | def | def |==== -*Examples:* -[source,Java] +*Examples* + +* Uses of the *identity not equals operator* with reference type values. ++ +[source,Painless] +---- +<1> List a = new ArrayList(); +<2> List b = new ArrayList(); +<3> List c = a; +<4> boolean c = a !== b; +<5> c = a !== c; +---- ++ +<1> declare `List a`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `a` +<2> declare `List b`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `List reference` -> `List reference`; + store `List reference` to `b` +<3> load from `a` -> `List reference`; + store `List reference` to `c` +<4> declare `boolean c`; + load from `a` -> `List reference @0`; + load from `b` -> `List reference @1`; + identity not equals `List reference @0` and `List reference @1` + -> `boolean true` + store `boolean true` to `c` +<5> load from `a` -> `List reference @0`; + load from `c` -> `List reference @1`; + identity not equals `List reference @0` and `List reference @1` + -> `boolean false` + store `boolean false` to `c` + (note `List reference @0` and `List reference @1` refer to the same + instance) ++ +* Uses of the *identity not equals operator* with `null` values. ++ +[source,Painless] +---- +<1> Object a = null; +<2> Object b = null; +<3> boolean c = a !== null; +<4> c = a !== b; +<5> b = new Object(); +<6> c = a !== b; +---- ++ +<1> declare `Object a`; + store `null` to `a` +<2> declare `Object b`; + store `null` to `b` +<3> declare `boolean c`; + load from `a` -> `null @0`; + identity not equals `null @0` and `null @1` -> `boolean false`; + store `boolean false` to `c` +<4> load from `a` -> `null @0`; + load from `b` -> `null @1`; + identity not equals `null @0` and `null @1` -> `boolean false`; + store `boolean false` to `c` +<5> allocate `Object` instance -> `Object reference`; + store `Object reference` to `b` +<6> load from `a` -> `Object reference`; + load from `b` -> `null`; + identity not equals `Object reference` and `null` -> `boolean true`; + store `boolean true` to `c` ++ +* Uses of the *identity not equals operator* with the `def` type. ++ +[source, Painless] ---- -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 +<1> def a = new HashMap(); +<2> def b = new ArrayList(); +<3> boolean c = a !== b; +<4> b = a; +<5> c = a !== b; ---- ++ +<1> declare `def d`; + allocate `HashMap` instance -> `HashMap reference`; + implicit cast `HashMap reference` to `def` -> `def` + store `def` to `d` +<2> declare `def e`; + allocate `ArrayList` instance -> `ArrayList reference`; + implicit cast `ArrayList reference` to `def` -> `def` + store `def` to `d` +<3> declare `boolean c`; + load from `a` -> `def`; + implicit cast `def` to `HashMap reference` -> `HashMap reference`; + load from `b` -> `def`; + implicit cast `def` to `ArrayList reference` -> `ArrayList reference`; + identity not equals `HashMap reference` and `ArrayList reference` + -> `boolean true`; + store `boolean true` to `c` +<4> load from `a` -> `def`; + store `def` to `b` +<5> load from `a` -> `def`; + implicit cast `def` to `HashMap reference @0` -> `HashMap reference @0`; + load from `b` -> `def`; + implicit cast `def` to `HashMap reference @1` -> `HashMap reference @1`; + identity not equals `HashMap reference @0` and `HashMap reference @1` + -> `boolean false`; + store `boolean false` to `b`; + (note `HashMap reference @0` and `HashMap reference @1` refer to the same + instance) [[boolean-xor-operator]] ==== Boolean Xor From 610d67c882882e56afc8bfe27626ba8b42fb3943 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sat, 2 Jun 2018 14:02:25 -0700 Subject: [PATCH 44/55] Completion of operators clean up. --- .../painless-operators-boolean.asciidoc | 220 +++++++++++++++--- .../painless-operators-numeric.asciidoc | 12 +- 2 files changed, 189 insertions(+), 43 deletions(-) diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc index ff7650e698972..cb920c624bc44 100644 --- a/docs/painless/painless-operators-boolean.asciidoc +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -1185,84 +1185,236 @@ identity_not_equals: expression '!==' expression; [[boolean-xor-operator]] ==== 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. +Use the *boolean xor operator* to boolean xor together two `boolean` type values +where if one `boolean` type value is `true` and the other is `false` the +resultant `boolean` type value is `true` and `false` otherwise. +*Errors* + +* If either evaluated value is a value other than a `boolean` type value or + a value that is castable to a `boolean` type value. + +*Truth* + +[cols="^1,^1,^1"] |==== -||true|false -|true|false|true -|false|true|false +| | 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* -*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* -*Examples:* +* Uses of the *boolean xor operator*. ++ +[source,Java] +---- +<1> boolean x = false; +<2> boolean y = x ^ true; +<3> y = y ^ x; +---- ++ +<1> declare `boolean x`; + store `boolean false` to `x` +<2> declare `boolean y`; + load from `x` -> `boolean false` + boolean xor `boolean false` and `boolean true` -> `boolean true`; + store `boolean true` to `y` +<3> load from `y` -> `boolean true @0`; + load from `x` -> `boolean true @1`; + boolean xor `boolean true @0` and `boolean true @1` -> `boolean false`; + store `boolean false` to `y` ++ +* Uses of the *boolean xor operator* with the `def` type. ++ [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 +<1> def x = false; +<2> def y = x ^ true; +<3> y = y ^ x; ---- ++ +<1> declare `def x`; + implicit cast `boolean false` to `def` -> `def`; + store `def` to `x` +<2> declare `def y`; + load from `x` -> `def`; + implicit cast `def` to `boolean false` -> `boolean false`; + boolean xor `boolean false` and `boolean true` -> `boolean true`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `y` +<3> load from `y` -> `def`; + implicit cast `def` to `boolean true @0` -> `boolean true @0`; + load from `x` -> `def`; + implicit cast `def` to `boolean true @1` -> `boolean true @1`; + boolean xor `boolean true @0` and `boolean true @1` -> `boolean false`; + implicit cast `boolean false` -> `def`; + store `def` to `y` [[boolean-and-operator]] ==== 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. +Use the *boolean and operator* to boolean and together two `boolean` type values +where if both `boolean` type values are `true` the resultant `boolean` type +value is `true` and `false` otherwise. -||true|false -|true|true|false -|false|false|false +*Errors* -The format starts with an expression, follows with the ampersand-ampersand operator, and finishes with an expression. +* If either evaluated value is a value other than a `boolean` type value or + a value that is castable to a `boolean` type value. + +*Truth* + +[cols="^1,^1,^1"] +|==== +| | true | false +| true | true | false +| false | false | false +|==== + +*Grammar* -*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* -*Examples:* +* Uses of the *boolean and operator*. ++ +[source,Java] +---- +<1> boolean x = true; +<2> boolean y = x && true; +<3> x = false; +<4> y = y && x; +---- ++ +<1> declare `boolean x`; + store `boolean true` to `x` +<2> declare `boolean y`; + load from `x` -> `boolean true @0`; + boolean and `boolean true @0` and `boolean true @1` -> `boolean true`; + store `boolean true` to `y` +<3> store `boolean false` to `x` +<4> load from `y` -> `boolean true`; + load from `x` -> `boolean false`; + boolean and `boolean true` and `boolean false` -> `boolean false`; + store `boolean false` to `y` ++ +* Uses of the *boolean and operator* with the `def` type. ++ [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 +<1> def x = true; +<2> def y = x && true; +<3> x = false; +<4> y = y && x; ---- ++ +<1> declare `def x`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `x` +<2> declare `def y`; + load from `x` -> `def`; + implicit cast `def` to `boolean true @0` -> `boolean true @0`; + boolean and `boolean true @0` and `boolean true @1` -> `boolean true`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `y` +<3> implicit cast `boolean false` to `def` -> `def`; + store `def` to `x`; +<4> load from `y` -> `def`; + implicit cast `def` to `boolean true` -> `boolean true`; + load from `x` -> `def`; + implicit cast `def` to `boolean false` -> `boolean false`; + boolean and `boolean true` and `boolean false` -> `boolean false`; + implicit cast `boolean false` -> `def`; + store `def` to `y` [[boolean-or-operator]] ==== 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. +Use the *boolean or operator* to boolean or together two `boolean` type values +where if either one of the `boolean` type values is `true` the resultant +`boolean` type value is `true` and `false` otherwise. + +*Errors* + +* If either evaluated value is a value other than a `boolean` type value or + a value that is castable to a `boolean` type value. + +*Truth* +[cols="^1,^1,^1"] |==== -||true|false -|true|true|true -|false|true|false +| | 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* -*Examples:* +* Uses of the *boolean or operator*. ++ [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 ----- \ No newline at end of file +<1> boolean x = false; +<2> boolean y = x || true; +<3> y = false; +<4> y = y || x; +---- ++ +<1> declare `boolean x`; + store `boolean false` to `x` +<2> declare `boolean y`; + load from `x` -> `boolean false`; + boolean or `boolean false` and `boolean true` -> `boolean true`; + store `boolean true` to `y` +<3> store `boolean false` to `y` +<4> load from `y` -> `boolean false @0`; + load from `x` -> `boolean false @1`; + boolean or `boolean false @0` and `boolean false @1` -> `boolean false`; + store `boolean false` to `y` ++ +* Uses of the *boolean or operator* with the `def` type. ++ +[source,Java] +---- +<1> def x = false; +<2> def y = x || true; +<3> y = false; +<4> y = y || x; +---- ++ +<1> declare `def x`; + implicit cast `boolean false` to `def` -> `def`; + store `def` to `x` +<2> declare `def y`; + load from `x` -> `def`; + implicit cast `def` to `boolean false` -> `boolean true`; + boolean or `boolean false` and `boolean true` -> `boolean true`; + implicit cast `boolean true` to `def` -> `def`; + store `def` to `y` +<3> implicit cast `boolean false` to `def` -> `def`; + store `def` to `y`; +<4> load from `y` -> `def`; + implicit cast `def` to `boolean false @0` -> `boolean false @0`; + load from `x` -> `def`; + implicit cast `def` to `boolean false @1` -> `boolean false @1`; + boolean or `boolean false @0` and `boolean false @1` -> `boolean false`; + implicit cast `boolean false` -> `def`; + store `def` to `y` diff --git a/docs/painless/painless-operators-numeric.asciidoc b/docs/painless/painless-operators-numeric.asciidoc index f4a2762302c8a..549e78637c09c 100644 --- a/docs/painless/painless-operators-numeric.asciidoc +++ b/docs/painless/painless-operators-numeric.asciidoc @@ -1101,7 +1101,7 @@ below. The right-hand side integer type value is always implicitly cast to an Use the *bitwise and operator* to bitwise and together each bit within two integer type values where if both bits at the same index are `1` the resultant -bit is `1` otherwise the resultant bit is `0`. +bit is `1` and `0` otherwise. *Errors* @@ -1109,8 +1109,6 @@ bit is `1` otherwise the resultant bit is `0`. *Bits* -The following table illustrates the resultant bit from the anding of two bits. - [cols="^1,^1,^1"] |==== | | 1 | 0 @@ -1181,7 +1179,7 @@ bitwise_and: expression '&' expression; Use the *bitwise xor operator* to bitwise 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`. +same index the resultant bit is `1` and `0` otherwise. *Errors* @@ -1189,8 +1187,6 @@ same index the resultant bit is `1` otherwise the resultant bit is `0`. *Bits* -The following table illustrates the resultant bit from the anding of two bits. - [cols="^1,^1,^1"] |==== | | 1 | 0 @@ -1261,7 +1257,7 @@ bitwise_and: expression '^' expression; Use the *bitwise or operator* to bitwise 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`. +bit is `1` and `0` otherwise. *Errors* @@ -1269,8 +1265,6 @@ bit is `1` otherwise the resultant bit is `0`. *Bits* -The following table illustrates the resultant bit from the anding of two bits. - [cols="^1,^1,^1"] |==== | | 1 | 0 From 3b8da6539a31fc8bce2d45045c8feff13883aa4f Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sat, 2 Jun 2018 14:27:28 -0700 Subject: [PATCH 45/55] Fix Java to Painless. --- docs/painless/painless-operators-boolean.asciidoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc index cb920c624bc44..3a20a929990c0 100644 --- a/docs/painless/painless-operators-boolean.asciidoc +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -1214,7 +1214,7 @@ boolean_xor: expression '^' expression; * Uses of the *boolean xor operator*. + -[source,Java] +[source,Painless] ---- <1> boolean x = false; <2> boolean y = x ^ true; @@ -1234,7 +1234,7 @@ boolean_xor: expression '^' expression; + * Uses of the *boolean xor operator* with the `def` type. + -[source,Java] +[source,Painless] ---- <1> def x = false; <2> def y = x ^ true; @@ -1290,7 +1290,7 @@ boolean_and: expression '&&' expression; * Uses of the *boolean and operator*. + -[source,Java] +[source,Painless] ---- <1> boolean x = true; <2> boolean y = x && true; @@ -1312,7 +1312,7 @@ boolean_and: expression '&&' expression; + * Uses of the *boolean and operator* with the `def` type. + -[source,Java] +[source,Painless] ---- <1> def x = true; <2> def y = x && true; @@ -1370,7 +1370,7 @@ boolean_and: expression '||' expression; * Uses of the *boolean or operator*. + -[source,Java] +[source,Painless] ---- <1> boolean x = false; <2> boolean y = x || true; @@ -1392,7 +1392,7 @@ boolean_and: expression '||' expression; + * Uses of the *boolean or operator* with the `def` type. + -[source,Java] +[source,Painless] ---- <1> def x = false; <2> def y = x || true; From 9439b923268a602fc64e33719b5272a65f36871a Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sun, 3 Jun 2018 15:36:53 -0700 Subject: [PATCH 46/55] Fix missing lang. --- docs/painless/painless-operators-general.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 752ba7c09f204..6964166d4761c 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -175,6 +175,7 @@ assignment: field '=' expression The examples use the following reference type definition: +[source,Painless] ---- name: Example From d54e4a048e7910e89f0f4e2168e8b8cabe8b9da8 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sun, 3 Jun 2018 15:38:24 -0700 Subject: [PATCH 47/55] Fix missing lang. --- docs/painless/painless-operators-reference.asciidoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 8808a3d92c13b..8aac90b06dc1f 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -96,6 +96,7 @@ field_access: '.' ID; The examples use the following reference type definition: +[source,Painless] ---- name: Example @@ -175,6 +176,7 @@ null_safe_field_access: '?.' ID; The examples use the following reference type definition: +[source,Painless] ---- name: Example From 73ff8a202a44ace9aef825c7c084d0e0aa6fb12a Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sun, 3 Jun 2018 22:12:20 -0700 Subject: [PATCH 48/55] Fix missing lang. --- docs/painless/painless-operators-general.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 6964166d4761c..cc7b306fed3b4 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -240,6 +240,7 @@ expression and a separate right-side expression. A compound assignment is equivalent to the expression below where V is the variable/field and T is the type of variable/member. +[source,Painless] ---- V = (T)(V op expression); ---- From c6881993b4cfd7420da1bb2c55bf178e7779fe45 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 4 Jun 2018 17:16:32 -0700 Subject: [PATCH 49/55] Response to PR review. --- docs/painless/painless-casting.asciidoc | 7 ++-- .../painless-operators-general.asciidoc | 34 +++++++++---------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 02419c8f20b33..adaa4c3b94baa 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -461,9 +461,10 @@ type value is derived from what the `def` type value represents at run-time. [[allowed-casts]] ==== Allowed Casts -The following tables list all allowed casts read as row (original type) to -column (target type) with implicit as `I`, explicit as `E`, and not allowed as -`-`: +The following tables show all allowed casts. Read the tables row by row, where +the original type is shown in the first column, and each subsequent column +indicates whether a cast to the specified type can be implicit (I), explicit +(E), or is not allowed (-). *Primitive/Reference Types* diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index cc7b306fed3b4..e7f8a206efe8a 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -4,10 +4,10 @@ [[precedence-operator]] ==== Precedence -An expression encapsulated within a *precedence operator* overrides -existing precedence relationships between operators and is evaluated -prior to other expressions in inward-to-outward order. Use the *precedence -operator* to guarantee the order of evaluation for an expression. +An expression encapsulated by the precedence operator (enclosed in parentheses) +overrides existing precedence relationships between operators and is evaluated +prior to other expressions in inward-to-outward order. Use the precedence +operator to guarantee the order of evaluation for an expression. *Grammar* [source,ANTLR4] @@ -17,7 +17,7 @@ precedence: '(' expression ')'; *Examples* -* Uses of the *precedence operator*. +* Uses of the precedence operator. + [source,Painless] ---- @@ -29,20 +29,20 @@ precedence: '(' expression ')'; add `int 5` and `int 4` -> `int 9`; multiply `int 9` and `int 6` -> `int 54`; store `int 54` to `x`; - (note the add is evaluated before the multiply due to the *precedence - operator*) + (note the add is evaluated before the multiply due to the precedence + operator) <2> declare `int y`; load from `x` -> `int 54`; subtract `int 50` from `int 54` -> `int 4`; divide `int 12` by `int 4` -> `int 3`; store `int 3` to `y`; - (note the subtract is evaluated before the divide due to the *precedence - operator*) + (note the subtract is evaluated before the divide due to the precedence + operator) [[function-call-operator]] ==== Function Call -A function call is defined within a script. Use the *function call operator* to +A function call is defined within a script. Use the function call operator to call an existing function. *Grammar* @@ -53,7 +53,7 @@ function_call: ID '(' ( expression (',' expression)* )? ')''; *Examples* -* Use of the *function call operator*. +* Use of the function call operator. + [source,Painless] ---- @@ -74,7 +74,7 @@ function_call: ID '(' ( expression (',' expression)* )? ')''; ==== Cast An explicit cast converts the value of an original type to the equivalent value -of a target type forcefully as an operation. Use the *cast operator* to specify +of a target type forcefully as an operation. Use the cast operator to specify an explicit cast. Refer to <> for more information. [[conditional-operator]] @@ -85,7 +85,7 @@ 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. The second and third expressions will be <> if the evaluated values are not the -same type. Use the *conditional operator* as a shortcut to avoid the need for a +same type. Use the conditional operator as a shortcut to avoid the need for a full if/else branch in certain expressions. *Errors* @@ -120,7 +120,7 @@ occur. *Examples* -* Uses of the *conditional operator*. +* Uses of the conditional operator. + [source,Painless] ---- @@ -153,7 +153,7 @@ occur. [[assignment-operator]] ==== Assignment -Use the *assignment operator* to store a value in a variable or reference type +Use the assignment operator to store a value in a variable or reference type member field for use in subsequent operations. Any operation that produces a value can be assigned to any variable/field as long as the <> are the same or the resultant type can be @@ -233,7 +233,7 @@ non-static member fields: [[compound-assignment-operator]] ==== Compound Assignment -Use the *compound assignment operator* as a shortcut for an assignment where a +Use the compound assignment operator 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. @@ -377,7 +377,7 @@ operators. store `boolean true` to `b`; (note this is equivalent to `b = b || true`) + -* Use of compound assignment with the *string concatenation operator*. +* Use of compound assignment with the string concatenation operator. + [source,Painless] ---- From 603e5e57291d0ea22a6080bb6749ec34eab38150 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 5 Jun 2018 13:30:26 -0700 Subject: [PATCH 50/55] PR response to numeric operators. --- docs/painless/painless-casting.asciidoc | 24 +- .../painless-operators-general.asciidoc | 53 ++-- .../painless-operators-numeric.asciidoc | 229 +++++++++--------- docs/painless/painless-operators.asciidoc | 4 +- docs/painless/painless-variables.asciidoc | 12 +- 5 files changed, 165 insertions(+), 157 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index bc8bbeee6fbe8..e73cd6fbc90d4 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -4,8 +4,8 @@ A cast converts the value of an original type to the equivalent value of a target type. An implicit cast infers the target type and automatically occurs during certain <>. An explicit cast specifies -the target type and forcefully occurs as its own operation. Use the *cast -operator* to specify an explicit cast. +the target type and forcefully occurs as its own operation. Use the `cast +operator '()'` to specify an explicit cast. Refer to the <> for a quick reference on all allowed casts. @@ -300,7 +300,7 @@ based on the current type value the `def` type value represents. [[string-character-casting]] ==== String to Character Casting -Use the *cast operator* to convert a <> value into a +Use the cast operator to convert a <> value into a <> value. *Errors* @@ -314,8 +314,8 @@ Use the *cast operator* to convert a <> value into a + [source,Painless] ---- -<1> char c = (char)"C" -<2> c = (char)'c' +<1> char c = (char)"C"; +<2> c = (char)'c'; ---- + <1> declare `char c`; @@ -347,12 +347,12 @@ reference type to its corresponding primitive type. Implicit boxing/unboxing occurs during the following operations: -* Conversions between a `def` type and a primitive type will be implicitly +* Conversions between a `def` type and a primitive type is implicitly boxed/unboxed as necessary, though this is referred to as an implicit cast throughout the documentation. -* Method/function call arguments will be implicitly boxed/unboxed as necessary. -* A primitive type value will be implicitly boxed when a reference type method - call is invoked on it. +* Method/function call arguments are implicitly boxed/unboxed as necessary. +* A primitive type value is implicitly boxed when a reference type method + is called on it. Explicit boxing/unboxing is not allowed. Use the reference type API to explicitly convert a primitive type value to its respective reference type @@ -423,8 +423,8 @@ Promotion is when a single value is implicitly cast to a certain type or multiple values are implicitly cast to the same type as required for evaluation by certain operations. Each operation that requires promotion has a promotion table that shows all required implicit casts based on the type(s) of value(s). A -value can be promoted to a `def` type at compile-time; however, the promoted -type value is derived from what the `def` type value represents at run-time. +value promoted to a `def` type at compile-time is promoted again at +run-time based on the type the `def` value represents. *Errors* @@ -464,7 +464,7 @@ type value is derived from what the `def` type value represents at run-time. The following tables show all allowed casts. Read the tables row by row, where the original type is shown in the first column, and each subsequent column -indicates whether a cast to the specified type can be implicit (I), explicit +indicates whether a cast to the specified target type is implicit (I), explicit (E), or is not allowed (-). *Primitive/Reference Types* diff --git a/docs/painless/painless-operators-general.asciidoc b/docs/painless/painless-operators-general.asciidoc index 43121bc5bf666..3a3670a14a32e 100644 --- a/docs/painless/painless-operators-general.asciidoc +++ b/docs/painless/painless-operators-general.asciidoc @@ -4,10 +4,10 @@ [[precedence-operator]] ==== Precedence -An expression encapsulated by the precedence operator (enclosed in parentheses) -overrides existing precedence relationships between operators and is evaluated -prior to other expressions in inward-to-outward order. Use the precedence -operator to guarantee the order of evaluation for an expression. +Use the `precedence operator '()'` to guarantee the order of evaluation for an +expression. An expression encapsulated by the precedence operator (enclosed in +parentheses) overrides existing precedence relationships between operators and +is evaluated prior to other expressions in inward-to-outward order. *Grammar* @@ -18,7 +18,7 @@ precedence: '(' expression ')'; *Examples* -* Uses of the precedence operator. +* Precedence with numeric operators. + [source,Painless] ---- @@ -43,8 +43,8 @@ precedence: '(' expression ')'; [[function-call-operator]] ==== Function Call -A <> is defined within a script. Use the -*function call operator* to call an existing function. +Use the `function call operator ()` to call an existing function. A +<> is defined within a script. *Grammar* @@ -55,7 +55,7 @@ function_call: ID '(' ( expression (',' expression)* )? ')''; *Examples* -* Use of the function call operator. +* A function call. + [source,Painless] ---- @@ -76,8 +76,9 @@ function_call: ID '(' ( expression (',' expression)* )? ')''; ==== Cast An explicit cast converts the value of an original type to the equivalent value -of a target type forcefully as an operation. Use the cast operator to specify -an explicit cast. Refer to <> for more information. +of a target type forcefully as an operation. Use the `cast operator '()'` to +specify an explicit cast. Refer to <> for more +information. [[conditional-operator]] ==== Conditional @@ -87,8 +88,8 @@ 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. The second and third expressions will be <> if the evaluated values are not the -same type. Use the conditional operator as a shortcut to avoid the need for a -full if/else branch in certain expressions. +same type. Use the `conditional operator '? :'` as a shortcut to avoid the need +for a full if/else branch in certain expressions. *Errors* @@ -123,7 +124,7 @@ occur. *Examples* -* Uses of the conditional operator. +* Evaluation of conditionals. + [source,Painless] ---- @@ -156,9 +157,9 @@ occur. [[assignment-operator]] ==== Assignment -Use the assignment operator to store a value in a variable or reference type -member field for use in subsequent operations. Any operation -that produces a value can be assigned to any variable/field as long as the +Use the `assignment operator '='` to store a value in a variable or reference +type member field for use in subsequent operations. Any operation that produces +a value can be assigned to any variable/field as long as the <> are the same or the resultant type can be <> to the variable/field type. @@ -190,7 +191,7 @@ non-static member fields: * List z ---- -* Uses of field assignment. +* Field assignments of different type values. + [source,Painless] ---- @@ -213,7 +214,7 @@ non-static member fields: implicit cast `ArrayList reference` to `List reference` -> `List reference`; store `List reference` to `z` of `Example reference` + -* Use of field assignment from a field access. +* A field assignment from a field access. + [source,Painless] ---- @@ -237,9 +238,9 @@ non-static member fields: [[compound-assignment-operator]] ==== Compound Assignment -Use the compound assignment operator 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. +Use the `compound assignment operator '$='` as a shortcut for an assignment +where a binary operation would occur between the variable/field as the +left-hand side expression and a separate right-hand side expression. A compound assignment is equivalent to the expression below where V is the variable/field and T is the type of variable/member. @@ -292,7 +293,7 @@ operators. *Examples* -* Uses of compound assignment for each numeric operator. +* Compound assignment for each numeric operator. + [source,Painless] ---- @@ -357,7 +358,7 @@ operators. store `int 15` to `i`; (note this is equivalent to `i = i|2`) + -* Uses of compound assignment for each boolean operator. +* Compound assignment for each boolean operator. + [source,Painless] ---- @@ -382,7 +383,7 @@ operators. store `boolean true` to `b`; (note this is equivalent to `b = b || true`) + -* Use of compound assignment with the string concatenation operator. +* A compound assignment with the string concatenation operator. + [source,Painless] ---- @@ -397,7 +398,7 @@ operators. store `String 'compound assignment'` to `s`; (note this is equivalent to `s = s + ' assignment'`) + -* Use of a compound assignment with the `def` type. +* A compound assignment with the `def` type. + [source,Painless] ---- @@ -414,7 +415,7 @@ operators. store `def` to `x`; (note this is equivalent to `x = x+2`) + -* Use of a compound assignment with an extra implicit cast. +* A compound assignment with an extra implicit cast. + [source,Painless] ---- diff --git a/docs/painless/painless-operators-numeric.asciidoc b/docs/painless/painless-operators-numeric.asciidoc index bc31cfbc496e3..adfc55d1896f9 100644 --- a/docs/painless/painless-operators-numeric.asciidoc +++ b/docs/painless/painless-operators-numeric.asciidoc @@ -4,15 +4,16 @@ [[post-increment-operator]] ==== Post Increment -Use the *post increment operator* to increase the value of numerical type -variable/field by `1`. There is an extra implicit cast when necessary to return -the promoted numeric type value to the original numeric type value of the -variable/field and can result in data loss. If a variable/field is read as part -of an expression the value is loaded prior to the 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 evaluated variable/field is a non-numeric type. +* If the variable/field is a non-numeric type. *Grammar* @@ -38,7 +39,7 @@ post_increment: ( variable | field ) '++'; *Examples* -* Use of the *post increment operator*. +* Post increment with different numeric types. + [source,Painless] ---- @@ -66,7 +67,7 @@ post_increment: ( variable | field ) '++'; add `long 1` and `long 1` -> `long 2`; store `long 2` to `j` + -* Use of the *post increment operator* with the `def` type. +* Post increment with the `def` type. + [source,Painless] ---- @@ -86,15 +87,16 @@ post_increment: ( variable | field ) '++'; [[post-decrement-operator]] ==== Post Decrement -Use the *post decrement operator* to decrease the value of numerical type -variable/field by `1`. There is an extra implicit cast when necessary to return -the promoted numeric type value to the original numeric type value of the -variable/field and can result in data loss. If a variable/field is read as part -of an expression the value is loaded prior to the 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 evaluated variable/field is a non-numeric type. +* If the variable/field is a non-numeric type. *Grammar* @@ -120,7 +122,7 @@ post_decrement: ( variable | field ) '--'; *Examples* -* Use of the *post decrement operator*. +* Post decrement with different numeric types. + [source,Painless] ---- @@ -148,7 +150,7 @@ post_decrement: ( variable | field ) '--'; subtract `long 1` from `long 1` -> `long 0`; store `long 0` to `j` + -* Use of the *post decrement operator* with the `def` type. +* Post decrement with the `def` type. + [source,Painless] ---- @@ -168,15 +170,16 @@ post_decrement: ( variable | field ) '--'; [[pre-increment-operator]] ==== Pre Increment -Use the *pre increment operator* to increase the value of numerical type -variable/field by `1`. There is an extra implicit cast when necessary to return -the promoted numeric type value to the original numeric type value of the -variable/field and can result in data loss. If a variable/field is read as part -of an expression the value is loaded after the 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 evaluated variable/field is a non-numeric type. +* If the variable/field is a non-numeric type. *Grammar* @@ -202,7 +205,7 @@ pre_increment: '++' ( variable | field ); *Examples* -* Use of the *pre increment operator*. +* Pre increment with different numeric types. + [source,Painless] ---- @@ -230,7 +233,7 @@ pre_increment: '++' ( variable | field ); store `long 2` to `j`; store `long 2` to `k` + -* Use of the *post increment operator* with the `def` type. +* Pre increment with the `def` type. + [source,Painless] ---- @@ -250,15 +253,16 @@ pre_increment: '++' ( variable | field ); [[pre-decrement-operator]] ==== Pre Decrement -Use the *pre decrement operator* to decrease the value of numerical type -variable/field by `1`. There is an extra implicit cast when necessary to return -the promoted numeric type value to the original numeric type value of the -variable/field and can result in data loss. If a variable/field is read as part -of an expression the value is loaded after the 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 evaluated variable/field is a non-numeric type. +* If the variable/field is a non-numeric type. *Grammar* @@ -284,7 +288,7 @@ pre_increment: '--' ( variable | field ); *Examples* -* Use of the *pre decrement operator*. +* Pre decrement with different numeric types. + [source,Painless] ---- @@ -312,7 +316,7 @@ pre_increment: '--' ( variable | field ); store `long 0` to `j` store `long 0` to `k`; + -* Use of the *pre decrement operator* with the `def` type. +* Pre decrement operator with the `def` type. + [source,Painless] ---- @@ -332,12 +336,12 @@ pre_increment: '--' ( variable | field ); [[unary-positive-operator]] ==== Unary Positive -Use the *unary positive operator* to the retrieve the identity of a numeric -value. +Use the `unary positive operator '+'` to the preserve the *identity* of a +numeric type value. *Errors* -* If the evaluated value is a non-numeric type. +* If the value is a non-numeric type. *Grammar* @@ -348,7 +352,7 @@ unary_positive: '+' expression; *Examples* -* Use of the *unary positive operator*. +* Unary positive with different numeric types. + [source,Painless] ---- @@ -365,7 +369,7 @@ unary_positive: '+' expression; implicit cast `int 1` to `long 1` -> `long 1`; store `long 1` to `y` + -* Use of the *unary positive operator* with the `def` type. +* Unary positive with the `def` type. + [source,Painless] ---- @@ -385,11 +389,11 @@ unary_positive: '+' expression; [[unary-negative-operator]] ==== Unary Negative -Use the *unary negative operator* to negate a numeric type value. +Use the `unary negative operator '-'` to *negate* a numeric type value. *Errors* -* If the evaluated value is a non-numeric type. +* If the value is a non-numeric type. *Grammar* @@ -400,7 +404,7 @@ unary_negative: '-' expression; *Examples* -* Use of the *unary negative operator*. +* Unary negative with different numeric types. + [source,Painless] ---- @@ -417,7 +421,7 @@ unary_negative: '-' expression; implicit cast `int 1` to `long 1` -> `long 1`; store `long 1` to `y` + -* Use of the *unary negative operator* with the `def` type. +* Unary negative with the `def` type. + [source,Painless] ---- @@ -437,16 +441,17 @@ unary_negative: '-' expression; [[bitwise-not-operator]] ==== Bitwise Not -Use the *bitwise not operator* to flip each bit in an integer type value where -if a bit is `1` it becomes `0` and if a bit is `0` it becomes `1`. +Use the `bitwise not operator '~'` to *flip* 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 evaluated value is a non-integer type. +* If the value is a non-integer type. *Bits* -[options="header",cols="^1,^1,"] +[options="header",cols="<1,<1"] |==== | original | result | 1 | 0 @@ -475,7 +480,7 @@ bitwise_not: '~' expression; *Examples* -* Uses of the *bitwise not operator*. +* Bitwise not with different numeric types. + [source,Painless] ---- @@ -497,7 +502,7 @@ bitwise_not: '~' expression; bitwise not `long -2` -> `long 1`; store `long 1` to `l` + -* Uses of the *bitwise not operator* with the `def` type. +* Bitwise not with the `def` type. + [source,Painless] ---- @@ -518,13 +523,13 @@ bitwise_not: '~' expression; [[multiplication-operator]] ==== Multiplication -Use the *multiplication operator* to multiply together two numerical +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 evaluated values is a non-numeric type. +* If either of the values is a non-numeric type. *Grammar* @@ -550,7 +555,7 @@ multiplication: expression '*' expression; *Examples* -* Uses of the *multiplication operator*. +* Multiplication with different numeric types. + [source,Painless] ---- @@ -568,7 +573,7 @@ multiplication: expression '*' expression; multiply `double 20.0` by `double 7.0` -> `double 140.0`; store `double 140.0` to `d` + -* Uses of the *multiplication operator* with the `def` type. +* Multiplication with the `def` type. + [source,Painless] ---- @@ -589,13 +594,13 @@ multiplication: expression '*' expression; [[division-operator]] ==== Division -Use the *division operator* to divide two numerical values. Rules for NaN -values and division by zero follow the JVM specification. Division with integer -values drops the remainder of the resultant value. +Use the `division operator '/'` to *divide* two numeric type values. 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 evaluated values is a non-numeric type. +* 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`. @@ -623,7 +628,7 @@ division: expression '/' expression; *Examples* -* Uses of the *division operator*. +* Division with different numeric types. + [source,Painless] ---- @@ -641,7 +646,7 @@ division: expression '/' expression; divide `double 7.0` by `double 7.0` -> `double 1.0`; store `double 1.0` to `d` + -* Uses of the *division operator* with the `def` type. +* Division with the `def` type. + [source,Painless] ---- @@ -662,13 +667,13 @@ division: expression '/' expression; [[remainder-operator]] ==== Remainder -Use the *remainder operator* to calculate the remainder for division between -two numerical values. Rules for NaN values and division by zero follow the JVM +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 evaluated values is a non-numeric type. +* If either of the values is a non-numeric type. *Grammar* @@ -694,7 +699,7 @@ remainder: expression '%' expression; *Examples* -* Uses of the *remainder operator*. +* Remainder with different numeric types. + [source,Painless] ---- @@ -712,7 +717,7 @@ remainder: expression '%' expression; remainder `double 1.0` by `double 7.0` -> `double 1.0`; store `double 1.0` to `d` + -* Uses of the *remainder operator* with the `def` type. +* Remainder with the `def` type. + [source,Painless] ---- @@ -733,12 +738,12 @@ remainder: expression '%' expression; [[addition-operator]] ==== Addition -Use the *addition operator* to add together two numerical values. Rules for -resultant overflow and NaN values follow the JVM specification. +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 evaluated values is a non-numeric type. +* If either of the values is a non-numeric type. *Grammar* @@ -764,7 +769,7 @@ addition: expression '+' expression; *Examples* -* Uses of the *addition operator*. +* Addition operator with different numeric types. + [source,Painless] ---- @@ -782,7 +787,7 @@ addition: expression '+' expression; add `double 33.0` and `double 7.0` -> `double 40.0`; store `double 40.0` to `d` + -* Uses of the *addition operator* with the `def` type. +* Addition with the `def` type. + [source,Painless] ---- @@ -803,13 +808,13 @@ addition: expression '+' expression; [[subtraction-operator]] ==== Subtraction -Use the *subtraction operator* to subtract a right-hand side numerical value -from a left-hand side numerical value. Rules for resultant overflow and NaN -values follow the JVM specification. +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 evaluated values is a non-numeric type. +* If either of the values is a non-numeric type. *Grammar* @@ -835,7 +840,7 @@ subtraction: expression '-' expression; *Examples* -* Uses of the *subtraction operator*. +* Subtraction with different numeric types. + [source,Painless] ---- @@ -853,7 +858,7 @@ subtraction: expression '-' expression; subtract `double 33.0` by `double 7.5` -> `double 25.5`; store `double 25.5` to `d` + -* Uses of the *subtraction operator* with the `def` type. +* Subtraction with the `def` type. + [source,Painless] ---- @@ -874,14 +879,14 @@ subtraction: expression '-' expression; [[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. +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 evaluated values is a non-integer type. -* If the evaluated right-hand side value cannot be cast to an int type. +* If either of the values is a non-integer type. +* If the right-hand side value cannot be cast to an int type. *Grammar* @@ -909,7 +914,7 @@ int type value and truncated to the number of bits of the promoted type value. *Examples* -* Uses of the *left shift operator*. +* Left shift with different integer types. + [source,Painless] ---- @@ -927,7 +932,7 @@ int type value and truncated to the number of bits of the promoted type value. implicit cast `int 32` to `long 32` -> `long 32`; store `long 32` to `l` + -* Uses of the *left shift operator* with the `def` type. +* Left shift with the `def` type. + [source,Painless] ---- @@ -948,15 +953,15 @@ int type value and truncated to the number of bits of the promoted type value. [[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. +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 evaluated values is a non-integer type. -* If the evaluated right-hand side value cannot be cast to an int type. +* If either of the values is a non-integer type. +* If the right-hand side value cannot be cast to an int type. *Grammar* @@ -984,7 +989,7 @@ int type value and truncated to the number of bits of the promoted type value. *Examples* -* Uses of the *right shift operator*. +* Right shift with different integer types. + [source,Painless] ---- @@ -1002,7 +1007,7 @@ int type value and truncated to the number of bits of the promoted type value. implicit cast `int 4` to `long 4` -> `long 4`; store `long 4` to `l` + -* Uses of the *right shift operator* with the `def` type. +* Right shift with the `def` type. + [source,Painless] ---- @@ -1023,15 +1028,15 @@ int type value and truncated to the number of bits of the promoted type value. [[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. +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 evaluated values is a non-integer type. -* If the evaluated right-hand side value cannot be cast to an int type. +* If either of the values is a non-integer type. +* If the right-hand side value cannot be cast to an int type. *Grammar* @@ -1059,7 +1064,7 @@ int type value and truncated to the number of bits of the promoted type value. *Examples* -* Uses of the *unsigned right shift operator*. +* Unsigned right shift with different integer types. + [source,Painless] ---- @@ -1077,7 +1082,7 @@ int type value and truncated to the number of bits of the promoted type value. implicit cast `int 3` to `long 3` -> `long 3`; store `long 3` to `l` + -* Uses of the *unsigned right shift operator* with the `def` type. +* Unsigned right shift with the `def` type. + [source,Painless] ---- @@ -1098,13 +1103,13 @@ int type value and truncated to the number of bits of the promoted type value. [[bitwise-and-operator]] ==== Bitwise And -Use the *bitwise and operator* to bitwise and together each bit within two +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` otherwise the resultant bit is `0`. *Errors* -* If either of the evaluated values is a non-integer type. +* If either of the values is a non-integer type. *Bits* @@ -1139,7 +1144,7 @@ bitwise_and: expression '&' expression; *Examples* -* Uses of the *bitwise and operator*. +* Bitwise and with different integer types. + [source,Painless] ---- @@ -1157,7 +1162,7 @@ bitwise_and: expression '&' expression; bitwise and `long 4` and `long 5` -> `long 4`; store `long 4` to `l` + -* Uses of the *bitwise and operator* with the `def` type. +* Bitwise and with the `def` type. + [source,Painless] ---- @@ -1178,17 +1183,17 @@ bitwise_and: expression '&' expression; [[bitwise-xor-operator]] ==== Bitwise Xor -Use the *bitwise xor operator* to bitwise 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`. +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 evaluated values is a non-integer type. +* If either of the values is a non-integer type. *Bits* -The following table illustrates the resultant bit from the anding of two bits. +The following table illustrates the resultant bit from the xoring of two bits. [cols="^1,^1,^1"] |==== @@ -1219,7 +1224,7 @@ bitwise_and: expression '^' expression; *Examples* -* Uses of the *bitwise xor operator*. +* Bitwise xor with different integer types. + [source,Painless] ---- @@ -1237,7 +1242,7 @@ bitwise_and: expression '^' expression; bitwise xor `long 3` and `long 5` -> `long 6`; store `long 6` to `l` + -* Uses of the *bitwise xor operator* with the `def` type. +* Bitwise xor with the `def` type. + [source,Painless] ---- @@ -1258,13 +1263,13 @@ bitwise_and: expression '^' expression; [[bitwise-or-operator]] ==== Bitwise Or -Use the *bitwise or operator* to bitwise or together each bit within two integer -type values where if at least one bit is a `1` at the same index the resultant +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 evaluated values is a non-integer type. +* If either of the values is a non-integer type. *Bits* @@ -1299,7 +1304,7 @@ bitwise_and: expression '|' expression; *Examples* -* Uses of the *bitwise or operator*. +* Bitwise or with different integer types. + [source,Painless] ---- @@ -1317,7 +1322,7 @@ bitwise_and: expression '|' expression; bitwise or `long 7` and `long 8` -> `long 15`; store `long 15` to `l` + -* Uses of the *bitwise or operator* with the `def` type. +* Bitwise or with the `def` type. + [source,Painless] ---- diff --git a/docs/painless/painless-operators.asciidoc b/docs/painless/painless-operators.asciidoc index bafa3886616f0..80ee81ae5708b 100644 --- a/docs/painless/painless-operators.asciidoc +++ b/docs/painless/painless-operators.asciidoc @@ -9,7 +9,7 @@ is evaluated. The following table lists all available operators: [cols="<6,<3,^3,^2,^4"] |==== -| *Operator* | *Category* | *Symbol(s)* | *Precedence* | *Associativity* +| *Operator* | *Category* | *Symbol(s)* | *Precedence* | *Associativity* | <> | <> | () | 0 | left -> right | <> | <> | . () | 1 | left -> right | <> | <> | . | 1 | left -> right @@ -32,7 +32,7 @@ is evaluated. The following table lists all available operators: | <> | <> | ~ | 2 | right -> left | <> | <> | () | 3 | right -> left | <> | <> | new () | 3 | right -> left -| <> | <> | new | 3 | right -> left +| <> | <> | new [] | 3 | right -> left | <> | <> | * | 4 | left -> right | <> | <> | / | 4 | left -> right | <> | <> | % | 4 | left -> right diff --git a/docs/painless/painless-variables.asciidoc b/docs/painless/painless-variables.asciidoc index 3da88ffa6ab2d..8f83b9e2b573b 100644 --- a/docs/painless/painless-variables.asciidoc +++ b/docs/painless/painless-variables.asciidoc @@ -67,7 +67,7 @@ assignment: '=' expression; [[variable-assignment]] ==== Assignment -Use the *assignment operator* to store a value in a variable for use in +Use the `assignment operator '='` to store a value in a variable for use in subsequent operations. Any operation that produces a value can be assigned to any variable as long as the <> are the same or the resultant type can be <> to the variable @@ -111,7 +111,7 @@ assignment: ID '=' expression <2> declare `double j`; store `double 2.0` to `j` + -* Assignment of one variable to another using primitive types. +* Assignment of one variable to another using primitive type values. + [source,Painless] ---- @@ -125,7 +125,8 @@ assignment: ID '=' expression load from `i` -> `int 10`; store `int 10` to `j` + -* Assignment with reference types using the *new instance operator*. +* Assignment with reference types using the + <>. + [source,Painless] ---- @@ -141,7 +142,7 @@ assignment: ID '=' expression implicit cast `HashMap reference` to `Map reference` -> `Map reference`; store `Map reference` to `m` + -* Assignment of one variable to another using reference types. +* Assignment of one variable to another using reference type values. + [source,Painless] ---- @@ -165,7 +166,8 @@ assignment: ID '=' expression store `List reference` to `m`; (note `l`, `k`, and `m` refer to the same instance) + -* Assignment with an array type variable using the *new array operator*. +* Assignment with array type variables using the + <>. + [source,Painless] ---- From 12fb54d41016480b0c2165d26a135f51eab16fa9 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 5 Jun 2018 14:02:03 -0700 Subject: [PATCH 51/55] Response to PR comments for reference operators. --- .../painless-operators-numeric.asciidoc | 42 ++++----- .../painless-operators-reference.asciidoc | 88 +++++++++---------- 2 files changed, 64 insertions(+), 66 deletions(-) diff --git a/docs/painless/painless-operators-numeric.asciidoc b/docs/painless/painless-operators-numeric.asciidoc index adfc55d1896f9..8e14d9051f528 100644 --- a/docs/painless/painless-operators-numeric.asciidoc +++ b/docs/painless/painless-operators-numeric.asciidoc @@ -4,7 +4,7 @@ [[post-increment-operator]] ==== Post Increment -Use the `post increment operator '++'` to *increase* the value of a numeric type +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 @@ -87,7 +87,7 @@ post_increment: ( variable | field ) '++'; [[post-decrement-operator]] ==== Post Decrement -Use the `post decrement operator '--'` to *decrease* the value of a numeric type +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 @@ -170,7 +170,7 @@ post_decrement: ( variable | field ) '--'; [[pre-increment-operator]] ==== Pre Increment -Use the `pre increment operator '++'` to *increase* the value of a numeric type +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 @@ -253,7 +253,7 @@ pre_increment: '++' ( variable | field ); [[pre-decrement-operator]] ==== Pre Decrement -Use the `pre decrement operator '--'` to *decrease* the value of a numeric type +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 @@ -336,7 +336,7 @@ pre_increment: '--' ( variable | field ); [[unary-positive-operator]] ==== Unary Positive -Use the `unary positive operator '+'` to the preserve the *identity* of a +Use the `unary positive operator '+'` to the preserve the IDENTITY of a numeric type value. *Errors* @@ -389,7 +389,7 @@ unary_positive: '+' expression; [[unary-negative-operator]] ==== Unary Negative -Use the `unary negative operator '-'` to *negate* a numeric type value. +Use the `unary negative operator '-'` to NEGATE a numeric type value. *Errors* @@ -441,7 +441,7 @@ unary_negative: '-' expression; [[bitwise-not-operator]] ==== Bitwise Not -Use the `bitwise not operator '~'` to *flip* each bit in an integer type value +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`. @@ -523,7 +523,7 @@ bitwise_not: '~' expression; [[multiplication-operator]] ==== Multiplication -Use the `multiplication operator '*'` to *multiply* together two numeric type +Use the `multiplication operator '*'` to MULTIPLY together two numeric type values. Rules for resultant overflow and NaN values follow the JVM specification. @@ -594,9 +594,9 @@ multiplication: expression '*' expression; [[division-operator]] ==== Division -Use the `division operator '/'` to *divide* two numeric type values. Rules for -NaN values and division by zero follow the JVM specification. Division with -integer values drops the remainder of the resultant value. +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* @@ -667,7 +667,7 @@ division: expression '/' expression; [[remainder-operator]] ==== Remainder -Use the `remainder operator '%'` to calculate the *remainder* for division +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. @@ -738,7 +738,7 @@ remainder: expression '%' expression; [[addition-operator]] ==== Addition -Use the `addition operator '+'` to *add* together two numeric type values. Rules +Use the `addition operator '+'` to ADD together two numeric type values. Rules for resultant overflow and NaN values follow the JVM specification. *Errors* @@ -808,7 +808,7 @@ addition: expression '+' expression; [[subtraction-operator]] ==== Subtraction -Use the `subtraction operator '-'` to *subtract* a right-hand side numeric type +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. @@ -879,7 +879,7 @@ subtraction: expression '-' expression; [[left-shift-operator]] ==== Left Shift -Use the `left shift operator '<<'` to *shift* lower order bits to higher order +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. @@ -953,7 +953,7 @@ int type value and truncated to the number of bits of the promoted type value. [[right-shift-operator]] ==== Right Shift -Use the `right shift operator '>>' to *shift* higher order bits to lower order +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. @@ -1028,7 +1028,7 @@ int type value and truncated to the number of bits of the promoted type value. [[unsigned-right-shift-operator]] ==== Unsigned Right Shift -Use the `unsigned right shift operator '>>>'` to *shift* higher order bits to +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. @@ -1103,7 +1103,7 @@ int type value and truncated to the number of bits of the promoted type value. [[bitwise-and-operator]] ==== Bitwise And -Use the `bitwise and operator '&'` to *and* together each bit within two +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` otherwise the resultant bit is `0`. @@ -1183,7 +1183,7 @@ bitwise_and: expression '&' expression; [[bitwise-xor-operator]] ==== Bitwise Xor -Use the `bitwise xor operator '^'` to *xor* together each bit within two integer +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`. @@ -1263,7 +1263,7 @@ bitwise_and: expression '^' expression; [[bitwise-or-operator]] ==== Bitwise Or -Use the `bitwise or operator '|'` to *or* together each bit within two integer +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`. @@ -1273,7 +1273,7 @@ bit is `1` otherwise the resultant bit is `0`. *Bits* -The following table illustrates the resultant bit from the anding of two bits. +The following table illustrates the resultant bit from the oring of two bits. [cols="^1,^1,^1"] |==== diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 8aac90b06dc1f..51db1b7f139b7 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -4,7 +4,7 @@ [[method-call-operator]] ==== Method Call -Use the *method call operator* to call a member method on a +Use the `method call operator '()'` to call a member method on a <> value. Implicit <> is evaluated as necessary per argument during the method call. When a method call is made on a `def` type value, the @@ -34,7 +34,7 @@ arguments: '(' (expression (',' expression)*)? ')'; *Examples* -* Uses of method calls. +* Method calls on different reference types. + [source,Painless] ---- @@ -77,7 +77,7 @@ arguments: '(' (expression (',' expression)*)? ')'; [[field-access-operator]] ==== Field Access -Use the *field access operator* to store a value to or load a value from a +Use the `field access operator '.'` to store a value to or load a value from a <> member field. *Errors* @@ -107,7 +107,7 @@ non-static member fields: * List z ---- -* Uses of the *field access operator*. +* Field access with the `Example` type. + [source,Painless] ---- @@ -147,8 +147,8 @@ non-static member fields: [[null-safe-operator]] ==== Null Safe -Use the *null safe operator* instead of the *method call operator* or *field -access operator* to ensure a reference type value is not `null` before +Use the `null safe operator '?.'` instead of the method call operator or field +access operator to ensure a reference type value is not `null` before a method call or field access. A `null` value will be returned if the reference type value is `null`, otherwise the method call or field access is evaluated. @@ -188,7 +188,7 @@ non-static member fields: * List x ---- -* Use of the *null safe operator* without a `null` value. +* Null safe without a `null` value. + [source,Painless] ---- @@ -204,7 +204,7 @@ non-static member fields: null safe call `factory` on `Example reference` -> `List reference`; store `List reference` to `x`; + -* Use of the *null safe operator* with a `null` value; +* Null safe with a `null` value; + [source,Painless] ---- @@ -222,9 +222,9 @@ non-static member fields: [[list-initialization-operator]] ==== List Initialization -Use the *list initialization operator* to allocate an ArrayList type value with -a set of pre-defined values. Each value used to initialize the ArrayList type -value is converted to a `def` type value when inserted into the ArrayList type +Use the `list initialization operator '[]'` to allocate an `List` type value +with a set of pre-defined values. Each value used to initialize the `List` type +value is converted to a `def` type value when inserted into the `List` type value using the `add` method. The order of specified values is maintained upon insertion. @@ -238,8 +238,7 @@ list_initialization: '[' expression (',' expression)* ']' *Examples* -* Use of the *list initialization operator* to create an empty ArrayList type - value. +* List initialization of an empty `List` type value. + [source,Painless] ---- @@ -251,7 +250,7 @@ list_initialization: '[' expression (',' expression)* ']' implicit cast `ArrayList reference` to `List reference` -> `List reference`; store `List reference` to `empty` + -* Use of the *list initialization operator* with static values. +* List initialization with static values. + [source,Painless] ---- @@ -266,7 +265,7 @@ list_initialization: '[' expression (',' expression)* ']' implicit cast `ArrayList reference` to `List reference` -> `List reference`; store `List reference` to `list` + -* Use of the *list initialization operator* with non-static values. +* List initialization with non-static values. + [source,Painless] ---- @@ -308,14 +307,14 @@ list_initialization: '[' expression (',' expression)* ']' [[list-access-operator]] ==== List Access -Use the *list access operator* as a shortcut for a `set` method call or `get` -method call made on a List type value. +Use the `list access operator '[]'` as a shortcut for a `set` method call or +`get` method call made on a `List` type value. *Errors* -* Use of the *list access operator* on a value that is not a List type value. -* Use of a non-integer type value as an index for an `set` method call or `get` - method call. +* If a value other than a `List` type value is accessed. +* If a non-integer type value is used as an index for a `set` method call or + `get` method call. *Grammar* @@ -326,7 +325,7 @@ list_access: '[' expression ']' *Examples* -* Uses of the *list access operator*. +* List access with the `List` type. + [source,Painless] ---- @@ -373,7 +372,7 @@ list_access: '[' expression ']' implicit cast `def` to `int 5` -> `int 5`; store `int 5` to `z` + -* Uses of the *list access operator* with the `def` type. +* List access with the `def` type. + [source,Painless] ---- @@ -430,11 +429,11 @@ list_access: '[' expression ']' [[map-initialization-operator]] ==== Map Initialization -Use the *map initialization operator* to allocate a HashMap type value with -a set of pre-defined values. Each pair of values used to initialize the HashMap -type value are converted to `def` type values when inserted into the HashMap -type value using the `put` method. The order of specified values is maintained -upon insertion. +Use the `map initialization operator '[:]'` to allocate a `Map` type value with +a set of pre-defined values. Each pair of values used to initialize the `Map` +type value are converted to `def` type values when inserted into the `Map` type +value using the `put` method. The order of specified values is maintained upon +insertion. *Grammar* @@ -447,8 +446,7 @@ key_pair: expression ':' expression *Examples* -* Use of the *map initialization operator* to create an empty HashMap type -value. +* Map initialization of an empty `Map` type value. + [source,Painless] ---- @@ -460,7 +458,7 @@ value. implicit cast `HashMap reference` to `Map reference` -> `Map reference`; store `Map reference` to `empty` + -* Use of the *map initialization operator* with non-static values. +* Map initialization with static values. + [source,Painless] ---- @@ -475,7 +473,7 @@ value. implicit cast `HashMap reference` to `Map reference` -> `Map reference`; store `Map reference` to `map` + -* Use of the *map initialization operator* with non-static values. +* Map initialization with non-static values. + [source,Painless] ---- @@ -522,12 +520,12 @@ value. [[map-access-operator]] ==== Map Access -Use the *map access operator* as a shortcut for a `put` method call or `get` -method call made on a Map type value. +Use the `map access operator '[]'` as a shortcut for a `put` method call or +`get` method call made on a `Map` type value. *Errors* -* Use of the *map access operator* on a value that is not a Map type value. +* If a value other than a `Map` type value is accessed. *Grammar* [source,ANTLR4] @@ -537,7 +535,7 @@ map_access: '[' expression ']' *Examples* -* Uses of the *map access operator*. +* Map access with the `Map` type. + [source,Painless] ---- @@ -575,7 +573,7 @@ map_access: '[' expression ']' implicit cast `def` to `int 5` -> `int 5`; store `int 5` to `z` + -* Uses of the *map access operator* using the `def` type. +* Map access with the `def` type. + [source,Painless] ---- @@ -621,7 +619,7 @@ map_access: '[' expression ']' [[new-instance-operator]] ==== New Instance -Use the *new instance operator* to allocate a +Use the `new instance operator 'new ()'` to allocate a <> instance to the heap and call a specified constructor. Implicit <> is evaluated as necessary per argument during the constructor call. @@ -648,7 +646,7 @@ new_instance: 'new' type '(' (expression (',' expression)*)? ')'; *Examples* -* Uses of the *new instance operator*. +* Allocation of new instances with different types. [source,Painless] ---- @@ -674,8 +672,8 @@ new_instance: 'new' type '(' (expression (',' expression)*)? ')'; [[string-concatenation-operator]] ==== String Concatenation -Use the *string concatenation operator* to concatenate two values together where -at least one of the values is of the <>. +Use the `string concatenation operator '+'` to concatenate two values together +where at least one of the values is a <>. *Grammar* @@ -686,7 +684,7 @@ concatenate: expression '+' expression; *Examples* -* Uses of the *string concatenation operator*. +* String concatenation with different primitive types. + [source,Painless] ---- @@ -708,7 +706,7 @@ concatenate: expression '+' expression; (note the addition is done prior to the concatenation due to precedence and associativity of the specific operations) + -* Uses of the *string concatenation operator* with the `def` type. +* String concatenation with the `def` type. + [source,Painless] ---- @@ -732,8 +730,8 @@ An elvis consists of two expressions. The first expression is evaluated with to check for a `null` value. If the first expression evaluates to `null` then the second expression is evaluated and its value used. If the first expression evaluates to not `null` then the resultant value of the first -expression is used. Use the *elvis operator* as a shortcut for the *conditional -operator*. +expression is used. Use the `elvis operator '?:'` as a shortcut for the +conditional operator. *Errors* @@ -748,7 +746,7 @@ elvis: expression '?:' expression; *Examples* -* Uses of the *elvis operator*. +* Elvis with different reference types. + [source,Painless] ---- From be37bf11796e88f7428e5ce988f6fa271e0516e5 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 5 Jun 2018 14:42:36 -0700 Subject: [PATCH 52/55] Cleaned up array operators based on PR feedback. --- .../painless-operators-array.asciidoc | 60 ++++++++++--------- .../painless-operators-reference.asciidoc | 19 +++--- docs/painless/painless-types.asciidoc | 28 +++++---- 3 files changed, 55 insertions(+), 52 deletions(-) diff --git a/docs/painless/painless-operators-array.asciidoc b/docs/painless/painless-operators-array.asciidoc index 70a36d9ea34a6..1f6a4819b9fec 100644 --- a/docs/painless/painless-operators-array.asciidoc +++ b/docs/painless/painless-operators-array.asciidoc @@ -4,11 +4,11 @@ [[array-initialization-operator]] ==== Array Initialization -Use the *array initialization operator* to allocate a single-dimensional -<> value with a set of pre-defined values. Each value -used to initialize the array type value is cast to the specified type value when -inserted into the array type value. The order of specified values is maintained -upon insertion. +Use the `array initialization operator '[] {}'` to allocate a single-dimensional +<> instance to the heap with a set of pre-defined +elements. Each value used to initialize an element in the array type instance is +cast to the specified element type value upon insertion. The order of specified +values is maintained. *Errors* @@ -25,7 +25,7 @@ expression_list: expression (',' expression); *Example:* -* Use of the *array initialization operator* with static values. +* Array initialization with static values. + [source,Painless] ---- @@ -40,7 +40,7 @@ expression_list: expression (',' expression); store `int 3` to `index [2]` of `1-d int array reference`; store `1-d int array reference` to `x`; + -* Use of the *array initialization operator* with non-static values. +* Array initialization with non-static values. + [source,Painless] ---- @@ -87,19 +87,19 @@ expression_list: expression (',' expression); [[array-access-operator]] ==== Array Access -Use the *array access operator* to store a value to or load a value from an -<> value. Each value of an array type value is accessed -with an int type value to specify the index to store/load. The range of values -within an array that are accessible is `[0, size)` where size is the number of -values specified at the time of allocation. Use a negative int type value as an -index to access an value in reverse from the end of an array type value within a -range of `[-size, -1]`. +Use the `array access operator '[]'` to store a value to or load a value from +an <> value. Each element of an array type value is +accessed with an `int` type value to specify the index to store/load. The range +of elements within an array that are accessible is `[0, size)` where size is the +number of elements specified at the time of allocation. Use a negative `int` +type value as an index to access an element in reverse from the end of an array +type value within a range of `[-size, -1]`. *Errors* -* If a value other than an int type value or a value that is castable to an int - type value is provided as an index. -* If a value is accessed outside of the valid ranges. +* If a value other than an `int` type value or a value that is castable to an + `int` type value is provided as an index. +* If an element is accessed outside of the valid ranges. *Grammar* @@ -110,7 +110,7 @@ brace_access: '[' expression ']' *Examples* -* Uses of the *array access operator*. +* Array access with a single-dimensional array. + [source,Painless] ---- @@ -145,7 +145,7 @@ brace_access: '[' expression ']' load from `index [1]` of `1-d int array reference` -> `int 5`; store `int 5` to `i`; + -* Uses of the *array access operator* with the `def` type. +* Array access with the `def` type. + [source,Painless] ---- @@ -195,7 +195,7 @@ brace_access: '[' expression ']' implicit cast `int 5` to `def`; store `def` to `z`; + -* Uses of the *array access operator* with a multi-dimensional array. +* Array access with a multi-dimensional array. + [source,Painless] ---- @@ -218,14 +218,15 @@ brace_access: '[' expression ']' [[array-length-operator]] ==== Array Length -Array type values contain a read-only member field named `length`. The field -`length` is an int type value storing the size of the array. Use the -<> to load the field `length` +An array type value contains a read-only member field named `length`. The +`length` field stores the size of the array as an `int` type value where size is +the number of elements specified at the time of allocation. Use the +<> to load the field `length` from an array type value. *Examples* -* Use of the `length` field. +* Access the `length` field. + [source,Painless] ---- @@ -244,10 +245,11 @@ from an array type value. [[new-array-operator]] ==== New Array -Use the *new array operator* to allocate a new array type instance to the heap. -Specify each dimension with the `[` and `]` tokens following the type name. The -size of each dimension is specified by an int type value in between the `[` and -`]` tokens. +Use the `new array operator 'new []'` to allocate an array type instance to +the heap. Specify the element type following the `new` token. Specify each +dimension with the `[` and `]` tokens following the element type name. The size +of each dimension is specified by an `int` type value in between each set of `[` +and `]` tokens. *Errors* @@ -263,7 +265,7 @@ new_array: 'new' TYPE ('[' expression ']')+; *Examples* -* Uses of the *new array operator*. +* Allocation of different array types. + [source,Painless] ---- diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index 047bd2539b51e..5158465fccd59 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -222,11 +222,11 @@ non-static member fields: [[list-initialization-operator]] ==== List Initialization -Use the `list initialization operator '[]'` to allocate an `List` type value -with a set of pre-defined values. Each value used to initialize the `List` type -value is converted to a `def` type value when inserted into the `List` type -value using the `add` method. The order of specified values is maintained upon -insertion. +Use the `list initialization operator '[]'` to allocate an `List` type instance +to the heap with a set of pre-defined values. Each value used to initialize the +`List` type instance is cast to a `def` type value upon insertion into the +`List` type instance using the `add` method. The order of the specified values +is maintained. *Grammar* @@ -429,11 +429,10 @@ list_access: '[' expression ']' [[map-initialization-operator]] ==== Map Initialization -Use the `map initialization operator '[:]'` to allocate a `Map` type value with -a set of pre-defined values. Each pair of values used to initialize the `Map` -type value are converted to `def` type values when inserted into the `Map` type -value using the `put` method. The order of specified values is maintained upon -insertion. +Use the `map initialization operator '[:]'` to allocate a `Map` type instance to +the heap with a set of pre-defined values. Each pair of values used to +initialize the `Map` type instance are cast to `def` type values upon insertion +into the `Map` type instance using the `put` method. *Grammar* diff --git a/docs/painless/painless-types.asciidoc b/docs/painless/painless-types.asciidoc index a1f6aeec6ce58..65ae9b3f70360 100644 --- a/docs/painless/painless-types.asciidoc +++ b/docs/painless/painless-types.asciidoc @@ -386,10 +386,11 @@ void addToList(List l, def d) { ==== Array Type An array type is a specialized reference type where an array type instance -represents a series of values allocated to the heap. All values in an array -type instance are of the same type. Each value is assigned an index from within -the range `[0, length)` where length is the total number of values allocated for -the array type instance. +contains a series of values allocated to the heap. Each value in an array type +instance is defined as an element. All elements in an array type instance are of +the same type (element type) specified as part of declaration. Each element is +assigned an index within the range `[0, length)` where length is the total +number of elements allocated for an array type instance. Use the <> or the <> to allocate an @@ -405,17 +406,18 @@ as an argument to a method/function call to indicate the argument refers to no array type instance. Use the <> to retrieve the length -of an array type value as an int type value. Use the +of an array type value as an `int` type value. Use the <> to load from and store to -individual values within an array type value. +an individual element within an array type instance. When an array type instance is allocated with multiple dimensions using the -range `[2, d]` where `d >= 2`, each dimension in the range `[1, d-1]` is also -an array type. The array type of each dimension, `n`, is an array type with the -number of dimensions equal to `d-n`. For example, consider `int[][][]` with 3 -dimensions. The 3rd dimension, `d-3`, is the primitive type `int`. The 2nd -dimension, `d-2`, is the array type `int[]`. And the 1st dimension, `d-1` is -the array type `int[][]`. +range `[2, d]` where `d >= 2`, each element within each dimension in the range +`[1, d-1]` is also an array type. The element type of each dimension, `n`, is an +array type with the number of dimensions equal to `d-n`. For example, consider +`int[][][]` with 3 dimensions. Each element in the 3rd dimension, `d-3`, is the +primitive type `int`. Each element in the 2nd dimension, `d-2`, is the array +type `int[]`. And each element in the 1st dimension, `d-1` is the array type +`int[][]`. *Examples* @@ -450,7 +452,7 @@ the array type `int[][]`. -> `1-d float array reference @1`; store `float 1.0` to `index [0]` of `1-d float array reference @1` + -* Use of a multi-dimensional array. +* General use of a multi-dimensional array. + [source,Painless] ---- From c35e9774efae7eecc0a278e336a8732828da3175 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 5 Jun 2018 15:30:19 -0700 Subject: [PATCH 53/55] Clean up boolean operators based on PR feedback. --- .../painless-operators-boolean.asciidoc | 126 +++++++++--------- .../painless-operators-reference.asciidoc | 4 +- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/docs/painless/painless-operators-boolean.asciidoc b/docs/painless/painless-operators-boolean.asciidoc index 3a20a929990c0..1223a8d56e78d 100644 --- a/docs/painless/painless-operators-boolean.asciidoc +++ b/docs/painless/painless-operators-boolean.asciidoc @@ -4,8 +4,8 @@ [[boolean-not-operator]] ==== Boolean Not -Use the *boolean not operator* to flip a `boolean` type value from `true` to -`false` or `false` to `true`. +Use the `boolean not operator '!'` to NOT a `boolean` type value where `true` is +flipped to `false` and `false` is flipped to `true`. *Errors* @@ -30,7 +30,7 @@ boolean_not: '!' expression; *Examples* -* Uses of the *boolean not operator*. +* Boolean not with the `boolean` type. + [source,Painless] ---- @@ -45,7 +45,7 @@ boolean_not: '!' expression; boolean not `boolean true` -> `boolean false`; store `boolean false` to `y` + -* Uses of the *boolean not operator* with the `def` type. +* Boolean not with the `def` type. + [source,Painless] ---- @@ -66,7 +66,7 @@ boolean_not: '!' expression; [[greater-than-operator]] ==== Greater Than -Use the *greater than operator* to compare two numeric type values where a +Use the `greater than operator '>'` to COMPARE two numeric type values where a resultant `boolean` type value is `true` if the left-hand side value is greater than to the right-hand side value and `false` otherwise. @@ -99,7 +99,7 @@ greater_than: expression '>' expression; *Examples* -* Uses of the *greater than operator*. +* Greater than with different numeric types. + [source,Painless] ---- @@ -119,7 +119,7 @@ greater_than: expression '>' expression; greater than `double 6.0 @1` and `double 6.0 @0` -> `boolean false`; store `boolean false` to `x` + -* Uses of the *greater than operator* with the `def` type. +* Greater than with `def` type. + [source,Painless] ---- @@ -153,7 +153,7 @@ greater_than: expression '>' expression; [[greater-than-or-equal-operator]] ==== Greater Than Or Equal -Use the *greater than or equal operator* to compare two numeric type values +Use the `greater than or equal operator '>='` to COMPARE two numeric type values where a resultant `boolean` type value is `true` if the left-hand side value is greater than or equal to the right-hand side value and `false` otherwise. @@ -186,7 +186,7 @@ greater_than_or_equal: expression '>=' expression; *Examples* -* Uses of the *greater than or equal operator*. +* Greater than or equal with different numeric types. + [source,Painless] ---- @@ -206,7 +206,7 @@ greater_than_or_equal: expression '>=' expression; greater than or equal `double 6.0 @1` and `double 6.0 @0` -> `boolean true`; store `boolean true` to `x` + -* Uses of the *greater than operator or equal* with the `def` type. +* Greater than or equal with the `def` type. + [source,Painless] ---- @@ -240,7 +240,7 @@ greater_than_or_equal: expression '>=' expression; [[less-than-operator]] ==== Less Than -Use the *less than operator* to compare two numeric type values where a +Use the `less than operator '<'` to COMPARE two numeric type values where a resultant `boolean` type value is `true` if the left-hand side value is less than to the right-hand side value and `false` otherwise. @@ -273,7 +273,7 @@ less_than: expression '<' expression; *Examples* -* Uses of the *less than operator*. +* Less than with different numeric types. + [source,Painless] ---- @@ -293,7 +293,7 @@ less_than: expression '<' expression; less than `double 6.0 @1` and `double 6.0 @0` -> `boolean false`; store `boolean false` to `x` + -* Uses of the *less than operator* with the `def` type. +* Less than with the `def` type. + [source,Painless] ---- @@ -327,7 +327,7 @@ less_than: expression '<' expression; [[less-than-or-equal-operator]] ==== Less Than Or Equal -Use the *less than or equal operator* to compare two numeric type values +Use the `less than or equal operator '<='` to COMPARE two numeric type values where a resultant `boolean` type value is `true` if the left-hand side value is less than or equal to the right-hand side value and `false` otherwise. @@ -360,7 +360,7 @@ greater_than_or_equal: expression '<=' expression; *Examples* -* Uses of the *less than or equal operator*. +* Less than or equal with different numeric types. + [source,Painless] ---- @@ -380,7 +380,7 @@ greater_than_or_equal: expression '<=' expression; less than or equal `double 6.0 @1` and `double 6.0 @0` -> `boolean true`; store `boolean true` to `x` + -* Uses of the *less than operator or equal* with the `def` type. +* Less than or equal with the `def` type. + [source,Painless] ---- @@ -414,7 +414,7 @@ greater_than_or_equal: expression '<=' expression; [[instanceof-operator]] ==== Instanceof -Use the *instanceof operator* to compare the variable/field type to a +Use the `instanceof operator` to COMPARE the variable/field type to a specified reference type using the reference type name where a resultant `boolean` type value is `true` if the variable/field type is the same as or a descendant of the specified reference type and false otherwise. @@ -432,7 +432,7 @@ instance_of: ID 'instanceof' TYPE; *Examples* -* Uses of the *instanceof operator*. +* Instance of with different reference types. + [source,Painless] ---- @@ -457,7 +457,7 @@ instance_of: ID 'instanceof' TYPE; store `true` to `b`; (note `HashMap` is a descendant of `Map`) + -* Uses of the *instanceof operator* with the `def` type. +* Instance of with the `def` type. + [source,Painless] ---- @@ -486,14 +486,14 @@ instance_of: ID 'instanceof' TYPE; [[equality-equals-operator]] ==== Equality Equals -Use the *equality equals operator* to compare two values where a resultant +Use the `equality equals operator '=='` to COMPARE two values where a resultant `boolean` type value is `true` if the two values are equal and `false` otherwise. The member method, `equals`, is implicitly called when the values are reference type values where the first value is the target of the call and the second value is the argument. This operation is null-safe where if both values are `null` the resultant `boolean` type value is `true`, and if only one value is `null` the resultant `boolean` type value is `false`. A valid comparison is -between boolean type values, numeric type values, or reference type values. +between `boolean` type values, numeric type values, or reference type values. *Errors* @@ -527,7 +527,7 @@ equality_equals: expression '==' expression; *Examples* -* Uses of the *equality equals operator* with `boolean` type values. +* Equality equals with the `boolean` type. + [source,Painless] ---- @@ -550,7 +550,7 @@ equality_equals: expression '==' expression; -> `boolean false`; store `boolean false` to `b` + -* Uses of the *equality equals operator* with primitive type values. +* Equality equals with primitive types. + [source,Painless] ---- @@ -575,7 +575,7 @@ equality_equals: expression '==' expression; equality equals `int 1 @0` and `int 1 @1` -> `boolean true`; store `boolean true` to `c` + -* Uses of the *equality equals operator* with reference type values. +* Equal equals with reference types. + [source,Painless] ---- @@ -611,7 +611,7 @@ equality_equals: expression '==' expression; -> `boolean true`; store `boolean true` to `c` + -* Uses of the *equality equals operator* with `null` values. +* Equality equals with `null`. + [source,Painless] ---- @@ -643,7 +643,7 @@ equality_equals: expression '==' expression; -> `boolean false`; store `boolean false` to `c` + -* Uses of the *equality equals operator* with the `def` type. +* Equality equals with the `def` type. + [source, Painless] ---- @@ -687,15 +687,15 @@ equality_equals: expression '==' expression; [[equality-not-equals-operator]] ==== Equality Not Equals -Use the *equality not equals operator* to compare two values where a resultant -`boolean` type value is `true` if the two values are not equal and `false` -otherwise. The member method, `equals`, is implicitly called when the values are -reference type values where the first value is the target of the call and the -second value is the argument with the resultant `boolean` type value flipped. -This operation is null-safe where if both values are `null` the resultant -`boolean` type value is `false`, and if only one value is `null` the resultant -`boolean` type value is `true`. A valid comparison is between boolean type -values, numeric type values, or reference type values. +Use the `equality not equals operator '!='` to COMPARE two values where a +resultant `boolean` type value is `true` if the two values are NOT equal and +`false` otherwise. The member method, `equals`, is implicitly called when the +values are reference type values where the first value is the target of the call +and the second value is the argument with the resultant `boolean` type value +flipped. This operation is `null-safe` where if both values are `null` the +resultant `boolean` type value is `false`, and if only one value is `null` the +resultant `boolean` type value is `true`. A valid comparison is between boolean +type values, numeric type values, or reference type values. *Errors* @@ -729,7 +729,7 @@ equality_not_equals: expression '!=' expression; *Examples* -* Uses of the *equality not equals operator* with `boolean` type values. +* Equality not equals with the `boolean` type. + [source,Painless] ---- @@ -751,7 +751,7 @@ equality_not_equals: expression '!=' expression; equality not equals `boolean true` and `boolean false` -> `boolean true`; store `boolean true` to `b` + -* Uses of the *equality not equals operator* with primitive type values. +* Equality not equals with primitive types. + [source,Painless] ---- @@ -776,7 +776,7 @@ equality_not_equals: expression '!=' expression; equality not equals `int 1 @0` and `int 1 @1` -> `boolean false`; store `boolean false` to `c` + -* Uses of the *equality not equals operator* with reference type values. +* Equality not equals with reference types. + [source,Painless] ---- @@ -814,7 +814,7 @@ equality_not_equals: expression '!=' expression; boolean not `boolean true` -> `boolean false`; store `boolean false` to `c` + -* Uses of the *equality not equals operator* with `null` values. +* Equality not equals with `null`. + [source,Painless] ---- @@ -847,7 +847,7 @@ equality_not_equals: expression '!=' expression; boolean not `boolean false` -> `boolean true`; store `boolean true` to `c` + -* Uses of the *equality not equals operator* with the `def` type. +* Equality not equals with the `def` type. + [source, Painless] ---- @@ -891,11 +891,11 @@ equality_not_equals: expression '!=' expression; [[identity-equals-operator]] ==== Identity Equals -Use the *identity equals operator* to compare two values where a resultant +Use the `identity equals operator '==='` to COMPARE two values where a resultant `boolean` type value is `true` if the two values are equal and `false` otherwise. A reference type value is equal to another reference type value if both values refer to same instance on the heap or if both values are `null`. A -valid comparison is between boolean type values, numeric type values, or +valid comparison is between `boolean` type values, numeric type values, or reference type values. *Errors* @@ -930,7 +930,7 @@ identity_equals: expression '===' expression; *Examples* -* Uses of the *identity equals operator* with reference type values. +* Identity equals with reference types. + [source,Painless] ---- @@ -965,7 +965,7 @@ identity_equals: expression '===' expression; (note `List reference @0` and `List reference @1` refer to the same instance) + -* Uses of the *identity equals operator* with `null` values. +* Identity equals with `null`. + [source,Painless] ---- @@ -996,7 +996,7 @@ identity_equals: expression '===' expression; identity equals `Object reference` and `null` -> `boolean false`; store `boolean false` to `c` + -* Uses of the *identity equals operator* with the `def` type. +* Identity equals with the `def` type. + [source, Painless] ---- @@ -1038,12 +1038,12 @@ identity_equals: expression '===' expression; [[identity-not-equals-operator]] ==== Identity Not Equals -Use the *identity not equals operator* to compare two values where a resultant -`boolean` type value is `true` if the two values are not equal and `false` -otherwise. A reference type value is not equal to another reference type value -if both values refer to different instances on the heap or if one value is -`null` and the other is not. A valid comparison is between boolean type values, -numeric type values, or reference type values. +Use the `identity not equals operator '!=='` to COMPARE two values where a +resultant `boolean` type value is `true` if the two values are NOT equal and +`false` otherwise. A reference type value is not equal to another reference type +value if both values refer to different instances on the heap or if one value is +`null` and the other is not. A valid comparison is between `boolean` type +values, numeric type values, or reference type values. *Errors* @@ -1077,7 +1077,7 @@ identity_not_equals: expression '!==' expression; *Examples* -* Uses of the *identity not equals operator* with reference type values. +* Identity not equals with reference type values. + [source,Painless] ---- @@ -1112,7 +1112,7 @@ identity_not_equals: expression '!==' expression; (note `List reference @0` and `List reference @1` refer to the same instance) + -* Uses of the *identity not equals operator* with `null` values. +* Identity not equals with `null`. + [source,Painless] ---- @@ -1143,7 +1143,7 @@ identity_not_equals: expression '!==' expression; identity not equals `Object reference` and `null` -> `boolean true`; store `boolean true` to `c` + -* Uses of the *identity not equals operator* with the `def` type. +* Identity not equals with the `def` type. + [source, Painless] ---- @@ -1185,7 +1185,7 @@ identity_not_equals: expression '!==' expression; [[boolean-xor-operator]] ==== Boolean Xor -Use the *boolean xor operator* to boolean xor together two `boolean` type values +Use the `boolean xor operator '^'` to XOR together two `boolean` type values where if one `boolean` type value is `true` and the other is `false` the resultant `boolean` type value is `true` and `false` otherwise. @@ -1212,7 +1212,7 @@ boolean_xor: expression '^' expression; *Examples* -* Uses of the *boolean xor operator*. +* Boolean xor with the `boolean` type. + [source,Painless] ---- @@ -1232,7 +1232,7 @@ boolean_xor: expression '^' expression; boolean xor `boolean true @0` and `boolean true @1` -> `boolean false`; store `boolean false` to `y` + -* Uses of the *boolean xor operator* with the `def` type. +* Boolean xor with the `def` type. + [source,Painless] ---- @@ -1261,7 +1261,7 @@ boolean_xor: expression '^' expression; [[boolean-and-operator]] ==== Boolean And -Use the *boolean and operator* to boolean and together two `boolean` type values +Use the `boolean and operator '&&'` to AND together two `boolean` type values where if both `boolean` type values are `true` the resultant `boolean` type value is `true` and `false` otherwise. @@ -1288,7 +1288,7 @@ boolean_and: expression '&&' expression; *Examples* -* Uses of the *boolean and operator*. +* Boolean and with the `boolean` type. + [source,Painless] ---- @@ -1310,7 +1310,7 @@ boolean_and: expression '&&' expression; boolean and `boolean true` and `boolean false` -> `boolean false`; store `boolean false` to `y` + -* Uses of the *boolean and operator* with the `def` type. +* Boolean and with the `def` type. + [source,Painless] ---- @@ -1342,7 +1342,7 @@ boolean_and: expression '&&' expression; [[boolean-or-operator]] ==== Boolean Or -Use the *boolean or operator* to boolean or together two `boolean` type values +Use the `boolean or operator '||'` to OR together two `boolean` type values where if either one of the `boolean` type values is `true` the resultant `boolean` type value is `true` and `false` otherwise. @@ -1368,7 +1368,7 @@ boolean_and: expression '||' expression; *Examples* -* Uses of the *boolean or operator*. +* Boolean or with the `boolean` type. + [source,Painless] ---- @@ -1390,7 +1390,7 @@ boolean_and: expression '||' expression; boolean or `boolean false @0` and `boolean false @1` -> `boolean false`; store `boolean false` to `y` + -* Uses of the *boolean or operator* with the `def` type. +* Boolean or with the `def` type. + [source,Painless] ---- diff --git a/docs/painless/painless-operators-reference.asciidoc b/docs/painless/painless-operators-reference.asciidoc index d6491db90e47f..487fcce15f31b 100644 --- a/docs/painless/painless-operators-reference.asciidoc +++ b/docs/painless/painless-operators-reference.asciidoc @@ -148,7 +148,7 @@ non-static member fields: ==== Null Safe Use the `null safe operator '?.'` instead of the method call operator or field -access operator to ensure a reference type value is not `null` before +access operator to ensure a reference type value is `non-null` before a method call or field access. A `null` value will be returned if the reference type value is `null`, otherwise the method call or field access is evaluated. @@ -728,7 +728,7 @@ concatenate: expression '+' expression; An elvis consists of two expressions. The first expression is evaluated with to check for a `null` value. If the first expression evaluates to `null` then the second expression is evaluated and its value used. If the first -expression evaluates to not `null` then the resultant value of the first +expression evaluates to `non-null` then the resultant value of the first expression is used. Use the `elvis operator '?:'` as a shortcut for the conditional operator. From 0760a41c116f919a7ee4e16d7d2dddbf7ddaab8b Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Tue, 5 Jun 2018 16:11:09 -0700 Subject: [PATCH 54/55] Accidentally left in modified test. --- .../src/test/java/org/elasticsearch/painless/AdditionTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java index 86de8b7242107..f124d088bf2f2 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AdditionTests.java @@ -24,7 +24,6 @@ public class AdditionTests extends ScriptTestCase { public void testBasics() throws Exception { - assertEquals(false, exec("HashMap x = null; ArrayList y = null; x == y")); assertEquals(3.0, exec("double x = 1; byte y = 2; return x + y;")); } From c361792cd2079f0ac323947748037c2802ab6206 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Thu, 7 Jun 2018 14:03:11 -0700 Subject: [PATCH 55/55] Response to more PR feedback. --- docs/painless/painless-casting.asciidoc | 2 +- docs/painless/painless-literals.asciidoc | 2 +- docs/painless/painless-scripts.asciidoc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/painless/painless-casting.asciidoc b/docs/painless/painless-casting.asciidoc index 61f1eed03efe0..4bcd14cbfc6a1 100644 --- a/docs/painless/painless-casting.asciidoc +++ b/docs/painless/painless-casting.asciidoc @@ -347,7 +347,7 @@ reference type to its corresponding primitive type. Implicit boxing/unboxing occurs during the following operations: -* Conversions between a `def` type and a primitive type is implicitly +* Conversions between a `def` type and a primitive type are implicitly boxed/unboxed as necessary, though this is referred to as an implicit cast throughout the documentation. * Method/function call arguments are implicitly boxed/unboxed as necessary. diff --git a/docs/painless/painless-literals.asciidoc b/docs/painless/painless-literals.asciidoc index 0be67968dbe62..621fc152be956 100644 --- a/docs/painless/painless-literals.asciidoc +++ b/docs/painless/painless-literals.asciidoc @@ -120,6 +120,6 @@ STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) [[character-literals]] ==== Characters -A character literal is not specified directly. Instead, use the +Character literals are not specified directly. Instead, use the <> to convert a `String` type value into a `char` type value. diff --git a/docs/painless/painless-scripts.asciidoc b/docs/painless/painless-scripts.asciidoc index 7b99c0f02b0fb..87e5b60159060 100644 --- a/docs/painless/painless-scripts.asciidoc +++ b/docs/painless/painless-scripts.asciidoc @@ -3,4 +3,4 @@ Scripts are composed of one-to-many <> and are run in a sandbox that determines what local variables are immediately available -along with what API's are whitelisted for use. \ No newline at end of file +along with what APIs are whitelisted for use. \ No newline at end of file