// Copyright 2017 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 java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Evaluation code for the Skylark AST. At the moment, it can execute only statements (and defers to
 * Expression.eval for evaluating expressions).
 */
public class Eval {
  private final Environment env;

  /** An exception that signals changes in the control flow (e.g. break or continue) */
  private static class FlowException extends EvalException {
    FlowException(String message) {
      super(null, message);
    }

    @Override
    public boolean canBeAddedToStackTrace() {
      return false;
    }
  }

  private static final FlowException breakException = new FlowException("FlowException - break");
  private static final FlowException continueException =
      new FlowException("FlowException - continue");

  public Eval(Environment env) {
    this.env = env;
  }

  void execAssignment(AssignmentStatement node) throws EvalException, InterruptedException {
    Object rvalue = node.getExpression().eval(env);
    node.getLValue().assign(rvalue, env, node.getLocation());
  }

  void execAugmentedAssignment(AugmentedAssignmentStatement node)
      throws EvalException, InterruptedException {
    node.getLValue()
        .assignAugmented(node.getOperator(), node.getExpression(), env, node.getLocation());
  }

  void execIfBranch(IfStatement.ConditionalStatements node)
      throws EvalException, InterruptedException {
    execStatements(node.getStatements());
  }

  void execFor(ForStatement node) throws EvalException, InterruptedException {
    Object o = node.getCollection().eval(env);
    Iterable<?> col = EvalUtils.toIterable(o, node.getLocation(), env);
    EvalUtils.lock(o, node.getLocation());
    try {
      for (Object it : col) {
        node.getVariable().assign(it, env, node.getLocation());

        try {
          execStatements(node.getBlock());
        } catch (FlowException ex) {
          if (ex == breakException) {
            return;
          }
        }
      }
    } finally {
      EvalUtils.unlock(o, node.getLocation());
    }
  }

  void execDef(FunctionDefStatement node) throws EvalException, InterruptedException {
    List<Expression> defaultExpressions = node.getSignature().getDefaultValues();
    ArrayList<Object> defaultValues = null;

    if (defaultExpressions != null) {
      defaultValues = new ArrayList<>(defaultExpressions.size());
      for (Expression expr : defaultExpressions) {
        defaultValues.add(expr.eval(env));
      }
    }

    // TODO(laurentlb): Could be moved to the Parser or the ValidationEnvironment?
    FunctionSignature sig = node.getSignature().getSignature();
    if (sig.getShape().getMandatoryNamedOnly() > 0) {
      throw new EvalException(node.getLocation(), "Keyword-only argument is forbidden.");
    }

    env.update(
        node.getIdentifier().getName(),
        new UserDefinedFunction(
            node.getIdentifier().getName(),
            node.getIdentifier().getLocation(),
            FunctionSignature.WithValues.create(sig, defaultValues, /*types=*/ null),
            node.getStatements(),
            env.getGlobals()));
  }

  void execIf(IfStatement node) throws EvalException, InterruptedException {
    ImmutableList<IfStatement.ConditionalStatements> thenBlocks = node.getThenBlocks();
    // Avoid iterator overhead - most of the time there will be one or few "if"s.
    for (int i = 0; i < thenBlocks.size(); i++) {
      IfStatement.ConditionalStatements stmt = thenBlocks.get(i);
      if (EvalUtils.toBoolean(stmt.getCondition().eval(env))) {
        exec(stmt);
        return;
      }
    }
    execStatements(node.getElseBlock());
  }

  void execLoad(LoadStatement node) throws EvalException, InterruptedException {
    for (Map.Entry<Identifier, String> entry : node.getSymbolMap().entrySet()) {
      try {
        Identifier name = entry.getKey();
        Identifier declared = new Identifier(entry.getValue());

        if (declared.isPrivate()) {
          throw new EvalException(
              node.getLocation(),
              "symbol '" + declared.getName() + "' is private and cannot be imported.");
        }
        // The key is the original name that was used to define the symbol
        // in the loaded bzl file.
        env.importSymbol(node.getImport().getValue(), name, declared.getName());
      } catch (Environment.LoadFailedException e) {
        throw new EvalException(node.getLocation(), e.getMessage());
      }
    }
  }

  void execReturn(ReturnStatement node) throws EvalException, InterruptedException {
    Expression ret = node.getReturnExpression();
    if (ret == null) {
      throw new ReturnStatement.ReturnException(node.getLocation(), Runtime.NONE);
    }
    throw new ReturnStatement.ReturnException(ret.getLocation(), ret.eval(env));
  }

  /**
   * Execute the statement.
   *
   * @throws EvalException if execution of the statement could not be completed.
   * @throws InterruptedException may be thrown in a sub class.
   */
  public void exec(Statement st) throws EvalException, InterruptedException {
    try {
      execDispatch(st);
    } catch (EvalException ex) {
      throw st.maybeTransformException(ex);
    }
  }

  void execDispatch(Statement st) throws EvalException, InterruptedException {
    switch (st.kind()) {
      case ASSIGNMENT:
        execAssignment((AssignmentStatement) st);
        break;
      case AUGMENTED_ASSIGNMENT:
        execAugmentedAssignment((AugmentedAssignmentStatement) st);
        break;
      case CONDITIONAL:
        execIfBranch((IfStatement.ConditionalStatements) st);
        break;
      case EXPRESSION:
        ((ExpressionStatement) st).getExpression().eval(env);
        break;
      case FLOW:
        throw ((FlowStatement) st).getKind() == FlowStatement.Kind.BREAK
            ? breakException
            : continueException;
      case FOR:
        execFor((ForStatement) st);
        break;
      case FUNCTION_DEF:
        execDef((FunctionDefStatement) st);
        break;
      case IF:
        execIf((IfStatement) st);
        break;
      case LOAD:
        execLoad((LoadStatement) st);
        break;
      case PASS:
        break;
      case RETURN:
        execReturn((ReturnStatement) st);
        break;
    }
  }

  private void execStatements(ImmutableList<Statement> statements)
      throws EvalException, InterruptedException {
    // Hot code path, good chance of short lists which don't justify the iterator overhead.
    for (int i = 0; i < statements.size(); i++) {
      exec(statements.get(i));
    }
  }
}
