/*
 * Copyright 2008 Google Inc.
 *
 * Licensed 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 com.google.gwt.dev.jjs.impl;

import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JPostfixOperation;
import com.google.gwt.dev.jjs.ast.JPrefixOperation;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;

/**
 * Most autoboxing is handled by {@link GenerateJavaAST}. The only cases it
 * does not handle are <code>++</code>, <code>--</code>, and compound
 * assignment operations (<code>+=</code>, etc.) when applied to a boxed
 * type. This class fixes such cases in two steps. First, an internal subclass
 * of {@link CompoundAssignmentNormalizer} simplifies such expressions to a
 * simple assignment expression. Second, this visitor replaces an assignment to
 * an unboxing method (<code>unbox(x) = unbox(x) + 1</code>) with an
 * assignment to the underlying box (<code>x = box(unbox(x) + 1)</code>).
 *
 * <p>
 * Update: GenerateJavaAST can also leave invalid AST structures of the form
 * <code>(Foo) x = foo</code> due to the way generics are handled. This can
 * happen when assigning into a field of a generic type. We'll go ahead and
 * resolve that case here as well.
 * </p>
 */
public class FixAssignmentToUnbox extends JModVisitor {
  /**
   * Normalize compound assignments where the lhs is an unbox operation.
   */
  private static class CompoundAssignmentToUnboxNormalizer extends
      CompoundAssignmentNormalizer {
    private final AutoboxUtils autoboxUtils;

    protected CompoundAssignmentToUnboxNormalizer(JProgram program) {
      autoboxUtils = new AutoboxUtils(program);
    }

    /**
     * If the lhs is an unbox operation, then return the box rather than the
     * original value.
     */
    @Override
    protected JExpression expressionToReturn(JExpression lhs) {
      JExpression boxed = autoboxUtils.undoUnbox(lhs);
      if (boxed != null) {
        return boxed;
      }
      return lhs;
    }

    @Override
    protected boolean shouldBreakUp(JBinaryOperation x) {
      return isUnboxExpression(x.getLhs());
    }

    @Override
    protected boolean shouldBreakUp(JPostfixOperation x) {
      return isUnboxExpression(x.getArg());
    }

    @Override
    protected boolean shouldBreakUp(JPrefixOperation x) {
      return isUnboxExpression(x.getArg());
    }

    private boolean isUnboxExpression(JExpression x) {
      return (autoboxUtils.undoUnbox(x) != null);
    }
  }

  public static void exec(JProgram program) {
    Event fixAssignmentToUnboxEvent =
        SpeedTracerLogger.start(CompilerEventType.FIX_ASSIGNMENT_TO_UNBOX);
    new CompoundAssignmentToUnboxNormalizer(program).accept(program);
    new FixAssignmentToUnbox(program).accept(program);
    fixAssignmentToUnboxEvent.end();
  }

  private final AutoboxUtils autoboxUtils;

  private FixAssignmentToUnbox(JProgram program) {
    this.autoboxUtils = new AutoboxUtils(program);
  }

  @Override
  public void endVisit(JBinaryOperation x, Context ctx) {
    if (x.getOp() != JBinaryOperator.ASG) {
      return;
    }

    JExpression lhs = x.getLhs();
    JExpression boxed = autoboxUtils.undoUnbox(lhs);
    if (boxed != null) {
      // Assignment-to-unbox, e.g.
      // unbox(x) = foo -> x = box(foo)
      JClassType boxedType = (JClassType) boxed.getType();

      ctx.replaceMe(new JBinaryOperation(x.getSourceInfo(), boxedType,
          JBinaryOperator.ASG, boxed, autoboxUtils.box(x.getRhs(), boxedType)));
      return;
    }

    if (lhs instanceof JCastOperation) {
      // Assignment-to-cast-operation, e.g.
      // (Foo) x = foo -> x = foo
      JCastOperation cast = (JCastOperation) lhs;
      JBinaryOperation newAsg = new JBinaryOperation(x.getSourceInfo(),
          x.getType(), JBinaryOperator.ASG, cast.getExpr(), x.getRhs());
      ctx.replaceMe(newAsg);
    }
  }
}
