_addInequality(debug, solver, firstArgTerm, thirdArgTerm);
_addInequality(debug, solver, thirdArgTerm, firstArgTerm);
return null;
}
} else if (value instanceof InstanceInvokeExpr) {
InstanceInvokeExpr r = (InstanceInvokeExpr) value;
String methodName = r.getMethod().getName();
// If we are invoking on something that is not a reference type,
// then ignore it.
if (!(r.getBase().getType() instanceof RefType)) {
return null;
}
// System.out.println("invokeExpr = " + r);
SootClass baseClass = ((RefType) r.getBase().getType())
.getSootClass();
InequalityTerm baseTerm = (InequalityTerm) objectToInequalityTerm
.get(r.getBase());
// FIXME: match better.
// If we are invoking a method on a token, then...
if (SootUtilities
.derivesFrom(baseClass, PtolemyUtilities.typeClass)) {
if (methodName.equals("convert")) {
return baseTerm;
// try {
// ptolemy.data.type.Type baseType = PtolemyUtilities
// .getTypeValue(method, (Local) r.getBase(),
// unit, localDefs, localUses);
// InequalityTerm baseTypeTerm = new ConstantTerm(
// baseType, r);
// return baseTypeTerm;
// } catch (RuntimeException ex) {
// // Ignore..
// }
} else if (r
.getMethod()
.getSignature()
.equals(
"<ptolemy.data.type.ArrayType: void <init>(ptolemy.data.type.Type)>")) {
InequalityTerm elementTerm = (InequalityTerm) objectToInequalityTerm
.get(r.getArg(0));
ptolemy.data.type.ArrayType arrayType = new ptolemy.data.type.ArrayType(
ptolemy.data.type.BaseType.UNKNOWN);
InequalityTerm variableTerm = new VariableTerm(arrayType, r);
_addInequality(debug, solver, elementTerm, arrayType
.getElementTypeTerm());
_addInequality(debug, solver, arrayType
.getElementTypeTerm(), elementTerm);
_addInequality(debug, solver, variableTerm, baseTerm);
return variableTerm;
}
}
if (SootUtilities.derivesFrom(baseClass,
PtolemyUtilities.tokenClass)) {
if (r.getMethod()
.equals(PtolemyUtilities.arrayTokenConstructor)) {
InequalityTerm firstArgTerm = (InequalityTerm) objectToInequalityTerm
.get(r.getArg(0));
ptolemy.data.type.ArrayType arrayType = new ptolemy.data.type.ArrayType(
ptolemy.data.type.BaseType.UNKNOWN);
VariableTerm newTerm = new VariableTerm(arrayType, r);
_addInequality(debug, solver, baseTerm, newTerm);
_addInequality(debug, solver, newTerm, baseTerm);
InequalityTerm elementTerm = arrayType.getElementTypeTerm();
_addInequality(debug, solver, firstArgTerm, elementTerm);
_addInequality(debug, solver, elementTerm, firstArgTerm);
return baseTerm;
} else if (r.getMethod().equals(
PtolemyUtilities.arrayTokenWithTypeConstructor)) {
InequalityTerm elementTypeTerm = (InequalityTerm) objectToInequalityTerm
.get(r.getArg(0));
ptolemy.data.type.ArrayType arrayType = new ptolemy.data.type.ArrayType(
ptolemy.data.type.BaseType.UNKNOWN);
VariableTerm newTerm = new VariableTerm(arrayType, r);
_addInequality(debug, solver, baseTerm, newTerm);
_addInequality(debug, solver, newTerm, baseTerm);
InequalityTerm elementTerm = arrayType.getElementTypeTerm();
_addInequality(debug, solver, elementTypeTerm, elementTerm);
_addInequality(debug, solver, elementTerm, elementTypeTerm);
return baseTerm;
} else if (methodName.equals("one")
|| methodName.equals("zero")
|| methodName.equals("bitwiseNot")
|| methodName.equals("pow")
|| methodName.equals("logicalRightShift")
|| methodName.equals("leftShift")
|| methodName.equals("rightShit")) {
// The returned type must be equal to the type
// we are calling the method on.
return baseTerm;
} else if (methodName.equals("add")
|| methodName.equals("addReverse")
|| methodName.equals("subtract")
|| methodName.equals("subtractReverse")
|| methodName.equals("multiply")
|| methodName.equals("multiplyReverse")
|| methodName.equals("divide")
|| methodName.equals("divideReverse")
|| methodName.equals("modulo")
|| methodName.equals("moduloReverse")
|| methodName.equals("bitwiseAnd")
|| methodName.equals("bitwiseOr")
|| methodName.equals("bitwiseXor")) {
// The return value is greater than the base and
// the argument.
// InequalityTerm returnValueTerm = new VariableTerm(
// PtolemyUtilities.getTokenTypeForSootType(
// (RefType)r.getMethod().getReturnType()),
// r.getMethod());
final InequalityTerm firstArgTerm = (InequalityTerm) objectToInequalityTerm
.get(r.getArg(0));
final InequalityTerm finalBaseTerm = baseTerm;
final InstanceInvokeExpr finalExpression = r;
// _addInequality(debug, solver, firstArgTerm,
// returnValueTerm);
// _addInequality(debug, solver, baseTerm,
// returnValueTerm);
InequalityTerm returnValueTerm = new MonotonicFunction() {
public Object getValue() throws IllegalActionException {
if (firstArgTerm.getValue().equals(
TypeLattice.lattice().bottom())
|| finalBaseTerm.getValue().equals(
TypeLattice.lattice().bottom())) {
return TypeLattice.lattice().bottom();
}
return TypeLattice.lattice().leastUpperBound(
firstArgTerm.getValue(),
finalBaseTerm.getValue());
}
public InequalityTerm[] getVariables() {
ArrayList list = new ArrayList();
if (firstArgTerm.isSettable()) {
list.add(firstArgTerm);
}
if (finalBaseTerm.isSettable()) {
list.add(finalBaseTerm);
}
InequalityTerm[] terms = (InequalityTerm[]) list
.toArray(new InequalityTerm[list.size()]);
return terms;
}
public Object getAssociatedObject() {
return finalExpression;
}
};
return returnValueTerm;
} else if (methodName.equals("convert")) {
System.out.println("convert method!");
// The return value type is equal to the base
// type. The first argument type is less than or
// equal to the base type.
InequalityTerm firstArgTerm = (InequalityTerm) objectToInequalityTerm
.get(r.getArg(0));
_addInequality(debug, solver, firstArgTerm, baseTerm);
return baseTerm;
} else if (methodName.equals("getElement")
|| methodName.equals("arrayValue")
|| methodName.equals("getElementType")) {
// If we call getElement or arrayValue on an array
// token, then the returned type is the element
// type of the array.
ptolemy.data.type.ArrayType arrayType = new ptolemy.data.type.ArrayType(
ptolemy.data.type.BaseType.UNKNOWN);
_addInequality(debug, solver, baseTerm, new VariableTerm(
arrayType, r));
InequalityTerm returnTypeTerm = arrayType
.getElementTypeTerm();
return returnTypeTerm;
} else if (methodName.equals("getElementAsToken")) {
final InequalityTerm matrixTerm = baseTerm;
InequalityTerm returnTypeTerm = new MonotonicFunction() {
public Object getValue() throws IllegalActionException {
if (matrixTerm.getValue() instanceof MatrixType) {
MatrixType type = (MatrixType) matrixTerm
.getValue();
return type.getElementType();
} else {
return BaseType.UNKNOWN;
}
}
public InequalityTerm[] getVariables() {
if (matrixTerm.isSettable()) {
InequalityTerm[] terms = new InequalityTerm[1];
terms[0] = matrixTerm;
return terms;
} else {
return new InequalityTerm[0];
}
}
};
return returnTypeTerm;
} else if (methodName.equals("absolute")) {
// Return the same as the input type, unless
// complex, in which case, return double.
final InequalityTerm finalBaseTerm = baseTerm;
final InstanceInvokeExpr finalExpression = r;
InequalityTerm returnValueTerm = new MonotonicFunction() {
public Object getValue() throws IllegalActionException {
if (finalBaseTerm.getValue().equals(
BaseType.COMPLEX)) {
return BaseType.DOUBLE;