Example #1
0
  private void analyzeLHS(Locals locals) {
    if (lhs instanceof AStoreable) {
      AStoreable lhs = (AStoreable) this.lhs;

      lhs.read = read;
      lhs.write = true;
      lhs.analyze(locals);
    } else {
      throw new IllegalArgumentException("Left-hand side cannot be assigned a value.");
    }
  }
Example #2
0
  private void analyzeSimple(Locals locals) {
    AStoreable lhs = (AStoreable) this.lhs;

    // If the lhs node is a def optimized node we update the actual type to remove the need for a
    // cast.
    if (lhs.isDefOptimized()) {
      rhs.analyze(locals);
      rhs.expected = rhs.actual;
      lhs.updateActual(rhs.actual);
      // Otherwise, we must adapt the rhs type to the lhs type with a cast.
    } else {
      rhs.expected = lhs.actual;
      rhs.analyze(locals);
    }

    rhs = rhs.cast(locals);

    this.statement = true;
    this.actual = read ? lhs.actual : Definition.VOID_TYPE;
  }
Example #3
0
  /**
   * Handles writing byte code for variable/method chains for all given possibilities including
   * String concatenation, compound assignment, regular assignment, and simple reads. Includes
   * proper duplication for chained assignments and assignments that are also read from.
   */
  @Override
  void write(MethodWriter writer, Globals globals) {
    writer.writeDebugInfo(location);

    // For the case where the assignment represents a String concatenation
    // we must, depending on the Java version, write a StringBuilder or
    // track types going onto the stack.  This must be done before the
    // lhs is read because we need the StringBuilder to be placed on the
    // stack ahead of any potential concatenation arguments.
    int catElementStackSize = 0;

    if (cat) {
      catElementStackSize = writer.writeNewStrings();
    }

    // Cast the lhs to a storeable to perform the necessary operations to store the rhs.
    AStoreable lhs = (AStoreable) this.lhs;
    lhs.setup(
        writer, globals); // call the setup method on the lhs to prepare for a load/store operation

    if (cat) {
      // Handle the case where we are doing a compound assignment
      // representing a String concatenation.

      writer.writeDup(
          lhs.accessElementCount(), catElementStackSize); // dup the top element and insert it
      // before concat helper on stack
      lhs.load(writer, globals); // read the current lhs's value
      writer.writeAppendStrings(lhs.actual); // append the lhs's value using the StringBuilder

      rhs.write(writer, globals); // write the bytecode for the rhs

      if (!(rhs instanceof EBinary)
          || !((EBinary) rhs).cat) { // check to see if the rhs has already done a concatenation
        writer.writeAppendStrings(rhs.actual); // append the rhs's value since it's hasn't already
      }

      writer.writeToStrings(); // put the value for string concat onto the stack
      writer.writeCast(back); // if necessary, cast the String to the lhs actual type

      if (lhs.read) {
        writer.writeDup(lhs.actual.sort.size, lhs.accessElementCount()); // if this lhs is also read
        // from dup the value onto the stack
      }

      lhs.store(
          writer,
          globals); // store the lhs's value from the stack in its respective variable/field/array
    } else if (operation != null) {
      // Handle the case where we are doing a compound assignment that
      // does not represent a String concatenation.

      writer.writeDup(lhs.accessElementCount(), 0); // if necessary, dup the previous lhs's value
      // to be both loaded from and stored to
      lhs.load(writer, globals); // load the current lhs's value

      if (lhs.read && post) {
        writer.writeDup(
            lhs.actual.sort.size, lhs.accessElementCount()); // dup the value if the lhs is also
        // read from and is a post increment
      }

      writer.writeCast(there); // if necessary cast the current lhs's value
      // to the promotion type between the lhs and rhs types
      rhs.write(writer, globals); // write the bytecode for the rhs

      // XXX: fix these types, but first we need def compound assignment tests.
      // its tricky here as there are possibly explicit casts, too.
      // write the operation instruction for compound assignment
      if (promote.sort == Sort.DEF) {
        writer.writeDynamicBinaryInstruction(
            location,
            promote,
            Definition.DEF_TYPE,
            Definition.DEF_TYPE,
            operation,
            DefBootstrap.OPERATOR_COMPOUND_ASSIGNMENT);
      } else {
        writer.writeBinaryInstruction(location, promote, operation);
      }

      writer.writeCast(back); // if necessary cast the promotion type value back to the lhs's type

      if (lhs.read && !post) {
        writer.writeDup(
            lhs.actual.sort.size, lhs.accessElementCount()); // dup the value if the lhs is also
        // read from and is not a post increment
      }

      lhs.store(
          writer,
          globals); // store the lhs's value from the stack in its respective variable/field/array
    } else {
      // Handle the case for a simple write.

      rhs.write(writer, globals); // write the bytecode for the rhs rhs

      if (lhs.read) {
        writer.writeDup(
            lhs.actual.sort.size,
            lhs.accessElementCount()); // dup the value if the lhs is also read from
      }

      lhs.store(
          writer,
          globals); // store the lhs's value from the stack in its respective variable/field/array
    }
  }