/*
 * 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.JClassType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JType;

/**
 * <p>
 * Rewrite Java <code>==</code> so that it will execute correctly in JavaScript.
 * After this pass, Java's <code>==</code> is considered equivalent to
 * JavaScript's <code>===</code>.
 * </p>
 * <p>
 * Whenever possible, a Java <code>==</code> is replaced by a JavaScript
 * <code>==</code>. This is shorter than <code>===</code>, and it avoids any
 * complication due to GWT treating both <code>null</code> and
 * <code>undefined</code> as a valid translation of a Java <code>null</code>.
 * </p>
 * <p>
 * However, whenever something that may be a String is compared to something
 * that may not be a <code>String</code>, use <code>===</code>. A Java object
 * compared to a string should always yield false, but that's not true when
 * comparing in JavaScript using <code>==</code>. The cases where
 * <code>===</code> must be used are:
 * </p>
 * <ul>
 * <li>One or both sides have unknown <code>String</code> status.</li>
 * <li>One side is definitely <code>String</code> and one side is definitely !
 * <code>String</code>. <br/>
 * TODO: This case could be optimized as
 * <code>(a == null) &amp; (b == null)</code>.</li>
 * </ul>
 * <p>
 * Since <code>null !== undefined</code>, it is also necessary to normalize
 * <code>null</code> vs. <code>undefined</code> if it's possible for one side to
 * be <code>null</code> and the other to be <code>undefined</code>.
 * </p>
 */
public class EqualityNormalizer {

  /**
   * Breaks apart certain complex assignments.
   */
  private class BreakupAssignOpsVisitor extends JModVisitor {

    @Override
    public void endVisit(JBinaryOperation x, Context ctx) {
      JBinaryOperator op = x.getOp();
      if (op != JBinaryOperator.EQ && op != JBinaryOperator.NEQ) {
        return;
      }
      JExpression lhs = x.getLhs();
      JExpression rhs = x.getRhs();
      JType lhsType = lhs.getType();
      JType rhsType = rhs.getType();
      if (!(lhsType instanceof JReferenceType)) {
        assert !(rhsType instanceof JReferenceType);
        return;
      }

      StringStatus lhsStatus = getStringStatus((JReferenceType) lhsType);
      StringStatus rhsStatus = getStringStatus((JReferenceType) rhsType);
      int strat = COMPARISON_STRAT[lhsStatus.getIndex()][rhsStatus.getIndex()];

      switch (strat) {
        case STRAT_TRIPLE: {
          if (canBeNull(lhs) && canBeNull(rhs)) {
            /*
             * If it's possible for one side to be null and the other side
             * undefined, then mask both sides.
             */
            lhs = maskUndefined(lhs);
            rhs = maskUndefined(rhs);
          }

          JBinaryOperation binOp =
              new JBinaryOperation(x.getSourceInfo(), x.getType(), x.getOp(), lhs, rhs);
          ctx.replaceMe(binOp);
          break;
        }

        case STRAT_DOUBLE: {
          boolean lhsNullLit = lhs == program.getLiteralNull();
          boolean rhsNullLit = rhs == program.getLiteralNull();
          if ((lhsNullLit && rhsStatus == StringStatus.NOTSTRING)
              || (rhsNullLit && lhsStatus == StringStatus.NOTSTRING)) {
            /*
             * If either side is a null literal and the other is non-String,
             * replace with a null-check.
             */
            String methodName;
            if (op == JBinaryOperator.EQ) {
              methodName = "Cast.isNull";
            } else {
              methodName = "Cast.isNotNull";
            }
            JMethod isNullMethod = program.getIndexedMethod(methodName);
            JMethodCall call = new JMethodCall(x.getSourceInfo(), null, isNullMethod);
            call.addArg(lhsNullLit ? rhs : lhs);
            ctx.replaceMe(call);
          } else {
            // Replace with a call to Cast.jsEquals, which does a == internally.
            String methodName;
            if (op == JBinaryOperator.EQ) {
              methodName = "Cast.jsEquals";
            } else {
              methodName = "Cast.jsNotEquals";
            }
            JMethod eqMethod = program.getIndexedMethod(methodName);
            JMethodCall call = new JMethodCall(x.getSourceInfo(), null, eqMethod);
            call.addArgs(lhs, rhs);
            ctx.replaceMe(call);
          }
          break;
        }
      }
    }

    private StringStatus getStringStatus(JReferenceType type) {
      JClassType stringType = program.getTypeJavaLangString();
      if (type == program.getTypeNull()) {
        return StringStatus.NULL;
      } else if (program.typeOracle.canTriviallyCast(type, stringType)) {
        return StringStatus.STRING;
      } else if (program.typeOracle.canTheoreticallyCast(type, stringType)) {
        return StringStatus.UNKNOWN;
      } else {
        return StringStatus.NOTSTRING;
      }
    }

    private JExpression maskUndefined(JExpression lhs) {
      assert ((JReferenceType) lhs.getType()).canBeNull();

      JMethod maskMethod = program.getIndexedMethod("Cast.maskUndefined");
      JMethodCall lhsCall = new JMethodCall(lhs.getSourceInfo(), null, maskMethod, lhs.getType());
      lhsCall.addArg(lhs);
      return lhsCall;
    }
  }

  /**
   * Represents what we know about an operand type in terms of its type and
   * <code>null</code> status.
   */
  private enum StringStatus {
    NOTSTRING(2), NULL(3), STRING(1), UNKNOWN(0);

    private int index;

    StringStatus(int index) {
      this.index = index;
    }

    public int getIndex() {
      return index;
    }
  }

  /**
   * A map of the combinations where each comparison strategy should be used.
   */
  private static int[][] COMPARISON_STRAT = {
      // ..U..S.!S..N
      {1, 1, 1, 0,}, // UNKNOWN
      {1, 0, 1, 0,}, // STRING
      {1, 1, 0, 0,}, // NOTSTRING
      {0, 0, 0, 0,}, // NULL
  };

  /**
   * The comparison strategy of using ==.
   */
  private static final int STRAT_DOUBLE = 0;

  /**
   * The comparison strategy of using ===.
   */
  private static final int STRAT_TRIPLE = 1;

  public static void exec(JProgram program) {
    new EqualityNormalizer(program).execImpl();
  }

  private static boolean canBeNull(JExpression x) {
    return ((JReferenceType) x.getType()).canBeNull();
  }

  private final JProgram program;

  private EqualityNormalizer(JProgram program) {
    this.program = program;
  }

  private void execImpl() {
    BreakupAssignOpsVisitor breaker = new BreakupAssignOpsVisitor();
    breaker.accept(program);
  }

}
