/*
 * 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.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.JPrimitiveType;
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 FixAssignmentsToUnboxOrCast extends JModVisitor {
  /**
   * Normalize compound assignments where the lhs is an unbox operation.
   */
  private static class CompoundAssignmentsToUnboxOrCastNormalizer
      extends CompoundAssignmentNormalizer {
    private final AutoboxUtils autoboxUtils;

    protected CompoundAssignmentsToUnboxOrCastNormalizer(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 isUnboxOrCastExpression(x.getLhs());
    }

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

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

    private boolean isUnboxOrCastExpression(JExpression x) {
      return (autoboxUtils.undoUnbox(x) != null) || x instanceof JCastOperation;
    }
  }

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

  private final AutoboxUtils autoboxUtils;

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

  private JBinaryOperation maybeFixLhsCast(JBinaryOperation x) {
    if (!(x.getLhs() instanceof JCastOperation)) {
      return x;
    }
    // Assignment-to-cast-operation, e.g.
    // (Foo) x = foo -> x = foo
    // (Foo) x += foo -> x += foo
    JCastOperation cast = (JCastOperation) x.getLhs();
    return new JBinaryOperation(x.getSourceInfo(), x.getType(), x.getOp(), cast.getExpr(),
            x.getRhs());
  }

  private JBinaryOperation maybeUndoBox(JBinaryOperation x) {
    JExpression lhs = x.getLhs();
    JExpression boxed = autoboxUtils.undoUnbox(lhs);
    if (boxed == null) {
      return x;
    }

    // Assignment-to-unbox, e.g.
    // unbox(x) = foo -> x = box(foo)
    JClassType boxedType = (JClassType) boxed.getType();
    return  new JBinaryOperation(x.getSourceInfo(), boxedType, x.getOp(), boxed,
        autoboxUtils.box(x.getRhs(), (JPrimitiveType) lhs.getType()));
  }

  @Override
  public void endVisit(JBinaryOperation x, Context ctx) {
    if (!x.isAssignment()) {
      return;
    }

    JBinaryOperation result = maybeFixLhsCast(maybeUndoBox(x));

    if (result != x) {
      ctx.replaceMe(result);
    }
  }
}
