// $Id: NegOpExpr.java,v 1.1.1.1 1999/12/05 22:19:52 mpp Exp $

package IR2;

import java.util.*;

public class NegOpExpr extends UnaryOpExpr {
  public NegOpExpr(RValue a) throws SemanticTypeException {
    super(a);
    if (a != null && a.get_type() != Typed.INT)
      throw new SemanticTypeException("non-integer expression passed to " +
				      "unary minus");
  }
  
  public String desc() { return super.desc("-"); }

  public DelocalizedRValue generate_rvalue_asm
    (MethodDescriptor d, Codegen c, CFG output) {
    // Crude hack to temporarily deal with MININT until the constant
    // flattening optimization is implemented.
    if (arg instanceof IntImmedExpr) {
      return new DelocalizedImmed(-((IntImmedExpr) arg).get_value());
    } else {
      DelocalizedRValue da1 = new DelocalizedImmed(0);
      DelocalizedRValue da2 = arg.generate_rvalue_asm(d, c, output);
      DelocalizedLValue result = new TempVarDescriptor(d);
      output.addElement
        (new DelocalizedBinaryOpInstruction
         (DelocalizedBinaryOpInstruction.SUB, result, da1, da2));
      return result;
    }
  }

  /* Typed implementation. */
  public int get_type() { return Typed.INT; }


  /* Algebraic simplification optimization. */
  public RValue algebraic_simplify() {
    arg = arg.algebraic_simplify();
    /* -(-i) == i */
    if (arg instanceof NegOpExpr)
      return ((NegOpExpr)arg).arg;
    return this;
  }

  
  /* Walkable implementation. */
  public String node_name() { return "neg_op_expr"; }
  public String pretty_print(int indent, boolean recursive) {
    String output = new String();
    
    for (int i = 0; i < indent; i++) output += " ";
    if (recursive) {
      indent += 2;
      output += "(" + this.node_name() + "\n";
      /* stuff - calls to prettyprints of internals of this node*/
      for (Enumeration e = this.neighbors(); e.hasMoreElements();) {
	Walkable foo = (Walkable)e.nextElement();
	output += foo.pretty_print(indent, true);
	    }
      for (int i = 0; i < indent; i++) output += " ";
      output += ") /* "+ this.node_name() + " */\n";
    } else {
      output += "(" + this.node_name() + ")\n";
    }
    return output;
  }
}

