// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.syntax;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.events.Location;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Base class for list and dict comprehension expressions.
 *
 * <p>A comprehension contains one or more clauses, e.g. [a+d for a in b if c for d in e] contains
 * three clauses: "for a in b", "if c", "for d in e". For and If clauses can happen in any order,
 * except that the first one has to be a For.
 *
 * <p>The code above can be expanded as:
 *
 * <pre>
 *   for a in b:
 *     if c:
 *       for d in e:
 *         result.append(a+d)
 * </pre>
 *
 * result is initialized to [] (list) or {} (dict) and is the return value of the whole expression.
 */
// TODO(adonovan): replace {Abstract,List,Dict}Comprehension by a single class.
public abstract class AbstractComprehension extends Expression {

  /**
   * The interface implemented by ForClause and (later) IfClause. A comprehension consists of one or
   * more Clauses.
   */
  public interface Clause {

    /** Enum for distinguishing clause types. */
    enum Kind {
      FOR,
      IF
    }

    /**
     * Returns whether this is a For or If clause.
     *
     * <p>This avoids having to rely on reflection, or on checking whether {@link #getLHS} is null.
     */
    Kind getKind();

    /**
     * The evaluation of the comprehension is based on recursion. Each clause may
     * call recursively evalStep (ForClause will call it multiple times, IfClause will
     * call it zero or one time) which will evaluate the next clause. To know which clause
     * is the next one, we pass a step argument (it represents the index in the clauses
     * list). Results are aggregated in the result argument, and are populated by
     * evalStep.
     *
     * @param env environment in which we do the evaluation.
     * @param collector the aggregated results of the comprehension.
     * @param step the index of the next clause to evaluate.
     */
    void eval(Environment env, OutputCollector collector, int step)
        throws EvalException, InterruptedException;

    /** The LHS variables defined in a ForClause, or null for an IfClause. */
    @Nullable
    Expression getLHS();

    /**
     * The Expression defined in Clause, i.e. the collection for ForClause and the
     * condition for IfClause. This is needed for SyntaxTreeVisitor.
     */
    Expression getExpression();

    /** Pretty print to a buffer. */
    void prettyPrint(Appendable buffer) throws IOException;
  }

  /** A for clause in a comprehension, e.g. "for a in b" in the example above. */
  public static final class ForClause implements Clause {
    private final Expression lhs;
    private final Expression iterable;

    @Override
    public Kind getKind() {
      return Kind.FOR;
    }

    public ForClause(Expression lhs, Expression iterable) {
      this.lhs = lhs;
      this.iterable = iterable;
    }

    @Override
    public void eval(Environment env, OutputCollector collector, int step)
        throws EvalException, InterruptedException {
      Object iterableObject = iterable.eval(env);
      Location loc = collector.getLocation();
      Iterable<?> listValue = EvalUtils.toIterable(iterableObject, loc, env);
      EvalUtils.lock(iterableObject, loc);
      try {
        for (Object listElement : listValue) {
          Eval.assign(lhs, listElement, env, loc);
          evalStep(env, collector, step);
        }
      } finally {
        EvalUtils.unlock(iterableObject, loc);
      }
    }

    @Override
    public Expression getLHS() {
      return lhs;
    }

    @Override
    public Expression getExpression() {
      return iterable;
    }

    @Override
    public void prettyPrint(Appendable buffer) throws IOException {
      buffer.append("for ");
      lhs.prettyPrint(buffer);
      buffer.append(" in ");
      iterable.prettyPrint(buffer);
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder();
      try {
        prettyPrint(builder);
      } catch (IOException e) {
        // Not possible for StringBuilder.
        throw new AssertionError(e);
      }
      return builder.toString();
    }
  }

  /** A if clause in a comprehension, e.g. "if c" in the example above. */
  public static final class IfClause implements Clause {
    private final Expression condition;

    @Override
    public Kind getKind() {
      return Kind.IF;
    }

    public IfClause(Expression condition) {
      this.condition = condition;
    }

    @Override
    public void eval(Environment env, OutputCollector collector, int step)
        throws EvalException, InterruptedException {
      if (EvalUtils.toBoolean(condition.eval(env))) {
        evalStep(env, collector, step);
      }
    }

    @Override
    public Expression getLHS() {
      return null;
    }

    @Override
    public Expression getExpression() {
      return condition;
    }

    @Override
    public void prettyPrint(Appendable buffer) throws IOException {
      buffer.append("if ");
      condition.prettyPrint(buffer);
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder();
      try {
        prettyPrint(builder);
      } catch (IOException e) {
        // Not possible for StringBuilder.
        throw new AssertionError(e);
      }
      return builder.toString();
    }
  }

  /**
   * The output expressions, e.g. "a+d" in the example above. This list has either one (list) or two
   * (dict) items.
   */
  private final ImmutableList<Expression> outputExpressions;

  private final ImmutableList<Clause> clauses;

  AbstractComprehension(List<Clause> clauses, Expression... outputExpressions) {
    this.clauses = ImmutableList.copyOf(clauses);
    this.outputExpressions = ImmutableList.copyOf(outputExpressions);
  }

  protected abstract char openingBracket();

  protected abstract char closingBracket();

  public ImmutableList<Expression> getOutputExpressions() {
    return outputExpressions;
  }

  @Override
  public void prettyPrint(Appendable buffer) throws IOException {
    buffer.append(openingBracket());
    printExpressions(buffer);
    for (Clause clause : clauses) {
      buffer.append(' ');
      clause.prettyPrint(buffer);
    }
    buffer.append(closingBracket());
  }

  /** Base class for comprehension builders. */
  public abstract static class AbstractBuilder {

    protected final List<Clause> clauses = new ArrayList<>();

    public void addFor(Expression lhs, Expression iterable) {
      Clause forClause = new ForClause(lhs, iterable);
      clauses.add(forClause);
    }

    public void addIf(Expression condition) {
      clauses.add(new IfClause(condition));
    }

    public abstract AbstractComprehension build();
  }

  public ImmutableList<Clause> getClauses() {
    return clauses;
  }

  @Override
  public void accept(SyntaxTreeVisitor visitor) {
    visitor.visit(this);
  }

  @Override
  public Kind kind() {
    return Kind.COMPREHENSION;
  }

  @Override
  Object doEval(Environment env) throws EvalException, InterruptedException {
    OutputCollector collector = createCollector(env);
    evalStep(env, collector, 0);
    Object result = collector.getResult(env);

    // Undefine loop variables (remove them from the environment).
    // This code is useful for the transition, to make sure no one relies on the old behavior
    // (where loop variables were leaking).
    // TODO(laurentlb): Instead of removing variables, we should create them in a nested scope.
    for (Clause clause : clauses) {
      // Check if a loop variable conflicts with another local variable.
      Expression lhs = clause.getLHS();
      if (lhs != null) {
        for (Identifier ident : ValidationEnvironment.boundIdentifiers(lhs)) {
          env.removeLocalBinding(ident.getName());
        }
      }
    }
    return result;
  }

  /**
   * Evaluate the clause indexed by step, or elementExpression. When we evaluate the
   * comprehension, step is 0 and we evaluate the first clause. Each clause may
   * recursively call evalStep any number of times. After the last clause,
   * the output expression(s) is/are evaluated and added to the results.
   *
   * <p> In the expanded example above, you can consider that evalStep is equivalent to
   * evaluating the line number step.
   */
  private static void evalStep(Environment env, OutputCollector collector, int step)
      throws EvalException, InterruptedException {
    List<Clause> clauses = collector.getClauses();
    if (step >= clauses.size()) {
      collector.evaluateAndCollect(env);
    } else {
      clauses.get(step).eval(env, collector, step + 1);
    }
  }

  /** Pretty-prints the output expression(s). */
  protected abstract void printExpressions(Appendable buffer) throws IOException;

  abstract OutputCollector createCollector(Environment env);

  /**
   * Interface for collecting the intermediate output of an {@code AbstractComprehension} and for
   * providing access to the final results.
   */
  interface OutputCollector {

    /** Returns the location for the comprehension we are evaluating. */
    Location getLocation();

    /** Returns the list of clauses for the comprehension we are evaluating. */
    List<Clause> getClauses();

    /**
     * Evaluates the output expression(s) of the comprehension and collects the result.
     */
    void evaluateAndCollect(Environment env) throws EvalException, InterruptedException;

    /**
     * Returns the final result of the comprehension.
     */
    Object getResult(Environment env) throws EvalException;
  }
}
