InvocationStatement.java
package edu.udel.cis.vsl.tass.model.impl.statement;
import java.util.Collection;
import java.util.List;
import edu.udel.cis.vsl.tass.model.IF.FunctionIF;
import edu.udel.cis.vsl.tass.model.IF.ModelFactoryIF;
import edu.udel.cis.vsl.tass.model.IF.SyntaxException;
import edu.udel.cis.vsl.tass.model.IF.expression.ExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.LHSExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.location.InvocationLocationIF;
import edu.udel.cis.vsl.tass.model.IF.statement.InvocationStatementIF;
import edu.udel.cis.vsl.tass.model.IF.type.TypeIF;
import edu.udel.cis.vsl.tass.model.IF.variable.SharedVariableIF;
import edu.udel.cis.vsl.tass.model.IF.variable.VariableIF;
public class InvocationStatement extends Statement implements
InvocationStatementIF {
/** Left-hand side of assignment. May be null. */
private LHSExpressionIF lhs;
/** Function being called. */
private FunctionIF callee;
/** Sequence of actual argument expressions */
ExpressionIF[] arguments;
public InvocationStatement(ModelFactoryIF factory,
InvocationLocationIF sourceLocation, LHSExpressionIF lhs,
FunctionIF callee, List<ExpressionIF> argumentList,
ExpressionIF guard) throws SyntaxException {
super(factory, guard, sourceLocation, StatementKind.INVOCATION);
int numFormals, numActuals, i;
if (callee == null)
throw new NullPointerException("Null callee");
if (!process().equals(callee.process()))
throw new SyntaxException(sourceLocation, "Function " + function()
+ " in process " + process() + " cannot call function "
+ callee + " in other process " + callee.process());
this.callee = callee;
numFormals = callee.numFormals();
if (argumentList == null)
throw new NullPointerException("Null argument list");
numActuals = argumentList.size();
if (callee.hasVariableArguments()) {
if (numActuals < numFormals) {
throw new SyntaxException(sourceLocation, "Expected at least "
+ numFormals + " arguments but saw " + numActuals + ":"
+ arguments);
}
} else {
if (numActuals != numFormals) {
throw new SyntaxException(sourceLocation, "Expected "
+ numFormals + " arguments but saw " + numActuals + ":"
+ arguments);
}
}
arguments = new ExpressionIF[numActuals];
i = 0;
for (ExpressionIF argument : argumentList) {
TypeIF actualType = argument.type();
if (i < numFormals) {
TypeIF formalType = callee.formal(i).type();
if (!actualType.isSubtypeOf(formalType)) {
throw new SyntaxException(argument, "Expected type "
+ formalType + " but saw type " + actualType
+ " in argument " + i + " of call to " + callee);
}
}
factory.checkScope(argument, sourceLocation.scope());
arguments[i] = argument;
i++;
}
if (lhs != null) {
if (!lhs.type().equals(callee.returnType())) {
throw new SyntaxException(lhs,
"Type mis-match: left-hand side has type " + lhs.type()
+ " but function " + callee + " returns type "
+ callee.returnType());
}
factory.checkScope(lhs, sourceLocation.scope());
}
this.lhs = lhs;
}
public InvocationStatement(ModelFactoryIF factory,
InvocationLocationIF sourceLocation, LHSExpressionIF lhs,
FunctionIF callee, List<ExpressionIF> argumentList)
throws SyntaxException {
this(factory, sourceLocation, lhs, callee, argumentList, factory
.booleanLiteralExpression(true));
}
public ExpressionIF[] arguments() {
return arguments;
}
public FunctionIF callee() {
return callee;
}
public LHSExpressionIF lhs() {
return lhs;
}
public String toString() {
String result;
int n = arguments.length;
if (lhs != null) {
result = lhs + " = ";
} else {
result = "";
}
result += callee + "(";
for (int i = 0; i < n; i++) {
if (i > 0)
result += ",";
result += arguments[i].toString();
}
result += ");";
return result;
}
private boolean inSet(VariableIF variable,
Collection<SharedVariableIF> shared) {
return variable instanceof SharedVariableIF
&& shared.contains((SharedVariableIF) variable);
}
public void complete() throws SyntaxException {
Collection<SharedVariableIF> shared = process().model().scope()
.properSharedVariables();
super.complete();
isLocal = true;
if (lhs != null) {
for (VariableIF variable : lhs.freeVariables()) {
if (inSet(variable, shared)) {
isLocal = false;
return;
}
}
}
for (ExpressionIF expression : arguments) {
for (VariableIF variable : expression.freeVariables()) {
if (inSet(variable, shared)) {
isLocal = false;
return;
}
}
}
}
}