/*
 * 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.SourceInfo;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JArrayType;
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.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
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.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JRuntimeTypeReference;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import com.google.gwt.thirdparty.guava.common.collect.Maps;

import java.util.Map;

/**
 * Replace cast and instanceof operations with calls to the Cast class. Depends
 * on {@link CatchBlockNormalizer}, {@link CompoundAssignmentNormalizer},
 * {@link Devirtualizer}, and {@link LongCastNormalizer} having already run.
 * <p>
 * May or may not prune trivial casts depending on configuration.
 */
public class ImplementCastsAndTypeChecks {

  /**
   * Replaces all casts and instanceof operations with calls to implementation
   * methods.
   */
  private class ReplaceTypeChecksVisitor extends JModVisitor {

    @Override
    public void endVisit(JCastOperation x, Context ctx) {
      JType toType = x.getCastType();
      JExpression expr = x.getExpr();

      SourceInfo info = x.getSourceInfo();
      if (pruneTrivialCasts && toType.isNullType()) {
        /**
         * A null type cast is used as a placeholder value to indicate that the
         * user tried a cast that couldn't possibly work. Typically this means
         * either the statically resolvable arg type is incompatible with the
         * target type, or the target type was globally uninstantiable.
         *
         * See {@link TypeTightener.TightenTypesVisitor#endVisit(JCastOperation, Context)}
         *
         * We handle this cast by throwing a ClassCastException, unless the
         * argument is null.
         */
        JMethod method = program.getIndexedMethod(
            RuntimeConstants.CAST_THROW_CLASS_CAST_EXCEPTION_UNLESS_NULL);
        // Note, we must update the method call to return the null type.
        JMethodCall call = new JMethodCall(info, null, method, expr);
        call.overrideReturnType(toType);
        ctx.replaceMe(call);
        return;
      }

      if (toType instanceof JReferenceType) {
        JExpression curExpr = expr;
        JReferenceType refType = (JReferenceType) toType.getUnderlyingType();
        JReferenceType argType = (JReferenceType) expr.getType();

        if (refType instanceof JArrayType) {
          // Arrays of any subclass of JavaScriptObject are considered arrays of JavaScriptObject
          // for casting and instanceof purposes.
          refType =  (JReferenceType) program.normalizeJsoType(refType);
        }

        if (pruneTrivialCasts && program.typeOracle.castSucceedsTrivially(argType, refType) ||
            determineTypeCategoryForType(refType) == TypeCategory.TYPE_JAVA_LANG_OBJECT) {
          // just remove the cast
          ctx.replaceMe(curExpr);
          return;
        } else if (program.typeOracle.isEffectivelyJavaScriptObject(argType)
            && program.typeOracle.isEffectivelyJavaScriptObject(refType)) {
          // leave the cast instance for Pruner/CFA, remove in GenJSAST
          return;
        }
        // A cast is still needed.  Substitute the appropriate Cast implementation.
        ctx.replaceMe(implementCastOrInstanceOfOperation(x.getSourceInfo(), curExpr, refType,
            dynamicCastMethodsByTargetTypeCategory, true));
        return;
      }

      // It is a primitive type, perform the necessary coercion.

      assert toType instanceof JPrimitiveType;
      /*
       * See JLS 5.1.3: if a cast narrows from one type to another, we must
       * call a narrowing conversion function. EXCEPTION: we currently have no
       * way to narrow double to float, so don't bother.
       */
      JPrimitiveType tByte = program.getTypePrimitiveByte();
      JPrimitiveType tChar = program.getTypePrimitiveChar();
      JPrimitiveType tShort = program.getTypePrimitiveShort();
      JPrimitiveType tInt = program.getTypePrimitiveInt();
      JPrimitiveType tLong = program.getTypePrimitiveLong();
      JPrimitiveType tFloat = program.getTypePrimitiveFloat();
      JPrimitiveType tDouble = program.getTypePrimitiveDouble();
      JType fromType = expr.getType();

      String methodName = null;

      if (tLong == fromType && tLong != toType) {
        if (tByte == toType || tShort == toType || tChar == toType) {
          /*
           * We need a double call here, one to convert long->int, and another
           * one to narrow. Construct the inner call here and fall through to
           * do the narrowing conversion.
           */
          JMethod castMethod = program.getIndexedMethod(RuntimeConstants.LONG_LIB_TO_INT);
          JMethodCall call = new JMethodCall(info, null, castMethod);
          call.addArg(expr);
          expr = call;
          fromType = tInt;
        } else if (tInt == toType) {
          methodName = RuntimeConstants.LONG_LIB_TO_INT;
        } else if (tFloat == toType || tDouble == toType) {
          methodName = RuntimeConstants.LONG_LIB_TO_DOUBLE;
        }
      }

      if (toType == tLong && fromType != tLong) {
        // Longs get special treatment.
        if (tByte == fromType || tShort == fromType || tChar == fromType || tInt == fromType) {
          methodName = RuntimeConstants.LONG_LIB_FROM_INT;
        } else if (tFloat == fromType || tDouble == fromType) {
          methodName = RuntimeConstants.LONG_LIB_FROM_DOUBLE;
        }
      } else if (tByte == fromType) {
        if (tChar == toType) {
          methodName = "Cast.narrow_" + toType.getName();
        }
      } else if (tShort == fromType) {
        if (tByte == toType || tChar == toType) {
          methodName = "Cast.narrow_" + toType.getName();
        }
      } else if (tChar == fromType) {
        if (tByte == toType || tShort == toType) {
          methodName = "Cast.narrow_" + toType.getName();
        }
      } else if (tInt == fromType) {
        if (tByte == toType || tShort == toType || tChar == toType) {
          methodName = "Cast.narrow_" + toType.getName();
        }
      } else if (tFloat == fromType || tDouble == fromType) {
        if (tByte == toType || tShort == toType || tChar == toType || tInt == toType) {
          methodName = "Cast.round_" + toType.getName();
        }
      }

      if (methodName != null) {
        JMethod castMethod = program.getIndexedMethod(methodName);
        JMethodCall call = new JMethodCall(info, null, castMethod, expr);
        call.overrideReturnType(toType);
        ctx.replaceMe(call);
      } else {
        // Just remove the cast
        ctx.replaceMe(expr);
      }
    }

    @Override
    public void endVisit(JInstanceOf x, Context ctx) {
      JReferenceType argType = (JReferenceType) x.getExpr().getType();
      JReferenceType toType = x.getTestType();
      // Only tests on run-time types are supported
      assert (toType == toType.getUnderlyingType());

      if (toType instanceof JArrayType) {
        // Arrays of any subclass of JavaScriptObject are considered arrays of JavaScriptObject
        // for casting and instanceof purposes.
        toType =  (JReferenceType) program.normalizeJsoType(toType);
      }

      assert !toType.isJsNative() || !(toType instanceof JInterfaceType);

      boolean isTrivialCast = program.typeOracle.castSucceedsTrivially(argType, toType)
          // don't depend on type-tightener having run
          || (program.typeOracle.isEffectivelyJavaScriptObject(argType)
              && program.typeOracle.isEffectivelyJavaScriptObject(toType));
      if (pruneTrivialCasts && isTrivialCast ||
          determineTypeCategoryForType(toType) == TypeCategory.TYPE_JAVA_LANG_OBJECT) {
        // trivially true if non-null; replace with a null test
        JBinaryOperation eq =
            new JBinaryOperation(x.getSourceInfo(), program.getTypePrimitiveBoolean(),
                JBinaryOperator.NEQ, x.getExpr(), program.getLiteralNull());
        ctx.replaceMe(eq);
      } else {
        // Replace the instance of check by a call to the appropriate instanceof method in class
        // Cast.
        ctx.replaceMe(implementCastOrInstanceOfOperation(x.getSourceInfo(), x.getExpr(), toType,
            instanceOfMethodsByTargetTypeCategory, false));
      }
    }
  }

  /**
   * Determines the type category for a specific reference type.
   */
  private TypeCategory determineTypeCategoryForType(JReferenceType type) {
    TypeCategory typeCategory = TypeCategory.typeCategoryForType(type, program);

    assert typeCategory.castInstanceOfQualifier() != null;

    return typeCategory;
  }

  /**
   * Returns an expression implementing the instanceof/dynamicCast operations.
   */
  private JMethodCall implementCastOrInstanceOfOperation(SourceInfo sourceInfo,
      JExpression targetExpression, JReferenceType targetType,
      Map<TypeCategory, JMethod> targetMethodByTypeCategory, boolean overrideReturnType) {

    TypeCategory targetTypeCategory = determineTypeCategoryForType(targetType);
    JMethod method = targetMethodByTypeCategory.get(targetTypeCategory);
    assert method != null;
    JMethodCall call = new JMethodCall(sourceInfo, null, method);
    if (overrideReturnType) {
      // Create a method call overriding the return type so that operations like Cast.dynamicCast
      // don't change the type of the original method call expression.
      call.overrideReturnType(targetType);
    }

    call.addArg(targetExpression);

    if (method.getParams().size() < 2) {
      // The cast checking method does not require an additional parameter. This situation arises
      // when the call is a cast check and cast checking has been disabled or when the type category
      // provides enough information, e.g. TYPE_UNTYPED_ARRAY.
      return call;
    } else if (targetTypeCategory.requiresTypeId()) {
      call.addArg((new JRuntimeTypeReference(sourceInfo, program.getTypeJavaLangObject(),
          targetType)));
      return call;
    } else if (targetTypeCategory.requiresJsConstructor()) {
      JDeclaredType declaredType = (JDeclaredType) targetType;

      JMethod jsConstructor = JjsUtils.getJsNativeConstructorOrNull(declaredType);
      assert jsConstructor != null &&  declaredType.isJsNative();
      call.addArg(new JsniMethodRef(sourceInfo, declaredType.getQualifiedJsName(), jsConstructor,
          program.getJavaScriptObject()));
      return call;
    } else {
      throw new AssertionError();
    }
  }

  public static void exec(JProgram program, boolean pruneTrivialCasts) {
    new ImplementCastsAndTypeChecks(program, pruneTrivialCasts).execImpl();
  }

  public static void exec(JProgram program) {
    new ImplementCastsAndTypeChecks(program, true).execImpl();
  }

  private final boolean pruneTrivialCasts;
  private final JProgram program;

  private Map<TypeCategory, JMethod> instanceOfMethodsByTargetTypeCategory =
      Maps.newEnumMap(TypeCategory.class);

  private Map<TypeCategory, JMethod> dynamicCastMethodsByTargetTypeCategory =
      Maps.newEnumMap(TypeCategory.class);

  private ImplementCastsAndTypeChecks(JProgram program, boolean pruneTrivialCasts) {
    this.program = program;
    this.pruneTrivialCasts = pruneTrivialCasts;

    for (TypeCategory t : TypeCategory.values()) {
      String castInstanceOfQualifier = t.castInstanceOfQualifier();
      if (castInstanceOfQualifier == null) {
        continue;
      }
      String instanceOfMethod = "Cast.instanceOf" + castInstanceOfQualifier;
      instanceOfMethodsByTargetTypeCategory.put(t, program.getIndexedMethod(instanceOfMethod));
      String castMethod = "Cast.castTo" + castInstanceOfQualifier;
      dynamicCastMethodsByTargetTypeCategory.put(t, program.getIndexedMethod(castMethod));
    }
  }

  private void execImpl() {
    new ReplaceTypeChecksVisitor().accept(program);
  }
}
