See: Description
| Interface | Description |
|---|---|
| SSource.Reserved |
Tracks derived arguments and the loop counter.
|
| Class | Description |
|---|---|
| AExpression |
The superclass for all E* (expression) and P* (postfix) nodes.
|
| ANode |
The superclass for all nodes.
|
| AStatement |
The superclass for all S* (statement) nodes.
|
| EAssignment |
Represents an assignment with the lhs and rhs as child nodes.
|
| EBinary |
Represents a binary math expression.
|
| EBool |
Represents a boolean expression.
|
| EBoolean |
Represents a boolean constant.
|
| ECallLocal |
Represents a user-defined call.
|
| ECapturingFunctionRef |
Represents a capturing function reference.
|
| EComp |
Represents a comparison expression.
|
| EConditional |
Represents a conditional expression.
|
| EDecimal |
Represents a decimal constant.
|
| EElvis |
The Elvis operator (
?:), a null coalescing operator. |
| EExplicit |
Represents an explicit cast.
|
| EFunctionRef |
Represents a function reference.
|
| EInstanceof |
Represents
instanceof operator. |
| ELambda |
Lambda expression node.
|
| EListInit |
Represents a list initialization shortcut.
|
| EMapInit |
Represents a map initialization shortcut.
|
| ENewArray |
Represents an array instantiation.
|
| ENewObj |
Represents and object instantiation.
|
| ENull |
Represents a null constant.
|
| ENumeric |
Represents a non-decimal numeric constant.
|
| ERegex |
Represents a regex constant.
|
| EStatic |
Represents a static type target.
|
| EString |
Represents a string constant.
|
| EUnary |
Represents a unary math expression.
|
| EVariable |
Represents a variable load/store.
|
| PBrace |
Represents an array load/store and defers to a child subnode.
|
| PCallInvoke |
Represents a method call and defers to a child subnode.
|
| PField |
Represents a field load/store and defers to a child subnode.
|
| PSubNullSafeCallInvoke |
Implements a call who's value is null if the prefix is null rather than throwing an NPE.
|
| PSubNullSafeField |
Implements a field who's value is null if the prefix is null rather than throwing an NPE.
|
| SBlock |
Represents a set of statements as a branch of control-flow.
|
| SBreak |
Represents a break statement.
|
| SCatch |
Represents a catch block as part of a try-catch block.
|
| SContinue |
Represents a continue statement.
|
| SDeclaration |
Represents a single variable declaration.
|
| SDeclBlock |
Represents a series of declarations.
|
| SDo |
Represents a do-while loop.
|
| SEach |
Represents a for-each loop and defers to subnodes depending on type.
|
| SExpression |
Represents the top-level node for an expression as a statement.
|
| SFor |
Represents a for loop.
|
| SFunction |
Represents a user-defined function.
|
| SFunction.FunctionReserved | |
| SIf |
Represents an if block.
|
| SIfElse |
Represents an if/else block.
|
| SReturn |
Represents a return statement.
|
| SSource |
The root of all Painless trees.
|
| SSource.MainMethodReserved | |
| SThrow |
Represents a throw statement.
|
| STry |
Represents the try block as part of a try-catch block.
|
| SWhile |
Represents a while loop.
|
The following are the types of nodes: A* (abstract) - These are the abstract nodes that are the superclasses for the other types. I* (interface) - These are marker interfaces to denote a property of the node. S* (statement) - These are nodes that represent a statement in Painless. E* (expression) - These are nodes that represent an expression in Painless. P* (postfix) - These are nodes that represent a postfix of a variable chain. E/P* (storeable) - These are nodes that are allowed to store a value to memory. *Sub* (sub) - These are partial nodes with a parent (S/E/P)* node used to split up logic into smaller pieces.
The following is a brief description of each node:
AExpression - The superclass for all E* (expression) and P* (postfix) nodes.
ANode - The superclass for all nodes.
AStatement - The superclass for all S* (statement) nodes.
AStoreable - The super class for an expression that can store a value in local memory.
EAssignment - Represents an assignment with the lhs and rhs as child nodes.
EBinary - Represents a binary math expression.
EBool - Represents a boolean expression.
EBoolean - Represents a boolean constant.
ECallLocal - Represents a user-defined call.
ECapturingFunctionRef - Represents a function reference (capturing).
ECast - Represents a cast inserted into the tree replacing others. (Internal only.)
EComp - Represents a comparison expression.
EConditional - Represents a conditional expression.
EConstant - Represents a constant inserted into the tree replacing others. (Internal only.)
EDecimal - Represents a decimal constant.
EExplicit - Represents an explicit cast.
EFunctionRef - Represents a function reference (non-capturing).
EInstanceof - Represents an instanceof check.
ELambda - Represents a lambda function.
EListInit - Represents a list initialization shortcut.
EMapInit - Represents a map initialization shortcut.
ENewArray - Represents an array instantiation.
ENewObj - Represents and object instantiation.
ENull - Represents a null constant.
ENumeric - Represents a non-decimal numeric constant.
ERegex - Represents a regular expression constant.
EStatic - Represents a static type target.
EString - Represents a string constant.
EUnary - Represents a unary math expression.
EVariable - Represents a variable load/store.
ILambda - Represents a marker to signify this node is a lambda function.
PBrace - Represents an array load/store and defers to a child subnode.
PCallInvoke - Represents a method call and defers to a child subnode.
PField - Represents a field load/store and defers to a child subnode.
PSubArrayLength - Represents an array length field load.
PSubBrace - Represents an array load/store.
PSubCallInvoke - Represents a method call.
PSubDefArray - Represents an array load/store or shortcut on a def type. (Internal only.)
PSubDefCall - Represents a method call made on a def type. (Internal only.)
PSubDefField - Represents a field load/store or shortcut on a def type. (Internal only.)
PSubField - Represents a field load/store.
PSubListShortcut - Represents a list load/store shortcut. (Internal only.)
PSubMapShortcut - Represents a map load/store shortcut. (Internal only.)
PSubShortcut - Represents a field load/store shortcut. (Internal only.)
SBlock - Represents a set of statements as a branch of control-flow.
SBreak - Represents a break statement.
SCatch - Represents a catch block as part of a try-catch block.
SContinue - Represents a continue statement.
SDeclaration - Represents a single variable declaration.
SDeclBlock - Represents a series of declarations.
SDo - Represents a do-while loop.
SEach - Represents a for-each loop and defers to subnodes depending on type.
SExpression - Represents the top-level node for an expression as a statement.
SFor - Represents a for loop.
SFunction - Represents a user-defined function.
SIf - Represents an if block.
SIfElse - Represents an if/else block.
SReturn - Represents a return statement.
SSource - The root of all Painless trees. Contains a series of statements.
SSubEachArray - Represents a for-each loop for arrays.
SSubEachIterable - Represents a for-each loop for iterables.
SThrow - Represents a throw statement.
STry - Represents the try block as part of a try-catch block.
SWhile - Represents a while loop.
Note that internal nodes are generated during the analysis phase by modifying the tree on-the-fly for clarity of development and convenience during the writing phase.
All Painless trees must start with an SSource node at the root. Each node has a constructor that requires all of its values and children be passed in at the time of instantiation. This means that Painless trees are build bottom-up; however, this helps enforce tree structure correctness and fits naturally with a standard recursive-descent parser.
Generally, statement nodes have member data that evaluate legal control-flow during the analysis phase. The typical order for statement nodes is for each node to call analyze on it's children during the analysis phase and write on it's children during the writing phase.
Generally, expression nodes have member data that evaluate static and def types. The typical order for an expression node
during the analysis phase looks like the following:
For known expected types:
expression.child.expected = expectedType // set the known expected type
expression.child.analyze(...) // analyze the child node to set the child's actual type
expression.child = expression.child.cast(...) // add an implicit cast node if the child node's
// actual type is not the expected type and set the
// expression's child to the implicit cast node
For unknown expected types that need promotion:
expression.child.analyze(...) // analyze the child node to set the child's actual type
Type promote = Caster.promote(...) // get the promotion type for the child based on
// the current operation and child's actual type
expression.child.expected = promote // set the expected type to the promotion type
expression.child = expression.child.cast(...) // add an implicit cast node if the child node's
// actual type is not the expected type and set the
// expression's child to the implicit cast node
Expression nodes just call each child during the writing phase.
Postfix nodes represent postfixes in a variable/method chain including braces, calls, or fields. Postfix nodes will always have a prefix node that is the prior piece of the variable/method chain. Analysis of a postfix node will cause a chain of analysis calls to happen where the prefix will be analyzed first and continue until the prefix is not a postfix node. Writing out a series of loads from a postfix node works in the same fashion. Stores work somewhat differently as described by later documentation.
Storebable nodes have three methods for writing -- setup, load, and store. These methods are used in conjunction with a parent node aware of the storeable node (lhs) that has a node representing a value to store (rhs). The setup method is always once called before a store to give storeable nodes a chance to write any prefixes they may have and any values such as array indices before the store happens. Load is called on a storeable node that must also be read from, and store is called to write a value to memory.
Sub nodes are partial nodes that require a parent to work correctly. These nodes can really represent anything the parent node would like to split up into logical pieces and don't really have any distinct set of rules. The currently existing subnodes all have ANode as a super class somewhere in their class hierarchy so the parent node can defer some analysis and writing to the sub node.