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

package IR2;

import java.util.*;

public class CallExpr extends RValue {
  protected MethodDescriptor method;
  protected RValue arguments[];

  public CallExpr(MethodDescriptor m, RValue a[])
    throws SemanticTypeException {
    method = m; arguments = a;
    method.typecheck_args(a);
  }

  public int get_type() {
    return method.get_type();
  }

  public MethodDescriptor get_method() {
    return method;
  }

  public RValue[] get_args() {
    return arguments;
  }

  public String desc() {
    String foo = "Call: <"+method.get_name()+"> ( ";
    for (int i=0; i<arguments.length; i++) {
      if (i!=0) foo += ", ";
      foo += arguments[i].desc();
    }
    foo = foo + " )";
    return foo;
  }

  // Generate code for doing call
  public DelocalizedRValue generate_rvalue_asm
    (MethodDescriptor d, Codegen c, CFG output) {

    // Generate the delocalized code to eval the arguments
    DelocalizedRValue [] args = new DelocalizedRValue [arguments.length];
    for (int i=0; i < arguments.length; i++) 
      args[i] = arguments[i].generate_rvalue_asm(d, c, output);

    DelocalizedLValue result = new TempVarDescriptor(d);
    output.addElement(
         new DelocalizedCallInstruction(
                    new DelocalizedLabelInstruction("_" + method.get_name()), 
                    args, result));

    return result;
  }


  /* Algebraic simplification optimization. */
  public RValue algebraic_simplify() {
    for (int i = 0; i < arguments.length; i++)
      arguments[i] = arguments[i].algebraic_simplify();
    return this;
  }


  /* Walkable implementation. */
  public String node_name() {
    return "call_expr";
  }

  public Enumeration neighbors() {
    Vector children = new Vector();
    children.addElement(method);
    for (int i = 0; i < arguments.length; i++)
      children.addElement(arguments[i]);
    return children.elements();
  }

  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();
	if (foo == null) 
	  output += "-error-";
	else
	  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;
  }
}
