/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * A painless tree is composed of the node classes found in this package. * <p> * 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. * <p> * The following is a brief description of each node: * {@link org.elasticsearch.painless.node.AExpression} - The superclass for all E* (expression) and P* (postfix) nodes. * {@link org.elasticsearch.painless.node.ANode} - The superclass for all nodes. * {@link org.elasticsearch.painless.node.AStatement} - The superclass for all S* (statement) nodes. * {@link org.elasticsearch.painless.node.AStoreable} - The super class for an expression that can store a value in local memory. * {@link org.elasticsearch.painless.node.EAssignment} - Represents an assignment with the lhs and rhs as child nodes. * {@link org.elasticsearch.painless.node.EBinary} - Represents a binary math expression. * {@link org.elasticsearch.painless.node.EBool} - Represents a boolean expression. * {@link org.elasticsearch.painless.node.EBoolean} - Represents a boolean constant. * {@link org.elasticsearch.painless.node.ECallLocal} - Represents a user-defined call. * {@link org.elasticsearch.painless.node.ECapturingFunctionRef} - Represents a function reference (capturing). * {@link org.elasticsearch.painless.node.ECast} - Represents a cast inserted into the tree replacing others. (Internal only.) * {@link org.elasticsearch.painless.node.EComp} - Represents a comparison expression. * {@link org.elasticsearch.painless.node.EConditional} - Represents a conditional expression. * {@link org.elasticsearch.painless.node.EConstant} - Represents a constant inserted into the tree replacing others. (Internal only.) * {@link org.elasticsearch.painless.node.EDecimal} - Represents a decimal constant. * {@link org.elasticsearch.painless.node.EExplicit} - Represents an explicit cast. * {@link org.elasticsearch.painless.node.EFunctionRef} - Represents a function reference (non-capturing). * {@link org.elasticsearch.painless.node.EInstanceof} - Represents an instanceof check. * {@link org.elasticsearch.painless.node.ELambda} - Represents a lambda function. * {@link org.elasticsearch.painless.node.EListInit} - Represents a list initialization shortcut. * {@link org.elasticsearch.painless.node.EMapInit} - Represents a map initialization shortcut. * {@link org.elasticsearch.painless.node.ENewArray} - Represents an array instantiation. * {@link org.elasticsearch.painless.node.ENewObj} - Represents and object instantiation. * {@link org.elasticsearch.painless.node.ENull} - Represents a null constant. * {@link org.elasticsearch.painless.node.ENumeric} - Represents a non-decimal numeric constant. * {@link org.elasticsearch.painless.node.ERegex} - Represents a regular expression constant. * {@link org.elasticsearch.painless.node.EStatic} - Represents a static type target. * {@link org.elasticsearch.painless.node.EString} - Represents a string constant. * {@link org.elasticsearch.painless.node.EUnary} - Represents a unary math expression. * {@link org.elasticsearch.painless.node.EVariable} - Represents a variable load/store. * {@link org.elasticsearch.painless.node.ILambda} - Represents a marker to signify this node is a lambda function. * {@link org.elasticsearch.painless.node.PBrace} - Represents an array load/store and defers to a child subnode. * {@link org.elasticsearch.painless.node.PCallInvoke} - Represents a method call and defers to a child subnode. * {@link org.elasticsearch.painless.node.PField} - Represents a field load/store and defers to a child subnode. * {@link org.elasticsearch.painless.node.PSubArrayLength} - Represents an array length field load. * {@link org.elasticsearch.painless.node.PSubBrace} - Represents an array load/store. * {@link org.elasticsearch.painless.node.PSubCallInvoke} - Represents a method call. * {@link org.elasticsearch.painless.node.PSubDefArray} - Represents an array load/store or shortcut on a def type. (Internal only.) * {@link org.elasticsearch.painless.node.PSubDefCall} - Represents a method call made on a def type. (Internal only.) * {@link org.elasticsearch.painless.node.PSubDefField} - Represents a field load/store or shortcut on a def type. (Internal only.) * {@link org.elasticsearch.painless.node.PSubField} - Represents a field load/store. * {@link org.elasticsearch.painless.node.PSubListShortcut} - Represents a list load/store shortcut. (Internal only.) * {@link org.elasticsearch.painless.node.PSubMapShortcut} - Represents a map load/store shortcut. (Internal only.) * {@link org.elasticsearch.painless.node.PSubShortcut} - Represents a field load/store shortcut. (Internal only.) * {@link org.elasticsearch.painless.node.SBlock} - Represents a set of statements as a branch of control-flow. * {@link org.elasticsearch.painless.node.SBreak} - Represents a break statement. * {@link org.elasticsearch.painless.node.SCatch} - Represents a catch block as part of a try-catch block. * {@link org.elasticsearch.painless.node.SContinue} - Represents a continue statement. * {@link org.elasticsearch.painless.node.SDeclaration} - Represents a single variable declaration. * {@link org.elasticsearch.painless.node.SDeclBlock} - Represents a series of declarations. * {@link org.elasticsearch.painless.node.SDo} - Represents a do-while loop. * {@link org.elasticsearch.painless.node.SEach} - Represents a for-each loop and defers to subnodes depending on type. * {@link org.elasticsearch.painless.node.SExpression} - Represents the top-level node for an expression as a statement. * {@link org.elasticsearch.painless.node.SFor} - Represents a for loop. * {@link org.elasticsearch.painless.node.SFunction} - Represents a user-defined function. * {@link org.elasticsearch.painless.node.SIf} - Represents an if block. * {@link org.elasticsearch.painless.node.SIfElse} - Represents an if/else block. * {@link org.elasticsearch.painless.node.SReturn} - Represents a return statement. * {@link org.elasticsearch.painless.node.SSource} - The root of all Painless trees. Contains a series of statements. * {@link org.elasticsearch.painless.node.SSubEachArray} - Represents a for-each loop for arrays. * {@link org.elasticsearch.painless.node.SSubEachIterable} - Represents a for-each loop for iterables. * {@link org.elasticsearch.painless.node.SThrow} - Represents a throw statement. * {@link org.elasticsearch.painless.node.STry} - Represents the try block as part of a try-catch block. * {@link org.elasticsearch.painless.node.SWhile} - Represents a while loop. * <p> * 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. * <p> * 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. * <p> * 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. * <p> * 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: * {@code * 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. * <p> * 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. * <p> * Storebable nodes have three methods for writing -- setup, load, and store. These methods * are used in conjuction 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. * <p> * 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 heirachy so the parent node can defer some analysis and writing to * the sub node. */ package org.elasticsearch.painless.node;