code: /*
   * 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.
   */
  
  package org.elasticsearch.painless.symbol;
  
  import org.elasticsearch.painless.FunctionRef;
  import org.elasticsearch.painless.Operation;
  import org.elasticsearch.painless.ir.IRNode.IRCondition;
  import org.elasticsearch.painless.ir.IRNode.IRDecoration;
  import org.elasticsearch.painless.lookup.PainlessCast;
  import org.elasticsearch.painless.lookup.PainlessClassBinding;
  import org.elasticsearch.painless.lookup.PainlessConstructor;
  import org.elasticsearch.painless.lookup.PainlessField;
  import org.elasticsearch.painless.lookup.PainlessInstanceBinding;
  import org.elasticsearch.painless.lookup.PainlessLookupUtility;
  import org.elasticsearch.painless.lookup.PainlessMethod;
  import org.elasticsearch.painless.symbol.FunctionTable.LocalFunction;
  
  import java.util.Collections;
  import java.util.List;
  
  public class IRDecorations {
  
      /** base class for all type decorations to provide consistent {@code #toString()} */
      public abstract static class IRDType extends IRDecoration<Class<?>> {
  
          public IRDType(Class<?> value) {
              super(value);
          }
  
          @Override
          public String toString() {
              return PainlessLookupUtility.typeToCanonicalTypeName(getValue());
          }
      }
  
      /** all expressions are decorated with a type based on the result */
      public static class IRDExpressionType extends IRDType {
  
          public IRDExpressionType(Class<?> value) {
              super(value);
          }
      }
  
      /** binary type is used as an optimization for binary math */
      public static class IRDBinaryType extends IRDType {
  
          public IRDBinaryType(Class<?> value) {
              super(value);
          }
      }
  
      /** shift type is used to define the right-hand side type of a shift operation */
      public static class IRDShiftType extends IRDType {
  
          public IRDShiftType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes a math operation */
      public static class IRDOperation extends IRDecoration<Operation> {
  
          public IRDOperation(Operation value) {
              super(value);
          }
  
          @Override
          public String toString() {
              return getValue().symbol;
          }
      }
  
      /** general flags used to describe options on a node; options depend on node type*/
      public static class IRDFlags extends IRDecoration<Integer> {
  
          public IRDFlags(Integer value) {
              super(value);
          }
      }
  
      /** condition attached to a statement node when all logical paths escape */
      public static class IRCAllEscape implements IRCondition {
  
          private IRCAllEscape() {
  
          }
      }
  
      /** condition attached to describe a cast for a node */
      public static class IRDCast extends IRDecoration<PainlessCast> {
  
          public IRDCast(PainlessCast value) {
              super(value);
          }
      }
  
      /** describes what exception type is caught */
      public static class IRDExceptionType extends IRDType {
  
          public IRDExceptionType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes a symbol for a node; what symbol represents depends on node type */
      public static class IRDSymbol extends IRDecoration<String> {
  
          public IRDSymbol(String value) {
              super(value);
          }
      }
  
      /**
       * additional information for the type of comparison;
       * comparison node's result is always boolean so this is required
       */
      public static class IRDComparisonType extends IRDType {
  
          public IRDComparisonType(Class<?> value) {
              super(value);
          }
      }
  
      /**
       * describes a constant for a node; what the constant is depends on the node
       */
      public static class IRDConstant extends IRDecoration<Object> {
  
          public IRDConstant(Object value) {
              super(value);
          }
      }
  
      /**
       * describes the type for a declaration
       */
      public static class IRDDeclarationType extends IRDType {
  
          public IRDDeclarationType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes a name for a specific piece of data in a node; the data depends on the node */
      public static class IRDName extends IRDecoration<String> {
  
          public IRDName(String value) {
              super(value);
          }
      }
  
      /** describes an encoding used to resolve references and lambdas at runtime */
      public static class IRDDefReferenceEncoding extends IRDecoration<String> {
  
          public IRDDefReferenceEncoding(String value) {
              super(value);
          }
      }
  
      /** describes the size of a dup instruction */
      public static class IRDSize extends IRDecoration<Integer> {
  
          public IRDSize(Integer value) {
              super(value);
          }
      }
  
      /** describes the depth of a dup instruction */
      public static class IRDDepth extends IRDecoration<Integer> {
  
          public IRDDepth(Integer value) {
              super(value);
          }
      }
  
      /** describes modifiers on a class, method, or field; depends on node type */
      public static class IRDModifiers extends IRDecoration<Integer> {
  
          public IRDModifiers(Integer value) {
              super(value);
          }
      }
  
      /** describes the type for a member field on a class */
      public static class IRDFieldType extends IRDType {
  
          public IRDFieldType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes a type for a variable access */
      public static class IRDVariableType extends IRDType {
  
          public IRDVariableType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes the name for a variable access */
      public static class IRDVariableName extends IRDecoration<String> {
  
          public IRDVariableName(String value) {
              super(value);
          }
      }
  
      /** describes the array variable type in a foreach loop */
      public static class IRDArrayType extends IRDType {
  
          public IRDArrayType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes the array variable name in a foreach loop */
      public static class IRDArrayName extends IRDecoration<String> {
  
          public IRDArrayName(String value) {
              super(value);
          }
      }
  
      /** describes the index variable type in a foreach loop */
      public static class IRDIndexType extends IRDType {
  
          public IRDIndexType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes the index variable name variable in a foreach loop */
      public static class IRDIndexName extends IRDecoration<String> {
  
          public IRDIndexName(String value) {
              super(value);
          }
      }
  
      /** describes the array type in a foreach loop */
      public static class IRDIndexedType extends IRDType {
  
          public IRDIndexedType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes the iterable variable type in a foreach loop */
      public static class IRDIterableType extends IRDType {
  
          public IRDIterableType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes the iterable name type in a foreach loop */
      public static class IRDIterableName extends IRDecoration<String> {
  
          public IRDIterableName(String value) {
              super(value);
          }
      }
  
      /** describes a method for a node; which method depends on node type */
      public static class IRDMethod extends IRDecoration<PainlessMethod> {
  
          public IRDMethod(PainlessMethod value) {
              super(value);
          }
  
          @Override
          public String toString() {
              return PainlessLookupUtility.buildPainlessMethodKey(getValue().javaMethod.getName(), getValue().typeParameters.size());
          }
      }
  
      /** describes the return type for a statement node */
      public static class IRDReturnType extends IRDType {
  
          public IRDReturnType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes the parameter types for a function node */
      public static class IRDTypeParameters extends IRDecoration<List<Class<?>>> {
  
          public IRDTypeParameters(List<Class<?>> value) {
              super(Collections.unmodifiableList(value));
          }
      }
  
      /** describes the parameter names for a function node */
      public static class IRDParameterNames extends IRDecoration<List<String>> {
  
          public IRDParameterNames(List<String> value) {
              super(Collections.unmodifiableList(value));
          }
      }
  
      /** describes if a method or field is static */
      public static class IRCStatic implements IRCondition {
  
          private IRCStatic() {
  
          }
      }
  
      /** describes if a method has variadic arguments */
      public static class IRCVarArgs implements IRCondition {
  
          private IRCVarArgs() {
  
          }
      }
  
      /** describes if a method or field is synthetic */
      public static class IRCSynthetic implements IRCondition {
  
          private IRCSynthetic() {
  
          }
      }
  
      /** describes the maximum number of loop iterations possible in a method */
      public static class IRDMaxLoopCounter extends IRDecoration<Integer> {
  
          public IRDMaxLoopCounter(Integer value) {
              super(value);
          }
      }
  
      /** describes the type for an instanceof instruction */
      public static class IRDInstanceType extends IRDType {
  
          public IRDInstanceType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes the call to a generated function */
      public static class IRDFunction extends IRDecoration<LocalFunction> {
  
          public IRDFunction(LocalFunction value) {
              super(value);
          }
      }
  
      /** describes the call to a class binding */
      public static class IRDClassBinding extends IRDecoration<PainlessClassBinding> {
  
          public IRDClassBinding(PainlessClassBinding value) {
              super(value);
          }
      }
  
      /** describes the call to an instance binding */
      public static class IRDInstanceBinding extends IRDecoration<PainlessInstanceBinding> {
  
          public IRDInstanceBinding(PainlessInstanceBinding value) {
              super(value);
          }
      }
  
      /** describes a constructor for a new instruction */
      public static class IRDConstructor extends IRDecoration<PainlessConstructor> {
  
          public IRDConstructor(PainlessConstructor value) {
              super(value);
          }
      }
  
      /** describes a value used as an index for shortcut field accesses */
      public static class IRDValue extends IRDecoration<String> {
  
          public IRDValue(String value) {
              super(value);
          }
      }
  
      /** describes the field for a field access */
      public static class IRDField extends IRDecoration<PainlessField> {
  
          public IRDField(PainlessField value) {
              super(value);
          }
      }
  
      /** describes if a loop has no escape paths */
      public static class IRCContinuous implements IRCondition {
  
          private IRCContinuous() {
  
          }
      }
  
      /** describes if a new array is an initializer */
      public static class IRCInitialize implements IRCondition {
  
          private IRCInitialize() {
  
          }
      }
  
      /** describes if an expression's value is read from */
      public static class IRCRead implements IRCondition {
  
          private IRCRead() {
  
          }
      }
  
      /** describes the names of all captured variables in a reference or lambda */
      public static class IRDCaptureNames extends IRDecoration<List<String>> {
  
          public IRDCaptureNames(List<String> value) {
              super(Collections.unmodifiableList(value));
          }
      }
  
      /** describes the type of value stored in an assignment operation */
      public static class IRDStoreType extends IRDType {
  
          public IRDStoreType(Class<?> value) {
              super(value);
          }
      }
  
      /** unary type is used as an optimization for unary math */
      public static class IRDUnaryType extends IRDType {
  
          public IRDUnaryType(Class<?> value) {
              super(value);
          }
      }
  
      /** describes a function reference resolved at compile-time */
      public static class IRDReference extends IRDecoration<FunctionRef> {
  
          public IRDReference(FunctionRef value) {
              super(value);
          }
      }
  
      /** describes the limit of operations performed on a regex */
      public static class IRDRegexLimit extends IRDecoration<Integer> {
  
          public IRDRegexLimit(Integer value) {
              super(value);
          }
      }
  }
  