package LBJ2.IR; import java.util.HashSet; import LBJ2.Pass; import LBJ2.frontend.TokenValue; /** * This class represents a method call. * * @author Nick Rizzolo **/ public class MethodInvocation extends StatementExpression { /** * (ø) This expression evaluates to the object whose method will be * called. **/ public Expression parentObject; /** (¬ø) The name of the method to be invoked. */ public Name name; /** (¬ø) The argument expressions passed to the method. */ public ExpressionList arguments; /** * Filled in by the <code>SemanticAnalysis</code> pass, this variable is * set to <code>true</code> iff this invocation represents a classifier * invocation. * * @see LBJ2.SemanticAnalysis **/ public boolean isClassifierInvocation; /** * Filled in by the <code>SemanticAnalysis</code> pass, this variable is * set to <code>true</code> iff this invocation is the argument of a * learning classifier expression's evaluate clause. * * @see LBJ2.SemanticAnalysis **/ public boolean isEvaluateArgument; /** * The <code>SemanticAnalysis</code> pass will let this * <code>MethodInvocation</code> know if it is the immediate * <code>value</code> child of a <code>SenseStatement</code> by setting * this flag. * * @see LBJ2.SemanticAnalysis **/ public boolean isSensedValue; /** * Initializing constructor. Line and byte offset information is taken * from the representation of the name. * * @param n The name of the method being invoked. **/ public MethodInvocation(Name n) { this(n, new ExpressionList()); } /** * Initializing constructor. Line and byte offset information is taken * from the representation of the name. * * @param n The name of the method being invoked. * @param a The argument expressions passed to the method. **/ public MethodInvocation(Name n, ExpressionList a) { this(null, n, a, n.line, n.byteOffset); } /** * Parser's constructor. Line and byte offset information is taken from * the representation of the name. * * @param p Represents the object whose method is being invoked. * @param n Token representing the name of the method being invoked. **/ public MethodInvocation(Expression p, TokenValue n) { this(p, n, new ExpressionList()); } /** * Parser's constructor. Line and byte offset information is taken from * the representation of the name. * * @param p Represents the object whose method is being invoked. * @param n Token representing the name of the method being invoked. * @param a The argument expressions passed to the method. **/ public MethodInvocation(Expression p, TokenValue n, ExpressionList a) { this(p, new Name(n), a, n.line, n.byteOffset); } /** * Full constructor. * * @param p Represents the object whose method is being invoked. * @param n The name of the method being invoked. * @param a The argument expressions passed to the method. * @param line The line on which the source code represented by this * node is found. * @param byteOffset The byte offset from the beginning of the source file * at which the source code represented by this node is * found. **/ public MethodInvocation(Expression p, Name n, ExpressionList a, int line, int byteOffset) { super(line, byteOffset); parentObject = p; name = n; arguments = a; isClassifierInvocation = isEvaluateArgument = isSensedValue = false; } /** * Returns a set of <code>Argument</code>s storing the name and type of * each variable that is a subexpression of this expression. This method * cannot be run before <code>SemanticAnalysis</code> runs. **/ public HashSet getVariableTypes() { HashSet result = new HashSet(); if (parentObject != null) result.addAll(parentObject.getVariableTypes()); result.addAll(name.getVariableTypes(true)); result.addAll(arguments.getVariableTypes()); return result; } /** * Determines if there are any quantified variables in this expression. * This method cannot be run before <code>SemanticAnalysis</code> runs. **/ public boolean containsQuantifiedVariable() { return parentObject != null && parentObject.containsQuantifiedVariable() || name.containsQuantifiedVariable(true) || arguments.containsQuantifiedVariable(); } /** Sets the <code>isSensedValue</code> flag. */ public void senseValueChild() { isSensedValue = true; } /** * Returns a hash code value for java hash structures. * * @return A hash code for this object. **/ public int hashCode() { int result = 31 * name.hashCode() + 17 * arguments.hashCode(); if (parentObject != null) result += 7 * parentObject.hashCode(); return result; } /** * Indicates whether some other object is "equal to" this one. * * @return <code>true</code> iff this object is the same as the argument. **/ public boolean equals(Object o) { if (!(o instanceof MethodInvocation)) return false; MethodInvocation i = (MethodInvocation) o; return (parentObject == null ? i.parentObject == null : parentObject.equals(i.parentObject)) && name.equals(i.name) && arguments.equals(i.arguments); } /** * Returns an iterator used to successively access the children of this * node. * * @return An iterator used to successively access the children of this * node. **/ public ASTNodeIterator iterator() { ASTNodeIterator I = new ASTNodeIterator(parentObject == null ? 2 : 3); if (parentObject != null) I.children[0] = parentObject; I.children[I.children.length - 2] = name; I.children[I.children.length - 1] = arguments; return I; } /** * Creates a new object with the same primitive data, and recursively * creates new member data objects as well. * * @return The clone node. **/ public Object clone() { return new MethodInvocation( (parentObject == null) ? null : (Expression) parentObject.clone(), (Name) name.clone(), (ExpressionList) arguments.clone(), -1, -1); } /** * Ensures that the correct <code>run()</code> method is called for this * type of node. * * @param pass The pass whose <code>run()</code> method should be called. **/ public void runPass(Pass pass) { pass.run(this); } /** * Writes a string representation of this <code>ASTNode</code> to the * specified buffer. The representation written is parsable by the LBJ2 * compiler, but not very readable. * * @param buffer The buffer to write to. **/ public void write(StringBuffer buffer) { if (parenthesized) buffer.append("("); if (parentObject != null) { parentObject.write(buffer); buffer.append("."); } name.write(buffer); buffer.append("("); arguments.write(buffer); buffer.append(")"); if (parenthesized) buffer.append(")"); } }