/*
 * 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.JArrayLength;
import com.google.gwt.dev.jjs.ast.JArrayRef;
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.JBlock;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JForStatement;
import com.google.gwt.dev.jjs.ast.JIntLiteral;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNewArray;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JPostfixOperation;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JUnaryOperation;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.JVariableRef;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;

import java.util.Collections;

/**
 * Implements JavaScript varargs calling convention by rewriting varargs calls and adding a
 * prolog to varargs JsMethods.
 * <p>
 * At the calls sites, inline array creation is replaced by array literals, which in turn will be
 * unwrapped as individual parameters at generation time.
 * <p>
 * To implement varargs methods, we analyze the usage of the varargs parameter to determine whether
 * it can be accessed directly (with possibly an offset in the index) or it has to be copied.
 */
public class ImplementJsVarargs {
  /**
   * Analyzes a method body to check whether the varargs parameter can be used directly or not.
   * <p>
   * The arguments variable cannot be used directly if is referenced without indexing or accessing
   * its length, or if it is written to.
   */
  private class NeedsArgumentsCopyAnalyzer extends JVisitor {

    private VarargsProcessingResult result = VarargsProcessingResult.SIMPLE_ACCESS;
    private JParameter varargsParameter;
    private int varargsParameterIndex;

    private NeedsArgumentsCopyAnalyzer(JMethod method) {
      assert method.isJsMethodVarargs();
      this.varargsParameter = Iterables.getLast(method.getParams());
      this.varargsParameterIndex = method.getParams().size() - 1;
      if (varargsParameterIndex != 0) {
        upgradeResult(VarargsProcessingResult.OFFSET_ACCESS);
      }
    }

    @Override
    public void endVisit(JParameterRef x, Context ctx) {
      // Any reference that is not .length or indexed means that we need to copy the varargs array.
      if (isVarargsReference(x)) {
        upgradeResult(VarargsProcessingResult.GENERAL_ACCESS);
      }
    }

    @Override
    public boolean visit(JArrayLength x, Context ctx) {
      if (isVarargsReference(x.getInstance())) {
        // This is a safe reference.
        return false;
      }
      return true;
    }

    @Override
    public boolean visit(JArrayRef x, Context ctx) {
      if (isVarargsReference(x.getInstance())) {
        // This is a safe reference, so only check the index expression.
        accept(x.getIndexExpr());
        return false;
      }

      return true;
    }

    @Override
    public boolean visit(JBinaryOperation x, Context ctx) {
      if (isModifyingVarargs(x)) {
          // The varargs parameter is written to, so upgrade to copy.
          upgradeResult(VarargsProcessingResult.GENERAL_ACCESS);
        return false;
      }
      return true;
    }

    @Override
    public boolean visit(JUnaryOperation x, Context ctx) {
      if (isModifyingVarargs(x)) {
        // The varargs parameter is written to, so upgrade to copy.
        upgradeResult(VarargsProcessingResult.GENERAL_ACCESS);
        return false;
      }
      return true;
    }

    @Override
    public boolean visit(JMethodCall x, Context ctx) {
      // Allow
      if (x.getTarget().isJsMethodVarargs() && x.getArgs().size() == 1
          && isVarargsReference(x.getArgs().get(0))) {
        // The varargs parameter is passed directly and it is the only parameter, so if it is the
        // only parameter in the current method it can be passed directly.
        upgradeResult(VarargsProcessingResult.PASS_WHOLE);
        if (x.getInstance() != null) {
          accept(x.getInstance());
        }
        for (JExpression arg : x.getArgs().subList(1, x.getArgs().size())) {
          accept(arg);
        }
        return false;
      }
      return true;
    }

    private boolean isModifyingVarargs(JBinaryOperation x) {
      if (!x.getOp().isAssignment()) {
        return false;
      }
      if (!(x.getLhs() instanceof JArrayRef)) {
        return false;
      }
      JArrayRef arrayRef = (JArrayRef) x.getLhs();
      JExpression instance = arrayRef.getInstance();
      return isVarargsReference(instance);
    }

    private boolean isModifyingVarargs(JUnaryOperation x) {
      if (!x.getOp().isModifying()) {
        return false;
      }
      if (!(x.getArg() instanceof JArrayRef)) {
        return false;
      }
      JArrayRef arrayRef = (JArrayRef) x.getArg();
      JExpression instance = arrayRef.getInstance();
      return isVarargsReference(instance);
    }

    private boolean isVarargsReference(JExpression instance) {
      if (!(instance instanceof JParameterRef)) {
        return false;
      }

      return (((JParameterRef) instance).getTarget() == varargsParameter);
    }

    private void upgradeResult(VarargsProcessingResult upgradeTo) {
      result = VarargsProcessingResult.join(result, upgradeTo);
    }
  }

  // Defines the analysis lattice
  //                            SIMPLE_ACCESS   (only arguments[i] or arguments.length, no writing)
  //                               /        \
  //  (complete passing of        /          \
  //   arguments)           PASS_WHOLE  OFFSET_ACCESS   (Simple access but needs to offset index)
  //                              \         /
  //                               \       /
  //                             GENERAL_ACCESS
  //
  private enum VarargsProcessingResult {
    SIMPLE_ACCESS, PASS_WHOLE, OFFSET_ACCESS, GENERAL_ACCESS;

    private static VarargsProcessingResult join(
        VarargsProcessingResult thisResult, VarargsProcessingResult thatResult) {
      if (thisResult.ordinal() > thatResult.ordinal()) {
        VarargsProcessingResult swap = thisResult;
        thisResult = thatResult;
        thatResult = swap;
      }

      if ((thisResult == PASS_WHOLE &&  thatResult == OFFSET_ACCESS)) {
        return GENERAL_ACCESS;
      }
      return thatResult;
    }
  }

  private VarargsProcessingResult needsVarargsProcessing(JMethod method) {
    NeedsArgumentsCopyAnalyzer analyzer =  new NeedsArgumentsCopyAnalyzer(method);
    analyzer.accept(method);
    return analyzer.result;
  }

  private abstract class VarargsReplacer {
    abstract JExpression replace(JParameterRef expression);

    JExpression replace(JArrayRef expression) {
      return new JArrayRef(expression.getSourceInfo(),
          replace((JParameterRef)  expression.getInstance()),
          expression.getIndexExpr());
    }

    JExpression replace(JArrayLength expression) {
      return new JArrayLength(expression.getSourceInfo(),
          replace((JParameterRef)  expression.getInstance()));
    }
  }

  /**
   * Replaces varargs parameter accesses with accesses to the copy.
   */
  private class ReplaceVarargsVariable extends VarargsReplacer {
    private JLocal localVariable;
    ReplaceVarargsVariable(JLocal localVariable) {
      this.localVariable = localVariable;
    }

    @Override
    public JExpression replace(JParameterRef expression) {
      return localVariable.createRef(expression.getSourceInfo());
    }
  }

  /**
   * Fixes this indexing of vararg accesses.
   */
  private class ReindexAccess extends VarargsReplacer {
    private int varargsIndex;
    ReindexAccess(int varargsIndex) {
      this.varargsIndex = varargsIndex;
    }

    @Override
    public JExpression replace(JParameterRef expression) {
      return expression;
    }

    JExpression replace(JArrayRef expression) {
      SourceInfo sourceInfo = expression.getSourceInfo();
      return new JArrayRef(expression.getSourceInfo(),
          expression.getInstance(),
          new JBinaryOperation(sourceInfo, JPrimitiveType.INT, JBinaryOperator.ADD,
              expression.getIndexExpr(), new JIntLiteral(sourceInfo, varargsIndex)));
    }

    JExpression replace(JArrayLength expression) {
      SourceInfo sourceInfo = expression.getSourceInfo();
      return new JBinaryOperation(sourceInfo, JPrimitiveType.INT, JBinaryOperator.SUB,
              expression, new JIntLiteral(sourceInfo, varargsIndex));
    }
  }

  private class VarargsMethodNormalizer extends JModVisitor {
    private JParameter varargsParameter;
    private int varargsIndex;
    private VarargsReplacer replacer;
    private JLocal argumentsCopyVariable;

    private boolean needsVarArgsPrologue(JMethod x) {
      // Native methods in general do not have bodies except for constructors; no code is generated
      // from them, safe and convenient to skip here.
      return x.isJsNative() || !x.isJsMethodVarargs();
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      if (needsVarArgsPrologue(x)) {
        return false;
      }
      varargsParameter = Iterables.getLast(x.getParams());
      varargsIndex = x.getParams().size() - 1;

      // JsVarargs parameter can be assumend not null in the implementing method
      varargsParameter.setType(varargsParameter.getType().strengthenToNonNull());

      argumentsCopyVariable = null;
      switch (needsVarargsProcessing(x)) {
        case GENERAL_ACCESS:
          argumentsCopyVariable = JProgram.createLocal(varargsParameter.getSourceInfo(),
              varargsParameter.getName(), varargsParameter.getType(), false,
              (JMethodBody) x.getBody());
          replacer = new ReplaceVarargsVariable(argumentsCopyVariable);
          return true;
        case OFFSET_ACCESS:
          replacer = new ReindexAccess(varargsIndex);
          return true;
       default:
          return false;
      }
    }

    @Override
    public void endVisit(JParameterRef x, Context ctx) {
      if (x.getTarget() == varargsParameter) {
        maybeReplace(x, replacer.replace(x), ctx);
      }
    }

    @Override
    public void endVisit(JArrayRef x, Context ctx) {
      if (x.getInstance() instanceof JParameterRef
          && ((JParameterRef) x.getInstance()).getTarget() == varargsParameter) {
        maybeReplace(x, replacer.replace(x), ctx);
      }
    }

    @Override
    public void endVisit(JArrayLength x, Context ctx) {
      if (x.getInstance() instanceof JParameterRef
          && ((JParameterRef) x.getInstance()).getTarget() == varargsParameter) {
        maybeReplace(x, replacer.replace(x), ctx);
      }
    }

    @Override
    public void endVisit(JMethod x, Context ctx) {
      if (needsVarArgsPrologue(x)) {
        return;
      }
      // rename the varargs variable to _arguments_.
      varargsParameter.setName("_arguments_");
    }

    private void maybeReplace(JExpression x, JExpression replacement, Context ctx) {
      if (replacement != x) {
        ctx.replaceMe(replacement);
      }
    }

    @Override
    public void endVisit(JMethodBody x, Context ctx) {
      if (argumentsCopyVariable == null) {
        return;
      }

      // Needs to populate the copy; add preamble.
      //
      // {
      //   <Type>[] args = new <Type>[arguments.length - offset];
      //   for (int $i = 0; $i < arguments.length - offset; i++) {
      //     args[i] = arguments[i + offset];
      //   }
      // }

      SourceInfo sourceInfo = varargsParameter.getSourceInfo();
      JBlock preamble = new JBlock(sourceInfo);
      JArrayType varargsArrayType = (JArrayType) varargsParameter.getType().getUnderlyingType();

      // (1) varargs_ = new VarArgsType[varargs.length - varArgsParameterIndex]
      JExpression lengthMinusVarargsIndex = varargsIndex == 0
          ? new JArrayLength(sourceInfo, varargsParameter.createRef(sourceInfo))
          : new JBinaryOperation(sourceInfo, JPrimitiveType.INT, JBinaryOperator.SUB,
              new JArrayLength(sourceInfo, varargsParameter.createRef(sourceInfo)),
              new JIntLiteral(sourceInfo, varargsIndex));
      JNewArray arrayVariable = JNewArray.createArrayWithDimensionExpressions(sourceInfo,
          varargsArrayType, Collections.singletonList(lengthMinusVarargsIndex));
      arrayVariable.getLeafTypeClassLiteral().setField(
          program.getClassLiteralField(varargsArrayType.getLeafType()));
      preamble.addStmt(new JDeclarationStatement(
          sourceInfo, argumentsCopyVariable.createRef(sourceInfo), arrayVariable));

      JLocal index = JProgram.createLocal(sourceInfo, "$i", JPrimitiveType.INT, false, x);

      // (2) (copy loop body)  varargs_[i] = varargs[i + varargsIndex];
      JExpression iPlusVarargsIndex = varargsIndex == 0 ? index.createRef(sourceInfo)
          : new JBinaryOperation(sourceInfo, JPrimitiveType.INT, JBinaryOperator.ADD,
              index.createRef(sourceInfo), new JIntLiteral(sourceInfo, varargsIndex));

      JBlock block = new JBlock(sourceInfo);
      block.addStmt(new JBinaryOperation(
          sourceInfo,
          varargsArrayType.getElementType(),
          JBinaryOperator.ASG,
          new JArrayRef(sourceInfo, replacer.replace(varargsParameter.createRef(sourceInfo)),
              index.createRef(sourceInfo)),
          new JArrayRef(sourceInfo, varargsParameter.createRef(sourceInfo), iPlusVarargsIndex))
              .makeStatement());
      // (3) for (int $i = 0 ; i < arguments.length - index; i++) {
      //       varargs_[i] = varargs[i + varargsIndex];
      //     }
      preamble.addStmt(new JForStatement(sourceInfo, Collections.<JStatement>singletonList(
          new JDeclarationStatement(sourceInfo, index.createRef(sourceInfo), JIntLiteral.ZERO)),
          new JBinaryOperation(sourceInfo, JPrimitiveType.INT,JBinaryOperator.LT,
                  index.createRef(sourceInfo),
              new CloneExpressionVisitor().cloneExpression(lengthMinusVarargsIndex)),
          new JPostfixOperation(sourceInfo, JUnaryOperator.INC, index.createRef(sourceInfo)),
          block));
      x.getStatements().add(0, preamble);
    }
  }

  // Normalizes JsVarargsCalls so that
  //  (1) inline new array expressions resulting from a "regular" varargs invocation are replaced
  //      by plain array literals.
  //  (2) side effecting instances in JsVarargs instance method calls with array calling convention
  //      are hoited into temporary variables.
  private class VarargsCallsNormalizer extends JModVisitor {
    private JMethodBody currentMethodBody;

    @Override
    public boolean visit(JMethodBody x, Context ctx) {
      currentMethodBody = x;
      return true;
    }

    @Override
    public void endVisit(JMethodBody x, Context ctx) {
      currentMethodBody = null;
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JMethod method = x.getTarget();
      if (!method.isJsMethodVarargs()) {
        return;
      }

      int varargIndex = method.getParams().size() - 1;
      JExpression varargArgument = x.getArgs().get(varargIndex);
      if (varargArgument instanceof JNewArray) {
        JNewArray varargArray = (JNewArray) varargArgument;
        if (varargArray.getInitializers() != null) {
          x.setArg(varargIndex, ArrayNormalizer.getInitializerArray(varargArray));
          madeChanges();
          return;
        }
      }

      SourceInfo varargsArgumentsourceInfo = varargArgument.getSourceInfo();
      if (varargArgument.getType().canBeNull()) {
        // varargsArgument => Array.ensureNotNull(varargsArgument)
        x.setArg(varargIndex, new JMethodCall(varargsArgumentsourceInfo, null,
            program.getIndexedMethod(RuntimeConstants.ARRAY_ENSURE_NOT_NULL), varargArgument));
      }

      // Passed as an array to varargs method will result in an apply call, in which case hoist the
      // qualifier to make sure it is only evaluated once.
      JExpression instance = x.getInstance();
      if (x.getTarget().needsDynamicDispatch() && !x.isStaticDispatchOnly()
          && instance != null && !(instance instanceof JVariableRef)) {
        // Move the potentially sideffecting qualifier to a temporary variable so that
        // the code generation for calls that need .apply don't need to hande the case.
        SourceInfo sourceInfo = x.getSourceInfo();
        JLocal tempInstance = JProgram.createLocal(sourceInfo, "$instance",
            instance.getType(), false, currentMethodBody);
        // (tempInstance = instance,
        //  tempInstance.method(pars);
        ctx.replaceMe(JjsUtils.createOptimizedMultiExpression(
            new JBinaryOperation(sourceInfo, instance.getType(),
                JBinaryOperator.ASG, tempInstance.createRef(sourceInfo), instance),
            new JMethodCall(x, tempInstance.createRef(sourceInfo), x.getArgs())));
      }
    }
  }

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

  private final JProgram program;

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

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