/**
 *  @(#) UnaryOpExpression.java
 *
 * JReversePro - Java Decompiler / Disassembler.
 * Copyright (C) 2008 Karthik Kumar.
 * 
 * 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 net.sf.jrevpro.ast.expression;

import net.sf.jrevpro.ast.evaluator.EvaluatorStack;
import net.sf.jrevpro.jls.JLSConstants;
import net.sf.jrevpro.jvm.JVMConstants;
import net.sf.jrevpro.jvm.TypeInferrer;
import net.sf.jrevpro.reflect.Import;

/**
 * @author akkumar
 * 
 */
public class UnaryOpExpression extends Expression {

  public enum UnaryOperator {
    NEGATE, CAST_LONG, CAST_FLOAT, CAST_DOUBLE, CAST_INT, CAST_BYTE, CAST_CHAR, CAST_SHORT, UNARY_PLUS, UNARY_MINUS, CAST_REFERENCE
  };

  public UnaryOpExpression(Expression _expr, UnaryOperator op, char type) {
    super(type, L_UNARY);
    expr = _expr;

  }

  public UnaryOpExpression(Expression _expr, UnaryOperator op, String type) {
    super(type, L_UNARY);
    expr = _expr;

  }

  /*
   * (non-Javadoc)
   * 
   * @see net.sf.jrevpro.jls.expression.Expression#getJLSRepresentation()
   */
  @Override
  public String getJLSCode() {
    switch (op) {
    case NEGATE:
      return JLSConstants.MINUS + expr.getValueEx(L_UNARY);
    case CAST_LONG:
      return JLSConstants.OPEN_BRACKET + JLSConstants.JLS_TYPE_LONG
          + JLSConstants.CLOSE_BRACKET + expr.getValueEx(L_CAST);
    case CAST_FLOAT:
      return JLSConstants.OPEN_BRACKET + JLSConstants.JLS_TYPE_FLOAT
          + JLSConstants.CLOSE_BRACKET + expr.getValueEx(L_CAST);
    case CAST_DOUBLE:
      return JLSConstants.OPEN_BRACKET + JLSConstants.JLS_TYPE_DOUBLE
          + JLSConstants.CLOSE_BRACKET + expr.getValueEx(L_CAST);
    case CAST_INT:
      return JLSConstants.OPEN_BRACKET + JLSConstants.JLS_TYPE_INT
          + JLSConstants.CLOSE_BRACKET + expr.getValueEx(L_CAST);
    case CAST_BYTE:
      return JLSConstants.OPEN_BRACKET + JLSConstants.JLS_TYPE_BYTE
          + JLSConstants.CLOSE_BRACKET + expr.getValueEx(L_CAST);
    case CAST_CHAR:
      return JLSConstants.OPEN_BRACKET + JLSConstants.JLS_TYPE_CHAR
          + JLSConstants.CLOSE_BRACKET + expr.getValueEx(L_CAST);
    case CAST_SHORT:
      return JLSConstants.OPEN_BRACKET + JLSConstants.JLS_TYPE_SHORT
          + JLSConstants.CLOSE_BRACKET + expr.getValueEx(L_CAST);
    case CAST_REFERENCE:
      return JLSConstants.OPEN_BRACKET
          + Import.getClassName(TypeInferrer.getJLSType(jvmType, false))
          + JLSConstants.CLOSE_BRACKET + expr.getValueEx(L_CAST);
    default:
      throw new IllegalArgumentException("Unary operator " + op
          + " not supported");
    }
  }

  public static void evaluateCasting(EvaluatorStack opStack, UnaryOperator unop) {
    Expression expr = opStack.pop();

    UnaryOperator op = UnaryOperator.CAST_BYTE;
    char type = JVMConstants.JVM_TYPE_BYTE;

    switch (unop) {
    case CAST_LONG:
      op = UnaryOperator.CAST_LONG;
      type = JVMConstants.JVM_TYPE_LONG;
      break;
    case CAST_FLOAT:
      op = UnaryOperator.CAST_FLOAT;
      type = JVMConstants.JVM_TYPE_FLOAT;
      break;
    case CAST_DOUBLE:
      op = UnaryOperator.CAST_DOUBLE;
      type = JVMConstants.JVM_TYPE_DOUBLE;
      break;
    case CAST_INT:
      op = UnaryOperator.CAST_INT;
      type = JVMConstants.JVM_TYPE_INT;
      break;
    case CAST_BYTE:
      op = UnaryOperator.CAST_BYTE;
      type = JVMConstants.JVM_TYPE_BYTE;
      break;
    case CAST_CHAR:
      op = UnaryOperator.CAST_CHAR;
      type = JVMConstants.JVM_TYPE_CHAR;
      break;
    case CAST_SHORT:
      op = UnaryOperator.CAST_SHORT;
      type = JVMConstants.JVM_TYPE_SHORT;
      break;
    default:
      throw new IllegalArgumentException("Invalid cast exception" + unop);
    }

    opStack.push(new UnaryOpExpression(expr, op, type));

  }

  public static void evaluateUnary(EvaluatorStack opStack, UnaryOperator unop,
      char type) {
    Expression expr = opStack.pop();
    UnaryOpExpression exp = new UnaryOpExpression(expr, unop, type);
    opStack.push(exp);
  }

  private Expression expr;

  private UnaryOperator op;

}

@@ -1026,16 +1026,19 @@
 sion %7B%0A%0A
+  %0A
   public
@@ -1067,141 +1067,512 @@
     
-NEGATE, CAST_LONG, CAST_FLOAT, CAST_DOUBLE, CAST_INT, CAST_BYTE, CAST_CHAR, CAST_SHORT, UNARY_PLUS, UNARY_MINUS, CAST_REFERENCE%0A  %7D;%0A
+/**%0A     * '-4' , say%0A     */%0A    NEGATE, %0A    /**%0A     * '(long)'%0A     */%0A    CAST_LONG, %0A    /**%0A     * '(float)'%0A     */%0A    CAST_FLOAT, %0A    /**%0A     * '(double)'%0A     */%0A    CAST_DOUBLE, %0A    /**%0A     * '(int)'%0A     */%0A    CAST_INT, %0A    /**%0A     * '(byte)'%0A     */%0A    CAST_BYTE, %0A    /**%0A     * '(char)'%0A     */    %0A    CAST_CHAR, %0A    /**%0A     * '(short)'%0A     */%0A    CAST_SHORT, UNARY_PLUS, UNARY_MINUS, CAST_REFERENCE%0A  %7D;%0A%0A  private final Expression expr;%0A%0A  private final UnaryOperator op;%0A  
 %0A  p
@@ -1679,32 +1679,50 @@
    expr = _expr;
+%0A    this.op = op;
 %0A%0A  %7D%0A%0A  public 
@@ -1834,16 +1834,33 @@
  _expr;%0A
+    this.op = op;
 %0A  %7D%0A%0A  
@@ -4918,63 +4918,8 @@
  %7D%0A%0A
-  private Expression expr;%0A%0A  private UnaryOperator op;
 %0A%0A%7D%0A

Add comments to the various operators.