/**
*
*/
package soottocfg.cfg.statement;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.base.Preconditions;
import soottocfg.cfg.SourceLocation;
import soottocfg.cfg.expression.Expression;
import soottocfg.cfg.expression.IdentifierExpression;
import soottocfg.cfg.expression.literal.BooleanLiteral;
import soottocfg.cfg.expression.literal.IntegerLiteral;
import soottocfg.cfg.expression.literal.NullLiteral;
import soottocfg.cfg.method.Method;
import soottocfg.cfg.type.BoolType;
import soottocfg.cfg.type.Type;
import soottocfg.cfg.variable.Variable;
/**
* @author schaef
*
*/
public class CallStatement extends Statement {
private static final long serialVersionUID = 7267962774002374725L;
private final Method method;
private final List<Expression> arguments;
private final List<Expression> returnReceiver;
public CallStatement(SourceLocation loc, Method method, List<Expression> arguments,
List<Expression> returnReceiver) {
super(loc);
Preconditions.checkArgument(method.getInParams().size() == arguments.size());
this.method = method;
this.arguments = new LinkedList<Expression>();
this.returnReceiver = returnReceiver;
for (int i = 0; i < arguments.size(); i++) {
Expression arg = arguments.get(i);
Type parType = method.getInParam(i).getType();
if (!(arg instanceof NullLiteral) && !arg.canBeAssignedToType(parType)) {
if (arg instanceof IntegerLiteral && parType == BoolType.instance()) {
if (((IntegerLiteral) arg).getValue() == 0L) {
this.arguments.add(BooleanLiteral.falseLiteral());
} else {
this.arguments.add(BooleanLiteral.trueLiteral());
}
} else {
StringBuilder sb = new StringBuilder();
sb.append("Type mismatch:\n");
sb.append(this.toString());
sb.append("\nAt position " + i);
sb.append(":\nArg " + arg);
sb.append(" of type " + arg.getType());
sb.append(" cannot be assigned to type " + parType);
throw new RuntimeException(sb.toString());
}
} else {
this.arguments.add(arg);
}
}
}
public Method getCallTarget() {
return method;
}
public List<Expression> getArguments() {
return arguments;
}
public List<Expression> getReceiver() {
return returnReceiver;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (!returnReceiver.isEmpty()) {
String delim = "";
for (Expression e : returnReceiver) {
sb.append(delim);
sb.append(e);
delim = ", ";
}
sb.append(" := ");
}
sb.append("call ");
sb.append(this.method.getMethodName());
sb.append("(");
String comma = "";
for (Expression e : this.arguments) {
sb.append(comma);
sb.append(e);
comma = ", ";
}
sb.append(")");
return sb.toString();
}
@Override
public Set<IdentifierExpression> getUseIdentifierExpressions() {
Set<IdentifierExpression> used = new HashSet<IdentifierExpression>();
for (Expression e : arguments) {
used.addAll(e.getUseIdentifierExpressions());
}
return used;
}
@Override
public Set<IdentifierExpression> getDefIdentifierExpressions() {
Set<IdentifierExpression> res = new HashSet<IdentifierExpression>();
for (Expression e : returnReceiver) {
if (e instanceof IdentifierExpression) {
res.add((IdentifierExpression) e);
}
}
return res;
}
@Override
public CallStatement deepCopy() {
List<Expression> argCopy = new LinkedList<Expression>();
for (Expression e : arguments) {
argCopy.add(e.deepCopy());
}
List<Expression> rec = new LinkedList<Expression>();
for (Expression e : returnReceiver) {
rec.add(e.deepCopy());
}
return new CallStatement(getSourceLocation(), method, argCopy, rec);
}
@Override
public CallStatement substitute(Map<Variable, Variable> subs) {
List<Expression> argCopy = new LinkedList<Expression>();
for (Expression e : arguments) {
argCopy.add(e.substitute(subs));
}
List<Expression> rec = new LinkedList<Expression>();
for (Expression e : returnReceiver) {
rec.add(e.substitute(subs));
}
return new CallStatement(getSourceLocation(), method, argCopy, rec);
}
@Override
public CallStatement substituteVarWithExpression(Map<Variable, Expression> subs) {
List<Expression> argCopy = new LinkedList<Expression>();
for (Expression e : arguments) {
argCopy.add(e.substituteVarWithExpression(subs));
}
List<Expression> rec = new LinkedList<Expression>();
for (Expression e : returnReceiver) {
rec.add(e.deepCopy());
}
return new CallStatement(getSourceLocation(), method, argCopy, rec);
}
}