/*
 * Copyright 2007 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.android.jack.ir.ast;

import javax.annotation.Nonnull;

/**
 * For precedence indices, see the Java Programming Language, 4th Edition, p.
 * 750, Table 2. I just numbered the table top to bottom as 0 through 14. Lower
 * number means higher precedence.
 */
public enum JBinaryOperator {

  // Don't renumber precs without checking implementation of isShiftOperator()

  MUL("*", 3), DIV("/", 3), MOD("%", 3), ADD("+", 4), CONCAT("+", 4), SUB("-", 4), SHL("<<", 5),
    SHR(">>", 5), SHRU(">>>", 5), LT("<", 6), LTE("<=", 6), GT(">", 6), GTE(">=", 6), EQ("==", 7),
    NEQ("!=", 7), BIT_AND("&", 8), BIT_XOR("^", 9), BIT_OR("|", 10), AND("&&", 11), OR("||", 12),
    ASG("=", 14), ASG_ADD("+=", 14, ADD), ASG_CONCAT("+=", 14, CONCAT), ASG_SUB("-=", 14, SUB),
    ASG_MUL("*=", 14, MUL), ASG_DIV("/=", 14, DIV), ASG_MOD("%=", 14, MOD),
    ASG_SHL("<<=", 14, SHL), ASG_SHR(">>=", 14, SHR), ASG_SHRU(">>>=", 14, SHRU),
    ASG_BIT_AND("&=", 14, BIT_AND), ASG_BIT_OR("|=", 14, BIT_OR), ASG_BIT_XOR("^=", 14, BIT_XOR);

  private final JBinaryOperator nonAsg;
  private final int precedence;
  private final String symbol;

  private JBinaryOperator(String symbol, int precedence) {
    this(symbol, precedence, null);
  }

  private JBinaryOperator(String symbol, int precedence, JBinaryOperator nonAsg) {
    this.symbol = symbol;
    this.precedence = precedence;
    this.nonAsg = nonAsg;
  }

  public JBinaryOperator getNonAssignmentOf() {
    return nonAsg;
  }

  public int getPrecedence() {
    return precedence;
  }

  public boolean isConditionalOperation() {
    return (this == AND || this == OR);
  }

  public boolean isLogicalAndBitwiseOperation() {
    return (this == BIT_AND || this == BIT_OR || this == BIT_XOR);
  }

  @Nonnull
  public JBinaryOperator getReverseOperator() throws UnsupportedOperatorException {
    switch (this) {
      case BIT_AND: {
        return BIT_OR;
      }
      case BIT_OR: {
        return BIT_AND;
      }
      // XOR:          EQ:
      // T XOR T = F   T EQ T = T
      // T XOR F = T   T EQ F = F
      // F XOR T = T   F EQ T = F
      // F XOR F = F   F EQ F = T
      case BIT_XOR: {
        return EQ;
      }
      case AND: {
        return OR;
      }
      case OR: {
        return AND;
      }
      case LT: {
        return GTE;
      }
      case LTE: {
        return GT;
      }
      case GT: {
        return LTE;
      }
      case GTE: {
        return LT;
      }
      case EQ: {
        return NEQ;
      }
      case NEQ: {
        return EQ;
      }
      default: {
        throw new UnsupportedOperatorException("Unsupported operator: " + this.toString());
      }
    }
  }

  public boolean isComparison() {
    return (this == LT || this == LTE || this == GT || this == GTE || this == EQ || this == NEQ);
  }

  public boolean isAssignment() {
    return (this == ASG) || (getNonAssignmentOf() != null);
  }

  public boolean isCompoundAssignment() {
    return (getNonAssignmentOf() != null);
  }

  public boolean isShiftOperator() {
    // Fragile implementation.
    return precedence == 5 || (nonAsg != null && nonAsg.precedence == 5);
  }

  @Override
  public String toString() {
    return symbol;
  }
}
