if (stmt instanceof InvokeStmt) {
Value expr = ((InvokeStmt) stmt).getInvokeExpr();
if (expr instanceof SpecialInvokeExpr) {
SpecialInvokeExpr r = (SpecialInvokeExpr) expr;
//String methodName = r.getMethod().getName();
Type type = r.getBase().getType();
// System.out.println("baseType = " + type);
// System.out.println("methodName = " + methodName);
if (type instanceof NullType) {
// Note: The control path that causes this to be
// null should never occur in practice.
return;
}
SootClass baseClass = ((RefType) type).getSootClass();
// FIXME: match better.
// If we are invoking a method on a token, then...
if (SootUtilities.derivesFrom(baseClass,
PtolemyUtilities.tokenClass)) {
if (r.getMethod().equals(
PtolemyUtilities.arrayTokenConstructor)) {
// The arrayToken constructor depends on the type
// of its constructor argument.
// System.out.println("found array invoke: " + r);
// System.out.println("Argument type is : " + in.get(r.getArg(0)));
ptolemy.data.type.Type argType = (ptolemy.data.type.Type) in
.get(r.getArg(0));
if (argType == null) {
argType = BaseType.UNKNOWN;
}
out.put(r.getBase(), new ArrayType(argType));
} else if (r.getMethod().equals(
PtolemyUtilities.arrayTokenWithTypeConstructor)) {
// The arrayToken constructor depends on the type
// of its constructor argument.
// System.out.println("found array invoke: " + r);
// System.out.println("Argument type is : " + in.get(r.getArg(0)));
ptolemy.data.type.Type argType = (ptolemy.data.type.Type) in
.get(r.getArg(0));
if (argType == null) {
argType = BaseType.UNKNOWN;
}
out.put(r.getBase(), new ArrayType(argType));
}
}
}
} else if (stmt instanceof AssignStmt) {
Value leftOp = ((AssignStmt) stmt).getLeftOp();
if (!_isTokenType(leftOp.getType())) {
// System.out.println("type " + leftOp.getType()
// + " is not a token");
return;
}
// System.out.println("from " + in);
Value rightOp = ((AssignStmt) stmt).getRightOp();
if (rightOp instanceof StaticInvokeExpr) {
StaticInvokeExpr r = (StaticInvokeExpr) rightOp;
if (r.getMethod().equals(PtolemyUtilities.arraycopyMethod)) {
out.put(r.getArg(0), in.get(r.getArg(2)));
}
} else if (rightOp instanceof InstanceInvokeExpr
|| rightOp instanceof InterfaceInvokeExpr) {
InstanceInvokeExpr r = (InstanceInvokeExpr) rightOp;
String methodName = r.getMethod().getName();
Type type = r.getBase().getType();
// System.out.println("baseType = " + type);
// System.out.println("methodName = " + methodName);
if (type instanceof NullType) {
// Note: The control path that causes this to be
// null should never occur in practice.
return;
}
SootClass baseClass = ((RefType) type).getSootClass();
// FIXME: match better.
// If we are invoking a method on a token, then...
if (SootUtilities.derivesFrom(baseClass,
PtolemyUtilities.tokenClass)) {
if (methodName.equals("one") || methodName.equals("zero")
|| methodName.equals("not")
|| methodName.equals("bitwiseNot")
|| methodName.equals("leftShift")
|| methodName.equals("rightShift")
|| methodName.equals("logicalRightShift")
|| methodName.equals("pow")) {
// The returned type must be equal to the type
// we are calling the method on.
_updateTypeInAssignment(leftOp, in.get(r.getBase()),
out);
} 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")) {
// System.out.println("methodName = " + methodName);
// System.out.println("r.getBase() = " + r.getBase());
// System.out.println("r.getArg(0) = " + r.getArg(0));
// System.out.println("type(r.getBase()) = " + in.get(r.getBase()));
// System.out.println("type(r.getArg(0)) = " + in.get(r.getArg(0)));
ptolemy.data.type.Type baseType = (ptolemy.data.type.Type) in
.get(r.getBase());
ptolemy.data.type.Type argType = (ptolemy.data.type.Type) in
.get(r.getArg(0));
if ((baseType == null) || (argType == null)) {
out.put(leftOp, null);
} else {
_updateTypeInAssignment(leftOp, TypeLattice
.lattice().leastUpperBound(baseType,
argType), out);
}
} else if (methodName.equals("convert")) {
// The return rightOp type is equal to the base type.
// The first argument type is less than or equal to the base type.
_updateTypeInAssignment(leftOp, in.get(r.getBase()),
out);
} else if (methodName.equals("getElement")
|| methodName.equals("arrayValue")) {
ptolemy.data.type.Type arrayType = (ptolemy.data.type.Type) in
.get(r.getBase());
if ((arrayType != null)
&& arrayType instanceof ArrayType) {
_updateTypeInAssignment(leftOp,
((ArrayType) arrayType).getElementType(),
out);
}
} else if (methodName.equals("getElementAsToken")) {
ptolemy.data.type.Type matrixType = (ptolemy.data.type.Type) in
.get(r.getBase());
if ((matrixType != null)
&& matrixType instanceof MatrixType) {
_updateTypeInAssignment(leftOp,
((MatrixType) matrixType).getElementType(),
out);
}
} else if (methodName.equals("absolute")) {
// Return the same as the input type, unless complex,
// in which case, return double.
ptolemy.data.type.Type inType = (ptolemy.data.type.Type) in
.get(r.getBase());
if (inType.equals(BaseType.COMPLEX)) {
_updateTypeInAssignment(leftOp, BaseType.DOUBLE,
out);
} else {
_updateTypeInAssignment(leftOp, inType, out);
}
}
} else if (SootUtilities.derivesFrom(baseClass,
PtolemyUtilities.componentPortClass)) {
// If we are invoking a method on a port.
TypedIOPort port = (TypedIOPort) _namedObjAnalysis
.getObject((Local) r.getBase());
//System.out.println("port for " + r.getBase() + " = " + port);
if (methodName.equals("broadcast")) {
// The type of the argument must be less than the
// type of the port.
} else if (methodName.equals("get")) {
// The port here may be null if the model does not
// actually contain the port... This happens, for
// instance, in MathFunction
if (port != null) {
_updateTypeInAssignment(leftOp, port.getType(), out);
}
} else if (methodName.equals("send")) {
if (r.getArgCount() == 3) {
// The type of the argument must be less than the
// type of the port.
//r.getArg(1));
} else if (r.getArgCount() == 2) {
// The type of the argument must be less than the
// type of the port.
// r.getArg(1));
}
}
} else if (SootUtilities.derivesFrom(baseClass,
PtolemyUtilities.attributeClass)) {
// If we are invoking a method on a parameter.
Attribute attribute = (Attribute) _namedObjAnalysis
.getObject((Local) r.getBase());
if (attribute == null) {
// A method invocation with a null base is bogus,
// so don't create a type constraint.
}