/**
  * Cast expression code generation
  *
  * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
  * @param valueRequired boolean
  */
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
   int pc = codeStream.position;
   boolean annotatedCast = (this.type.bits & ASTNode.HasTypeAnnotations) != 0;
   boolean needRuntimeCheckcast = (this.bits & ASTNode.GenerateCheckcast) != 0;
   if (this.constant != Constant.NotAConstant) {
     if (valueRequired
         || needRuntimeCheckcast
         || annotatedCast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
       codeStream.generateConstant(this.constant, this.implicitConversion);
       if (needRuntimeCheckcast || annotatedCast) {
         codeStream.checkcast(this.type, this.resolvedType, pc);
       }
       if (!valueRequired) {
         // the resolveType cannot be double or long
         codeStream.pop();
       }
     }
     codeStream.recordPositionsFrom(pc, this.sourceStart);
     return;
   }
   this.expression.generateCode(
       currentScope, codeStream, annotatedCast || valueRequired || needRuntimeCheckcast);
   if (annotatedCast
       || (needRuntimeCheckcast
           && TypeBinding.notEquals(
               this.expression.postConversionType(currentScope),
               this.resolvedType
                   .erasure()))) { // no need to issue a checkcast if already done as genericCast
     codeStream.checkcast(this.type, this.resolvedType, pc);
   }
   if (valueRequired) {
     codeStream.generateImplicitConversion(this.implicitConversion);
   } else if (annotatedCast || needRuntimeCheckcast) {
     switch (this.resolvedType.id) {
       case T_long:
       case T_double:
         codeStream.pop2();
         break;
       default:
         codeStream.pop();
         break;
     }
   }
   codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
    if (!valueRequired) currentScope.problemReporter().unusedObjectAllocation(this);
    int pc = codeStream.position;
    MethodBinding codegenBinding = this.binding.original();
    ReferenceBinding allocatedType = codegenBinding.declaringClass;
    codeStream.new_(allocatedType);
    boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
    if (valueRequired || isUnboxing) {
      codeStream.dup();
    }
    // better highlight for allocation: display the type individually
    if (this.type != null) { // null for enum constant body
      codeStream.recordPositionsFrom(pc, this.type.sourceStart);
    } else {
      // push enum constant name and ordinal
      codeStream.ldc(String.valueOf(this.enumConstant.name));
      codeStream.generateInlinedValue(this.enumConstant.binding.id);
    }
    // handling innerclass instance allocation - enclosing instance arguments
    if (allocatedType.isNestedType()) {
      codeStream.generateSyntheticEnclosingInstanceValues(
          currentScope, allocatedType, enclosingInstance(), this);
    }
    // generate the arguments for constructor
    generateArguments(this.binding, this.arguments, currentScope, codeStream);
    // handling innerclass instance allocation - outer local arguments
    if (allocatedType.isNestedType()) {
      codeStream.generateSyntheticOuterArgumentValues(currentScope, allocatedType, this);
    }

    // invoke constructor
    if (this.syntheticAccessor == null) {
      codeStream.invoke(
          Opcodes.OPC_invokespecial, codegenBinding, null /* default declaringClass */);
    } else {
      // synthetic accessor got some extra arguments appended to its signature, which need values
      for (int i = 0,
              max = this.syntheticAccessor.parameters.length - codegenBinding.parameters.length;
          i < max;
          i++) {
        codeStream.aconst_null();
      }
      codeStream.invoke(
          Opcodes.OPC_invokespecial, this.syntheticAccessor, null /* default declaringClass */);
    }
    if (valueRequired) {
      codeStream.generateImplicitConversion(this.implicitConversion);
    } else if (isUnboxing) {
      // conversion only generated if unboxing
      codeStream.generateImplicitConversion(this.implicitConversion);
      switch (postConversionType(currentScope).id) {
        case T_long:
        case T_double:
          codeStream.pop2();
          break;
        default:
          codeStream.pop();
      }
    }
    codeStream.recordPositionsFrom(pc, this.sourceStart);

    if (this.anonymousType != null) {
      this.anonymousType.generateCode(currentScope, codeStream);
    }
  }
  /**
   * MessageSend code generation
   *
   * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
   * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
   * @param valueRequired boolean
   */
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
    int pc = codeStream.position;
    MethodBinding codegenBinding = this.binding.original();
    if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
      // generate receiver/enclosing instance access
      boolean isStatic = codegenBinding.isStatic();
      // outer access ?
      if (!isStatic && ((this.bits & DepthMASK) != 0)) {
        // outer method can be reached through emulation
        ReferenceBinding targetType =
            currentScope
                .enclosingSourceType()
                .enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
        Object[] path =
            currentScope.getEmulationPath(
                targetType, true /*only exact match*/, false /*consider enclosing arg*/);
        if (path == null) {
          // emulation was not possible (should not happen per construction)
          currentScope.problemReporter().needImplementation(this);
        } else {
          codeStream.generateOuterAccess(path, this, targetType, currentScope);
        }
      } else {
        this.receiver.generateCode(currentScope, codeStream, !isStatic);
        if ((this.bits & NeedReceiverGenericCast) != 0) {
          codeStream.checkcast(this.actualReceiverType);
        }
        codeStream.recordPositionsFrom(pc, this.sourceStart);
      }
      // generate arguments
      generateArguments(this.binding, this.arguments, currentScope, codeStream);
      // actual message invocation
      TypeBinding constantPoolDeclaringClass =
          CodeStream.getConstantPoolDeclaringClass(
              currentScope,
              codegenBinding,
              this.actualReceiverType,
              this.receiver.isImplicitThis());
      if (isStatic) {
        codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
      } else if ((this.receiver.isSuper()) || codegenBinding.isPrivate()) {
        codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, constantPoolDeclaringClass);
      } else {
        if (constantPoolDeclaringClass.isInterface()) { // interface or annotation type
          codeStream.invoke(
              Opcodes.OPC_invokeinterface, codegenBinding, constantPoolDeclaringClass);
        } else {
          codeStream.invoke(Opcodes.OPC_invokevirtual, codegenBinding, constantPoolDeclaringClass);
        }
      }
    } else {
      codeStream.generateEmulationForMethod(currentScope, codegenBinding);
      // generate receiver/enclosing instance access
      boolean isStatic = codegenBinding.isStatic();
      // outer access ?
      if (!isStatic && ((this.bits & DepthMASK) != 0)) {
        // not supported yet
        currentScope.problemReporter().needImplementation(this);
      } else {
        this.receiver.generateCode(currentScope, codeStream, !isStatic);
        if ((this.bits & NeedReceiverGenericCast) != 0) {
          codeStream.checkcast(this.actualReceiverType);
        }
        codeStream.recordPositionsFrom(pc, this.sourceStart);
      }
      if (isStatic) {
        // we need an object on the stack which is ignored for the method invocation
        codeStream.aconst_null();
      }
      // generate arguments
      if (this.arguments != null) {
        int argsLength = this.arguments.length;
        codeStream.generateInlinedValue(argsLength);
        codeStream.newArray(
            currentScope.createArrayType(
                currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
        codeStream.dup();
        for (int i = 0; i < argsLength; i++) {
          codeStream.generateInlinedValue(i);
          this.arguments[i].generateCode(currentScope, codeStream, true);
          TypeBinding parameterBinding = codegenBinding.parameters[i];
          if (parameterBinding.isBaseType() && parameterBinding != TypeBinding.NULL) {
            codeStream.generateBoxingConversion(codegenBinding.parameters[i].id);
          }
          codeStream.aastore();
          if (i < argsLength - 1) {
            codeStream.dup();
          }
        }
      } else {
        codeStream.generateInlinedValue(0);
        codeStream.newArray(
            currentScope.createArrayType(
                currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
      }
      codeStream.invokeJavaLangReflectMethodInvoke();

      // convert the return value to the appropriate type for primitive types
      if (codegenBinding.returnType.isBaseType()) {
        int typeID = codegenBinding.returnType.id;
        if (typeID == T_void) {
          // remove the null from the stack
          codeStream.pop();
        }
        codeStream.checkcast(typeID);
        codeStream.getBaseTypeValue(typeID);
      } else {
        codeStream.checkcast(codegenBinding.returnType);
      }
    }
    // required cast must occur even if no value is required
    if (this.valueCast != null) codeStream.checkcast(this.valueCast);
    if (valueRequired) {
      // implicit conversion if necessary
      codeStream.generateImplicitConversion(this.implicitConversion);
    } else {
      boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
      // conversion only generated if unboxing
      if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
      switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.returnType.id) {
        case T_long:
        case T_double:
          codeStream.pop2();
          break;
        case T_void:
          break;
        default:
          codeStream.pop();
      }
    }
    codeStream.recordPositionsFrom(
        pc, (int) (this.nameSourcePosition >>> 32)); // highlight selector
  }
 /**
  * Field reference code generation
  *
  * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
  * @param valueRequired boolean
  */
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
   int pc = codeStream.position;
   if (this.constant != Constant.NotAConstant) {
     if (valueRequired) {
       codeStream.generateConstant(this.constant, this.implicitConversion);
     }
     codeStream.recordPositionsFrom(pc, this.sourceStart);
     return;
   }
   FieldBinding codegenBinding = this.binding.original();
   boolean isStatic = codegenBinding.isStatic();
   boolean isThisReceiver = this.receiver instanceof ThisReference;
   Constant fieldConstant = codegenBinding.constant();
   if (fieldConstant != Constant.NotAConstant) {
     if (!isThisReceiver) {
       this.receiver.generateCode(currentScope, codeStream, !isStatic);
       if (!isStatic) {
         codeStream.invokeObjectGetClass();
         codeStream.pop();
       }
     }
     if (valueRequired) {
       codeStream.generateConstant(fieldConstant, this.implicitConversion);
     }
     codeStream.recordPositionsFrom(pc, this.sourceStart);
     return;
   }
   if (valueRequired
       || (!isThisReceiver
           && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
       || ((this.implicitConversion & TypeIds.UNBOXING) != 0)
       || (this.genericCast != null)) {
     this.receiver.generateCode(currentScope, codeStream, !isStatic);
     if ((this.bits & NeedReceiverGenericCast) != 0) {
       codeStream.checkcast(this.actualReceiverType);
     }
     pc = codeStream.position;
     if (codegenBinding.declaringClass == null) { // array length
       codeStream.arraylength();
       if (valueRequired) {
         codeStream.generateImplicitConversion(this.implicitConversion);
       } else {
         // could occur if !valueRequired but compliance >= 1.4
         codeStream.pop();
       }
     } else {
       if (this.syntheticAccessors == null
           || this.syntheticAccessors[FieldReference.READ] == null) {
         TypeBinding constantPoolDeclaringClass =
             CodeStream.getConstantPoolDeclaringClass(
                 currentScope,
                 codegenBinding,
                 this.actualReceiverType,
                 this.receiver.isImplicitThis());
         if (isStatic) {
           codeStream.fieldAccess(
               Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
         } else {
           codeStream.fieldAccess(
               Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
         }
       } else {
         codeStream.invoke(
             Opcodes.OPC_invokestatic,
             this.syntheticAccessors[FieldReference.READ],
             null /* default declaringClass */);
       }
       // required cast must occur even if no value is required
       if (this.genericCast != null) codeStream.checkcast(this.genericCast);
       if (valueRequired) {
         codeStream.generateImplicitConversion(this.implicitConversion);
       } else {
         boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
         // conversion only generated if unboxing
         if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
         switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.type.id) {
           case T_long:
           case T_double:
             codeStream.pop2();
             break;
           default:
             codeStream.pop();
         }
       }
     }
   } else {
     if (isThisReceiver) {
       if (isStatic) {
         // if no valueRequired, still need possible side-effects of <clinit> invocation, if field
         // belongs to different class
         if (this.binding.original().declaringClass != this.actualReceiverType.erasure()) {
           MethodBinding accessor =
               this.syntheticAccessors == null
                   ? null
                   : this.syntheticAccessors[FieldReference.READ];
           if (accessor == null) {
             TypeBinding constantPoolDeclaringClass =
                 CodeStream.getConstantPoolDeclaringClass(
                     currentScope,
                     codegenBinding,
                     this.actualReceiverType,
                     this.receiver.isImplicitThis());
             codeStream.fieldAccess(
                 Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
           } else {
             codeStream.invoke(
                 Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
           }
           switch (codegenBinding.type.id) {
             case T_long:
             case T_double:
               codeStream.pop2();
               break;
             default:
               codeStream.pop();
           }
         }
       }
     } else {
       this.receiver.generateCode(currentScope, codeStream, !isStatic);
       if (!isStatic) {
         codeStream.invokeObjectGetClass(); // perform null check
         codeStream.pop();
       }
     }
   }
   codeStream.recordPositionsFrom(pc, this.sourceEnd);
 }
 /**
  * MessageSend code generation
  *
  * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
  * @param valueRequired boolean
  */
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
   int pc = codeStream.position;
   // generate receiver/enclosing instance access
   MethodBinding codegenBinding =
       this.binding instanceof PolymorphicMethodBinding ? this.binding : this.binding.original();
   boolean isStatic = codegenBinding.isStatic();
   if (isStatic) {
     this.receiver.generateCode(currentScope, codeStream, false);
   } else if ((this.bits & ASTNode.DepthMASK) != 0
       && this.receiver.isImplicitThis()) { // outer access ?
     // outer method can be reached through emulation if implicit access
     ReferenceBinding targetType =
         currentScope
             .enclosingSourceType()
             .enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
     Object[] path =
         currentScope.getEmulationPath(
             targetType, true /*only exact match*/, false /*consider enclosing arg*/);
     codeStream.generateOuterAccess(path, this, targetType, currentScope);
   } else {
     this.receiver.generateCode(currentScope, codeStream, true);
     if ((this.bits & NeedReceiverGenericCast) != 0) {
       codeStream.checkcast(this.actualReceiverType);
     }
   }
   codeStream.recordPositionsFrom(pc, this.sourceStart);
   // generate arguments
   generateArguments(this.binding, this.arguments, currentScope, codeStream);
   pc = codeStream.position;
   // actual message invocation
   if (this.syntheticAccessor == null) {
     TypeBinding constantPoolDeclaringClass =
         CodeStream.getConstantPoolDeclaringClass(
             currentScope,
             codegenBinding,
             this.actualReceiverType,
             this.receiver.isImplicitThis());
     if (isStatic) {
       codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
     } else if ((this.receiver.isSuper()) || codegenBinding.isPrivate()) {
       codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, constantPoolDeclaringClass);
     } else if (constantPoolDeclaringClass.isInterface()) { // interface or annotation type
       codeStream.invoke(Opcodes.OPC_invokeinterface, codegenBinding, constantPoolDeclaringClass);
     } else {
       codeStream.invoke(Opcodes.OPC_invokevirtual, codegenBinding, constantPoolDeclaringClass);
     }
   } else {
     codeStream.invoke(
         Opcodes.OPC_invokestatic, this.syntheticAccessor, null /* default declaringClass */);
   }
   // required cast must occur even if no value is required
   if (this.valueCast != null) codeStream.checkcast(this.valueCast);
   if (valueRequired) {
     // implicit conversion if necessary
     codeStream.generateImplicitConversion(this.implicitConversion);
   } else {
     boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
     // conversion only generated if unboxing
     if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
     switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.returnType.id) {
       case T_long:
       case T_double:
         codeStream.pop2();
         break;
       case T_void:
         break;
       default:
         codeStream.pop();
     }
   }
   codeStream.recordPositionsFrom(
       pc, (int) (this.nameSourcePosition >>> 32)); // highlight selector
 }