// 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.devtools.build.lib.events.Location;
import java.io.IOException;

/** Syntax node for a unary operator expression. */
public final class UnaryOperatorExpression extends Expression {

  private final UnaryOperator operator;

  private final Expression operand;

  public UnaryOperatorExpression(UnaryOperator operator, Expression operand) {
    this.operator = operator;
    this.operand = operand;
  }

  public UnaryOperator getOperator() {
    return operator;
  }

  public Expression getOperand() {
    return operand;
  }

  @Override
  public void prettyPrint(Appendable buffer) throws IOException {
    // TODO(bazel-team): Possibly omit parentheses when they are not needed according to operator
    // precedence rules. This requires passing down more contextual information.
    buffer.append(operator.toString());
    buffer.append('(');
    operand.prettyPrint(buffer);
    buffer.append(')');
  }

  @Override
  public String toString() {
    // All current and planned unary operators happen to be prefix operators.
    // Non-symbolic operators have trailing whitespace built into their name.
    //
    // Note that this omits the parentheses for brevity, but is not correct in general due to
    // operator precedence rules. For example, "(not False) in mylist" prints as
    // "not False in mylist", which evaluates to opposite results in the case that mylist is empty.
    return operator.toString() + operand;
  }

  private static Object evaluate(
      UnaryOperator operator,
      Object value,
      Location loc)
      throws EvalException, InterruptedException {
    switch (operator) {
      case NOT:
        return !EvalUtils.toBoolean(value);

      case MINUS:
        if (!(value instanceof Integer)) {
          throw new EvalException(
              loc,
              String.format(
                  "unsupported operand type for -: '%s'", EvalUtils.getDataTypeName(value)));
        }
        try {
          return Math.negateExact((Integer) value);
        } catch (ArithmeticException e) {
          // Fails for -MIN_INT.
          throw new EvalException(loc, e.getMessage());
        }

      default:
        throw new AssertionError("Unsupported unary operator: " + operator);
    }
  }

  @Override
  Object doEval(Environment env) throws EvalException, InterruptedException {
    return evaluate(operator, operand.eval(env), getLocation());
  }

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

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