/*
 * 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());

      JBinaryOperation operation = new JBinaryOperation(x.getSourceInfo(),
          newLhs.getType(), op.getNonAssignmentOf(), newLhs, x.getRhs());
      // 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;
  }

  protected abstract boolean shouldBreakUp(JBinaryOperation x);

  protected abstract boolean shouldBreakUp(JPostfixOperation x);

  protected abstract boolean shouldBreakUp(JPrefixOperation x);
}
