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

package IR2;

import java.util.*;

public class CalloutExpr extends RValue {
  protected String function;
  protected RValue arguments[];

  public CalloutExpr(String f, RValue a[]) throws SemanticTypeException {
    function = f; arguments = a;
    for (int i = 0; i < a.length; i++) {
      if (a[i] != null && a[i].get_type() == Typed.VOID)
	throw new SemanticTypeException("void-typed expression passed to " +
					"argument " + (i+1) + 
					" of callout(\"" + function + 
					"\", ...)");
    }
  }

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

  public String desc() {
    String foo = "CALLOUTEXPR: <"+function+"> ( ";
    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 DelocalizedCalloutInstruction(
                    new DelocalizedLabelInstruction(function),
                    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 "callout_expr";
  }
  public Enumeration neighbors() {
    return new ShortEnumeration(arguments);
  }
  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;
  }
}
