Painless Spec Documentation Clean Up (#29441)

Created a flatter structure for the different sections.  Cleaned up comments, keywords, and literals.  Used callouts for examples where it made sense.
This commit is contained in:
Jack Conradson 2018-04-17 12:16:08 -07:00 committed by GitHub
parent 7969eb7db7
commit c833167d84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 385 additions and 385 deletions

View File

@ -5,39 +5,6 @@ include::../Versions.asciidoc[]
include::painless-getting-started.asciidoc[]
// include::painless-examples.asciidoc[]
// include::painless-design.asciidoc[]
include::painless-lang-spec.asciidoc[]
include::painless-syntax.asciidoc[]
include::painless-api-reference.asciidoc[]
////
Proposed Outline (WIP)
Getting Started with Painless
Accessing Doc Values
Updating Fields
Working with Dates
Using Regular Expressions
Debugging Painless Scripts
Example Scripts
Using Painless in Script Fields
Using Painless in Watches
Using Painless in Function Score Queries
Using Painless in Script Queries
Using Painless When Updating Docs
Using Painless When Reindexing
How Painless Works
Painless Architecture
Dispatching Functions
Painless Language Specification
Painless API
////
Painless API Reference

View File

@ -1,17 +1,13 @@
["appendix",id="painless-api-reference"]
= Painless API Reference
[[painless-api-reference]]
== Painless API Reference
Painless has a strict whitelist for methods and
classes to make sure that all painless scripts are secure and fast. Most of
these methods are exposed directly from the JRE while others are part of
Elasticsearch or Painless itself. Below is a list of all available methods
grouped under the classes on which you can call them. Clicking on the method
name takes you to the documentation for the method.
NOTE: Methods defined in the JRE also have a `(java 9)` link which can be used
to see the method's documentation in Java 9 while clicking on the method's name
goes to the Java 8 documentation. Usually these aren't different but it is
worth going to the version that matches the version of Java you are using to
run Elasticsearch just in case.
Painless has a strict whitelist for methods and classes to ensure all
painless scripts are secure. Most of these methods are exposed directly
from the Java Runtime Enviroment (JRE) while others are part of
Elasticsearch or Painless itself. Below is a list of all available
classes grouped with their respected methods. Clicking on the method
name takes you to the documentation for that specific method. Methods
defined in the JRE also have a `(java 9)` link which can be used to see
the method's documentation in Java 9.
include::painless-api-reference/index.asciidoc[]

View File

@ -0,0 +1,172 @@
[[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:*
[source,ANTLR4]
----
cast: '(' TYPE ')' expression
----
[[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.
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.
|====
| | 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 |
|====
Example(s)
[source,Java]
----
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.
----
[[reference-casting]]
==== Reference 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_.
*Examples:*
[source,Java]
----
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
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.
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]
----
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
----
[[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:
* 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:*
[source,Java]
----
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
----
[[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.
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:*
[source,Java]
----
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.
----

View File

@ -0,0 +1,51 @@
[[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.
*Grammar*
[source,ANTLR4]
----
SINGLE_LINE_COMMENT: '//' .*? [\n\r];
MULTI_LINE_COMMENT: '/*' .*? '*/';
----
*Examples*
Single-line comments.
[source,Painless]
----
// single-line comment
int value; // single-line comment
----
Multi-line comments.
[source,Painless]
----
/* multi-
line
comment */
int value; /* multi-
line
comment */ value = 0;
int value; /* multi-line
comment */
/* multi-line
comment */ int value;
int value; /* multi-line
comment */ value = 0;
int value; /* multi-line comment */ value = 0;
----

View File

@ -2,7 +2,7 @@ _Painless_ is a simple, secure scripting language designed specifically for use
with Elasticsearch. It is the default scripting language for Elasticsearch and
can safely be used for inline and stored scripts. For a detailed description of
the Painless syntax and language features, see the
{painless}/painless-specification.html[Painless Language Specification].
{painless}/painless-lang-spec.html[Painless Language Specification].
[[painless-features]]
You can use Painless anywhere scripts can be used in Elasticsearch. Painless

View File

@ -1,7 +1,6 @@
[[painless-syntax]]
=== Painless Syntax
[[painless-general-syntax]]
=== General Syntax
[float]
[[control-flow]]
==== Control flow
@ -17,7 +16,6 @@ for (item : list) {
}
---------------------------------------------------------
[float]
[[functions]]
==== Functions
@ -32,7 +30,6 @@ if (isNegative(someVar)) {
}
---------------------------------------------------------
[float]
[[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].
@ -49,7 +46,6 @@ list.sort(Integer::compare);
You can make method references to functions within the script with `this`,
for example `list.sort(this::mycompare)`.
[float]
[[patterns]]
==== Patterns
@ -62,7 +58,6 @@ are always constants and compiled efficiently a single time.
Pattern p = /[aeiou]/
---------------------------------------------------------
[float]
[[pattern-flags]]
===== Pattern flags
@ -84,34 +79,3 @@ Pattern class] using these characters:
|`u` | UNICODE_CASE | `'Ɛ' ==~ /ɛ/iu`
|`x` | COMMENTS (aka extended) | `'a' ==~ /a #comment/x`
|=======================================================================
[float]
[[painless-deref]]
==== Dereferences
Like lots of languages, Painless uses `.` to reference fields and call methods:
[source,painless]
---------------------------------------------------------
String foo = 'foo';
TypeWithGetterOrPublicField bar = new TypeWithGetterOrPublicField()
return foo.length() + bar.x
---------------------------------------------------------
Like Groovy, Painless uses `?.` to perform null-safe references, with the
result being `null` if the left hand side is `null`:
[source,painless]
---------------------------------------------------------
String foo = null;
return foo?.length() // Returns null
---------------------------------------------------------
Unlike Groovy, Painless doesn't support writing to `null` values with this
operator:
[source,painless]
---------------------------------------------------------
TypeWithSetterOrPublicField foo = null;
foo?.x = 'bar' // Compile error
---------------------------------------------------------

View File

@ -0,0 +1,13 @@
[[painless-keywords]]
=== Keywords
The keywords in the table below are reserved for built-in language
features. These keywords cannot be used as <<identifiers, identifiers>> or
<<painless-types, types>>.
[cols="^1,^1,^1,^1,^1"]
|====
| if | else | while | do | for
| in | continue | break | return | new
| try | catch | throw | this | instanceof
|====

View File

@ -1,73 +1,34 @@
[[painless-specification]]
[[painless-lang-spec]]
== Painless Language Specification
Painless uses a Java-style syntax that is similar to Groovy. In fact, most
Painless scripts are also valid Groovy, and simple Groovy scripts are typically
valid Painless. This specification assumes you have at least a passing
familiarity with Java and related languages.
Painless is essentially a subset of Java with some additional scripting
language features that make scripts easier to write. However, there are some
important differences, particularly with the casting model. For more detailed
Painless is a scripting language designed for security and performance.
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,
refer to the corresponding topics in the
https://docs.oracle.com/javase/specs/jls/se8/html/index.html[Java Language
Specification].
Painless scripts are parsed and compiled using the http://www.antlr.org/[ANTLR4]
and http://asm.ow2.org/[ASM] libraries. Painless scripts are compiled directly
into Java byte code and executed against a standard Java Virtual Machine. This
specification uses ANTLR4 grammar notation to describe the allowed syntax.
and http://asm.ow2.org/[ASM] libraries. Scripts are compiled directly
into Java Virtual Machine (JVM) byte code and executed against a standard JVM.
This specification uses ANTLR4 grammar notation to describe the allowed syntax.
However, the actual Painless grammar is more compact than what is shown here.
[float]
[[comments]]
==== Comments
include::painless-comments.asciidoc[]
Painless supports both single-line and multi-line comments. You can include
comments anywhere within a script.
Single-line comments are preceded by two slashes: `// comment`. They can be
placed anywhere on a line. All characters from the two slashes to the end of
the line are ignored.
Multi-line comments are preceded by a slash-star `/*` and closed by
star-slash `*/`. Multi-line comments can start anywhere on a line. All
characters from the opening `/*` to the closing `*/` are ignored.
*Examples:*
[source,Java]
----
// single-line comment
<code> // single-line comment
/* multi-
line
comment */
<code> /* multi-line
comment */ <code>
<code> /* multi-line comment */ <code>
----
[float]
[[keywords]]
==== Keywords
Painless reserves the following keywords for built-in language features.
These keywords cannot be used in other contexts, such as identifiers.
[cols="^1,^1,^1,^1,^1"]
|====
| if | else | while | do | for
| in | continue | break | return | new
| try | catch | throw | this | instanceof
|====
include::painless-keywords.asciidoc[]
include::painless-literals.asciidoc[]
include::painless-variables.asciidoc[]
include::painless-types.asciidoc[]
include::painless-casting.asciidoc[]
include::painless-operators.asciidoc[]
include::painless-general-syntax.asciidoc[]

View File

@ -1,94 +1,143 @@
[[literals]]
[[painless-literals]]
=== Literals
Literals are values that you can specify directly in Painless scripts.
Use literals to specify different types of values directly in a script.
[[integers]]
==== Integers
Specify integer literals in decimal, octal, or hex notation. Use the following
single letter designations to specify the primitive type: `l` for `long`, `f`
for `float`, and `d` for `double`. If not specified, the type defaults to
`int` (with the exception of certain assignments described later).
Use integer literals to specify an integer value in decimal, octal, or hex
notation of the <<primitive-types, primitive types>> `int`, `long`, `float`,
or `double`. Use the following single letter designations to specify the
<<primitive-types, 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:*
*Grammar*
[source,ANTLR4]
----
INTEGER: '-'? ( '0' | [1-9] [0-9]* ) [lLfFdD]?;
OCTAL: '-'? '0' [0-7]+ [lL]?;
HEX: '-'? '0' [xX] [0-9a-fA-F]+ [lL]?;
OCTAL: '-'? '0' [0-7]+ [lL]?;
HEX: '-'? '0' [xX] [0-9a-fA-F]+ [lL]?;
----
*Examples:*
[source,Java]
*Examples*
Integer literals.
[source,Painless]
----
0 // integer literal of 0
0D // double literal of 0.0
1234L // long literal of 1234
-90F // float literal of -90.0
-022 // integer literal of -18 specified in octal
0xF2A // integer literal of 3882
0 <1>
0D <2>
1234L <3>
-90f <4>
-022 <5>
0xF2A <6>
----
[[floating-point-values]]
==== Floating Point Values
<1> `int 0`
<2> `double 0.0`
<3> `long 1234`
<4> `float -90.0`
<5> `int -18` in octal
<6> `int 3882` in hex
Specify floating point literals using the following single letter designations
for the primitive type: `f` for `float` and `d` for `double`.
If not specified, the type defaults to `double`.
[[floats]]
==== Floats
*Grammar:*
Use floating point literals to specify a floating point value of the
<<primitive-types, primitive types>> `float` or `double`. Use the following
single letter designations to specify the <<primitive-types, 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]+)? ( [eE] [+\-]? [0-9]+ )? [fFdD]?;
DECIMAL: '-'? ( '0' | [1-9] [0-9]* ) (DOT [0-9]+)? EXPONENT? [fFdD]?;
EXPONENT: ( [eE] [+\-]? [0-9]+ );
----
*Examples:*
[source,Java]
*Examples*
Floating point literals.
[source,Painless]
----
0.0 // double value of 0.0
1E6 // double value of 1000000
0.977777 // double value of 0.97777
-126.34 // double value of -126.34
89.9F // float value of 89.9
0.0 <1>
1E6 <2>
0.977777 <3>
-126.34 <4>
89.9F <5>
----
<1> `double 0.0`
<2> `double 1000000.0` in exponent notation
<3> `double 0.977777`
<4> `double -126.34`
<5> `float 89.9`
[[strings]]
==== Strings
Specify literal string with either single or double quotes. In double-quoted
literal strings, you can escape double-quotes with a backslash to include them
in the string. Similarly, you escape single quotes with a backslash in
single-quoted literal strings. Backslashes themselves also need to be
escaped with a backslash.
Use string literals to specify string values of the
<<string-type, String type>> 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:*
*Grammar*
[source,ANTLR4]
----
STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) | ( '\'' ( '\\\'' | '\\\\' | ~[\\'] )*? '\'' );
STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' )
| ( '\'' ( '\\\'' | '\\\\' | ~[\\'] )*? '\'' );
----
*Examples:*
[source,Java]
*Examples*
String literals using single-quotes.
[source,Painless]
----
"double-quoted String literal"
'single-quoted String literal'
"\"double-quoted String with escaped double-quotes\" and backslash: \\"
'\'single-quoted String with escaped single-quotes\' and backslash \\'
"double-quoted String with non-escaped 'single-quotes'"
'single-quoted String with non-escaped "double-quotes"'
'single-quoted string literal'
'\'single-quoted string with escaped single-quotes\' and backslash \\'
'single-quoted string with non-escaped "double-quotes"'
----
[[char]]
===== Char
String literals using double-quotes.
You cannot directly specify character literals in Painless. However, you can
cast single-character strings to char. Attempting to cast a multi-character
string to a char throws an error.
[source,Painless]
----
"double-quoted string literal"
"\"double-quoted string with escaped double-quotes\" and backslash: \\"
"double-quoted string with non-escaped 'single-quotes'"
----
*Examples:*
[source,Java]
[[characters]]
==== Characters
Use the <<painless-casting, casting operator>> to convert string literals or
<<string-type, String>> values into <<primitive-types, char>> values.
<<string-type, String>> values converted into
<<primitive-types, char>> values must be exactly one character in length
or an error will occur.
*Examples*
Casting string literals into <<primitive-types, char>> values.
[source,Painless]
----
(char)"C"
(char)'c'
----
Casting a <<string-type, String>> value into a <<primitive-types, char>> value.
[source,Painless]
----
String s = "s";
char c = (char)s;
----

View File

@ -1,3 +1,4 @@
[[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].

View File

@ -1,5 +1,5 @@
[[types]]
=== Data Types
[[painless-types]]
=== Types
Painless supports both dynamic and static types. Static types are split into
_primitive types_ and _reference types_.
@ -267,176 +267,3 @@ 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
----
[[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:*
[source,ANTLR4]
----
cast: '(' TYPE ')' expression
----
[[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.
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.
|====
| | 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 |
|====
Example(s)
[source,Java]
----
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.
----
[[reference-casting]]
==== Reference 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_.
*Examples:*
[source,Java]
----
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
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.
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]
----
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
----
[[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:
* 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:*
[source,Java]
----
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
----
[[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.
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:*
[source,Java]
----
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.
----

View File

@ -1,15 +1,15 @@
[[variables]]
[[painless-variables]]
=== Variables
Variables in Painless must be declared and can be statically or <<dynamic-types,
dynamically typed>>.
Variables in Painless must be declared and can be
statically or <<dynamic-types, dynamically typed>>.
[[variable-identifiers]]
==== Variable Identifiers
[[identifiers]]
==== Identifiers
Specify variable identifiers using the following grammar. Variable identifiers
must start with a letter or underscore. You cannot use <<keywords, keywords>> or
<<types, types>> as identifiers.
must start with a letter or underscore. You cannot use
<<painless-keywords, keywords>> or <<painless-types, types>> as identifiers.
*Grammar:*
[source,ANTLR4]
@ -20,7 +20,6 @@ ID: [_a-zA-Z] [_a-zA-Z-0-9]*;
*Examples:*
[source,Java]
----
_
a
Z
id
@ -30,8 +29,8 @@ MAP25
_map25
----
[[variable-declaration]]
==== Variable Declaration
[[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
@ -56,7 +55,7 @@ int i = 10; // Declare the int variable i and set it to the int literal 10
----
[[variable-assignment]]
==== Variable Assignment
==== Assignment
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

View File

@ -489,7 +489,7 @@ Using `_index` in scripts has been replaced with writing `ScriptEngine` backends
=== Painless Syntax
See the
{painless}/painless-specification.html[Painless Language Specification]
{painless}/painless-lang-spec.html[Painless Language Specification]
in the guide to the {painless}/index.html[Painless Scripting Language].
[role="exclude",id="modules-scripting-painless-debugging"]