if (childTypes[i] == null) {
throw new RuntimeException("node " + node + " has null type.");
}
}
Type baseType = null;
if ((_scope != null) && (functionName != null)) {
baseType = _scope.getType(functionName);
}
if ((baseType != null) || (functionName == null)) {
baseType = _inferChild(node, 0);
// Handle as an array or matrix index into a named
// variable reference.
if (baseType instanceof FunctionType) {
_setType(node, ((FunctionType) baseType).getReturnType());
return;
} else if (argCount == 1) {
if (baseType instanceof ArrayType) {
_setType(node, ((ArrayType) baseType).getElementType());
return;
} else {
_assert(true, node, "Cannot use array " + "indexing on '"
+ node.getFunctionName()
+ "' because it does not have an array type.");
}
} else if (argCount == 2) {
if (baseType instanceof MatrixType) {
_setType(node, ((MatrixType) baseType).getElementType());
return;
} else {
_assert(true, node, "Cannot use matrix " + "indexing on '"
+ node.getFunctionName()
+ "' because it does not have a matrix type.");
}
}
throw new IllegalActionException("Wrong number of indices "
+ "when referencing " + functionName);
}
// Psuedo-temporary hack for casts....
if ((functionName.compareTo("cast") == 0) && (argCount == 2)) {
ASTPtRootNode castTypeNode = ((ASTPtRootNode) node
.jjtGetChild(0 + 1));
ParseTreeEvaluator parseTreeEvaluator = new ParseTreeEvaluator();
try {
ptolemy.data.Token t = parseTreeEvaluator.evaluateParseTree(
castTypeNode, _scope);
_setType(node, t.getType());
} catch (IllegalActionException ex) {
_setType(node, childTypes[0]);
}
return;
// Note: We used to just do this, but in some case is it
// useful to have functions which are type constructors...
// Hence the above code.
// _setType(node,
// ((ASTPtRootNode) node.jjtGetChild(0 + 1)).getType());
// return;
}
// A hack, because the result of the 'fix' function is
// dependent on its arguments, which should be constant.
if ((functionName.compareTo("fix") == 0) && (argCount == 3)) {
ASTPtRootNode lengthNode = ((ASTPtRootNode) node.jjtGetChild(1 + 1));
ASTPtRootNode integerBitsNode = ((ASTPtRootNode) node
.jjtGetChild(2 + 1));
ParseTreeEvaluator parseTreeEvaluator = new ParseTreeEvaluator();
try {
ptolemy.data.Token length = parseTreeEvaluator
.evaluateParseTree(lengthNode, _scope);
ptolemy.data.Token integerBits = parseTreeEvaluator
.evaluateParseTree(integerBitsNode, _scope);
_setType(node, new FixType(new Precision(((ScalarToken) length)
.intValue(), ((ScalarToken) integerBits).intValue())));
return;
} catch (Throwable throwable) {
// Do nothing... rely on the regular method resolution
// to generate the right type.
}
}
if (functionName.compareTo("eval") == 0) {
// We can't infer the type of eval expressions...
_setType(node, BaseType.GENERAL);
return;
}
if (functionName.compareTo("matlab") == 0) {
// We can't infer the type of matlab expressions...
_setType(node, BaseType.GENERAL);
return;
}
// Otherwise, try to reflect the method name.
CachedMethod cachedMethod;
try {
cachedMethod = CachedMethod.findMethod(functionName, childTypes,
CachedMethod.FUNCTION);
} catch (Exception ex) {
// Deal with what happens if the method is not found.
// FIXME: hopefully this is monotonic???
_setType(node, BaseType.UNKNOWN);
return;
}
if (cachedMethod.isValid()) {
Type type = cachedMethod.getReturnType();
_setType(node, type);
} else {
// If we reach this point it means the function was not found on
// the search path.
StringBuffer buffer = new StringBuffer();