/*
 * 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.InternalCompilerException;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JIntLiteral;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JLongLiteral;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JParameterRef;
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.JThisRef;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;

/**
 * <p>
 * Replace problematic compound assignments with a sequence of simpler
 * operations, all of which are either simple assignments or are non-assigning
 * operations. When doing so, be careful that side effects happen exactly once
 * and that the order of any side effects is preserved. The choice of which
 * assignments to replace is made in subclasses; they must override the three
 * <code>shouldBreakUp()</code> methods.
 * </p>
 * 
 * <p>
 * Note that because AST nodes are mutable, they cannot be reused in different
 * parts of the same tree. Instead, the node must be cloned before each
 * insertion into a tree other than the first.
 * </p>
 * 
 * <p>
 * If the <code>reuseTemps</code> constructor parameter is set to
 * <code>true</code>, then temps of the correct type will be reused once they
 * become available. To determine when a temp can be reused, the current
 * implementation uses a notion of "temp usage scopes". Every time a temporary
 * variable is allocated, it is recorded in the current temp usage scope. Once
 * the current temp usage scope is exited, all of its temps become available for
 * use for other purposes.
 * </p>
 */
public abstract class CompoundAssignmentNormalizer {
  /**
   * Breaks apart certain complex assignments.
   */
  private class BreakupAssignOpsVisitor extends TempLocalVisitor {

    /**
     * Replaces side effects in lvalue.
     */
    private class ReplaceSideEffectsInLvalue extends JModVisitor {

      private final JMultiExpression multi;

      ReplaceSideEffectsInLvalue(JMultiExpression multi) {
        this.multi = multi;
      }

      public JMultiExpression getMultiExpr() {
        return multi;
      }

      @Override
      public boolean visit(JArrayRef x, Context ctx) {
        JExpression newInstance = possiblyReplace(x.getInstance());
        JExpression newIndexExpr = possiblyReplace(x.getIndexExpr());
        if (newInstance != x.getInstance() || newIndexExpr != x.getIndexExpr()) {
          JArrayRef newExpr = new JArrayRef(x.getSourceInfo(), newInstance, newIndexExpr);
          ctx.replaceMe(newExpr);
        }
        return false;
      }

      @Override
      public boolean visit(JFieldRef x, Context ctx) {
        if (x.getInstance() != null) {
          JExpression newInstance = possiblyReplace(x.getInstance());
          if (newInstance != x.getInstance()) {
            JFieldRef newExpr =
                new JFieldRef(x.getSourceInfo(), newInstance, x.getField(), x.getEnclosingType());
            ctx.replaceMe(newExpr);
          }
        }
        return false;
      }

      @Override
      public boolean visit(JLocalRef x, Context ctx) {
        return false;
      }

      @Override
      public boolean visit(JParameterRef x, Context ctx) {
        return false;
      }

      @Override
      public boolean visit(JThisRef x, Context ctx) {
        return false;
      }

      private JExpression possiblyReplace(JExpression x) {
        if (!x.hasSideEffects()) {
          return x;
        }

        // Create a temp local
        JLocal tempLocal = createTempLocal(x.getSourceInfo(), x.getType());

        // Create an assignment for this temp and add it to multi.
        JLocalRef tempRef = new JLocalRef(x.getSourceInfo(), tempLocal);
        JBinaryOperation asg =
            new JBinaryOperation(x.getSourceInfo(), x.getType(), JBinaryOperator.ASG, tempRef, x);
        multi.exprs.add(asg);
        // Update me with the temp
        return cloner.cloneExpression(tempRef);
      }
    }

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

      /*
       * Convert to an assignment and binary operation. Since the left hand size
       * must be computed twice, we have to replace any left-hand side
       * expressions that could have side effects with temporaries, so that they
       * are only run once.
       */
      ReplaceSideEffectsInLvalue replacer =
          new ReplaceSideEffectsInLvalue(new JMultiExpression(x.getSourceInfo()));
      JExpression newLhs = replacer.accept(x.getLhs());

      JExpression operation =
          new JBinaryOperation(x.getSourceInfo(), newLhs.getType(), op.getNonAssignmentOf(),
              newLhs, x.getRhs());
      operation = modifyResultOperation((JBinaryOperation) operation);

      // newLhs is cloned below because it was used in operation
      JBinaryOperation asg =
          new JBinaryOperation(x.getSourceInfo(), newLhs.getType(), JBinaryOperator.ASG, cloner
              .cloneExpression(newLhs), operation);

      JMultiExpression multiExpr = replacer.getMultiExpr();
      if (multiExpr.exprs.isEmpty()) {
        // just use the split assignment expression
        ctx.replaceMe(asg);
      } else {
        // add the assignment as the last item in the multi
        multiExpr.exprs.add(asg);
        ctx.replaceMe(multiExpr);
      }
    }

    @Override
    public void endVisit(JPostfixOperation x, Context ctx) {
      JUnaryOperator op = x.getOp();
      if (!op.isModifying()) {
        return;
      }
      if (!shouldBreakUp(x)) {
        return;
      }

      // Convert into a comma operation, such as:
      // (t = x, x += 1, t)

      // First, replace the arg with a non-side-effect causing one.
      JMultiExpression multi = new JMultiExpression(x.getSourceInfo());
      ReplaceSideEffectsInLvalue replacer = new ReplaceSideEffectsInLvalue(multi);
      JExpression newArg = replacer.accept(x.getArg());

      JExpression expressionReturn = expressionToReturn(newArg);

      // Now generate the appropriate expressions.
      JLocal tempLocal = createTempLocal(x.getSourceInfo(), expressionReturn.getType());

      // t = x
      JLocalRef tempRef = new JLocalRef(x.getSourceInfo(), tempLocal);
      JBinaryOperation asg =
          new JBinaryOperation(x.getSourceInfo(), x.getType(), JBinaryOperator.ASG, tempRef,
              expressionReturn);
      multi.exprs.add(asg);

      // x += 1
      asg = createAsgOpFromUnary(newArg, op);
      // Break the resulting asg op before adding to multi.
      multi.exprs.add(accept(asg));

      // t
      tempRef = new JLocalRef(x.getSourceInfo(), tempLocal);
      multi.exprs.add(tempRef);

      ctx.replaceMe(multi);
    }

    @Override
    public void endVisit(JPrefixOperation x, Context ctx) {
      JUnaryOperator op = x.getOp();
      if (!op.isModifying()) {
        return;
      }
      if (!shouldBreakUp(x)) {
        return;
      }

      // Convert into the equivalent binary assignment operation, such as:
      // x += 1
      JBinaryOperation asg = createAsgOpFromUnary(x.getArg(), op);

      // Visit the result to break it up even more.
      ctx.replaceMe(accept(asg));
    }

    private JBinaryOperation createAsgOpFromUnary(JExpression arg, JUnaryOperator op) {
      JBinaryOperator newOp;
      if (op == JUnaryOperator.INC) {
        newOp = JBinaryOperator.ASG_ADD;
      } else if (op == JUnaryOperator.DEC) {
        newOp = JBinaryOperator.ASG_SUB;
      } else {
        throw new InternalCompilerException("Unexpected modifying unary operator: "
            + String.valueOf(op.getSymbol()));
      }

      JExpression one;
      if (arg.getType() == JPrimitiveType.LONG) {
        // use an explicit long, so that LongEmulationNormalizer does not get
        // confused
        one = JLongLiteral.get(1);
      } else {
        // int is safe to add to all other types
        one = JIntLiteral.get(1);
      }
      // arg is cloned below because the caller is allowed to use it somewhere
      JBinaryOperation asg =
          new JBinaryOperation(arg.getSourceInfo(), arg.getType(), newOp, cloner
              .cloneExpression(arg), one);
      return asg;
    }
  }

  private final CloneExpressionVisitor cloner = new CloneExpressionVisitor();

  public void accept(JNode node) {
    BreakupAssignOpsVisitor breaker = new BreakupAssignOpsVisitor();
    breaker.accept(node);
  }

  /**
   * Decide what expression to return when breaking up a compound assignment of
   * the form <code>lhs op= rhs</code>. By default the <code>lhs</code> is
   * returned.
   */
  protected JExpression expressionToReturn(JExpression lhs) {
    return lhs;
  }

  /**
   * Decide what expression to return when breaking up a compound assignment of
   * the form <code>lhs op= rhs</code>. The breakup creates an expression of the
   * form <code>lhs = lhs op rhs</code>, and the right hand side of the newly
   * created expression is passed to this method.
   */
  protected JExpression modifyResultOperation(JBinaryOperation op) {
    return op;
  }

  protected abstract boolean shouldBreakUp(JBinaryOperation x);

  protected abstract boolean shouldBreakUp(JPostfixOperation x);

  protected abstract boolean shouldBreakUp(JPrefixOperation x);
}
