// Essentially this method builds an application
// of the function to the supplied arguments using our
// source model.
// Build up the argument names and types.
TypeExpr te = functionalAgent.getTypeExpr();
int nArgs = te.getArity();
int nNamedArgs = functionalAgent.getNArgumentNames();
String paramNames[] = CALDocToJavaDocUtilities.getArgumentNamesFromCALDocComment(cdc, functionalAgent);
if (paramNames.length != nArgs) {
throw new NullPointerException ("Mismatch between arity and number of arguments for " + calFuncName);
}
String origParamNames[] = new String[paramNames.length];
System.arraycopy(paramNames, 0, origParamNames, 0, origParamNames.length);
JavaTypeName paramTypes[] = new JavaTypeName [paramNames.length];
// If we have named arguments we should use those names.
Set<String> paramNamesSet = new HashSet<String>();
for (int i = 0; i < paramNames.length; ++i) {
String name = paramNames[i];
if (name == null) {
if (i < nNamedArgs) {
name = functionalAgent.getArgumentName(i);
}
if (name == null || name.equals("")) {
name = null;
// There is no name for this argument in the functional entity. This
// usually occurs with foreign functions and class methods because
// you don't have to explicitly name the arguments.
// Check to see if there was a CALDoc comment that named the arguments.
if (cdc != null && cdc.getNArgBlocks() == paramNames.length) {
name = cdc.getNthArgBlock(i).getArgName().getCalSourceForm();
}
// If we still don't have an argument name just build one.
if (name == null) {
name = "arg_" + (i+1);
}
}
// Make sure name is unique.
String baseName = name;
int suffix = 0;
while (paramNamesSet.contains(name)) {
name = baseName + "_" + suffix++;
}
}
origParamNames[i] = name;
paramNames[i] = fixupVarName(name);
paramTypes[i] = SOURCE_MODEL_EXPR_TYPE_NAME;
}
// Get the JavaDoc for the helper function. If there is CALDoc
// for the function we translate it to JavaDoc.
JavaDocComment funcComment;
if (cdc != null) {
funcComment = new JavaDocComment(calDocCommentToJavaComment(cdc, functionalAgent, false));
funcComment = fixupJavaDoc(funcComment, origParamNames, paramNames);
} else {
funcComment = new JavaDocComment("Helper binding method for function: " + calFuncName + ". ");
for (int iName = 0; iName < paramNames.length; ++iName) {
funcComment.addLine("@param " + paramNames[iName]);
}
funcComment.addLine("@return the SourceModule.expr representing an application of " + calFuncName);
}
// Create the method.
JavaMethod bindingMethod =
new JavaMethod(PUBLIC_STATIC_FINAL,
SOURCE_MODEL_EXPR_TYPE_NAME,
paramNames,
paramTypes,
null, javaFuncName);
functionsClass.addMethod(bindingMethod);
// Add the JavaDoc
bindingMethod.setJavaDocComment(funcComment);
// Build up the body of the method.
// We want to us the QualifiedName field.
JavaField nameField = new JavaField.Static(functionsClassTypeName, javaFuncName, QUALIFIED_NAME_TYPE_NAME);
// Create an instance of SourceModel.Expr.Var for the CAL function.
JavaExpression sourceModelVarCreation =
new MethodInvocation.Static(
SOURCE_MODEL_EXPR_VAR_TYPE_NAME,
"make",
nameField,
QUALIFIED_NAME_TYPE_NAME,
SOURCE_MODEL_EXPR_VAR_TYPE_NAME);
// For the comment for this method we want an @see referring to the previous method.
String atSee = "@see #" + javaFuncName + "(";
for (int iArg = 0; iArg < paramNames.length; ++iArg) {
if (iArg == 0) {
atSee = atSee + paramTypes[iArg].getFullJavaSourceName();
} else {
atSee = atSee + ", " + paramTypes[iArg].getFullJavaSourceName();
}
}
atSee = atSee + ")";
if (paramNames.length == 0) {
// Simply return the Expr.Var
bindingMethod.addStatement(new ReturnStatement(sourceModelVarCreation));
} else {
// Need to create an application.
// Create an array of SourceModel.Expr. The first element is the SourceModel.Expr.Var
// for the CAL function the remaining elements are the function arguments.
JavaExpression arrayElements[] = new JavaExpression[paramNames.length + 1];
arrayElements[0] = sourceModelVarCreation;
for (int i = 1; i <= paramNames.length; ++i) {
arrayElements[i] = new JavaExpression.MethodVariable(paramNames[i-1]);
}
// Build the array creation expression.
JavaExpression arrayCreation =
new JavaExpression.ArrayCreationExpression(SOURCE_MODEL_EXPR_TYPE_NAME, arrayElements);
// Invoke SourceModel.Expr.Application.make()
MethodInvocation makeApply =
new MethodInvocation.Static(
SOURCE_MODEL_EXPR_APPLICATION_TYPE_NAME,
"make",
arrayCreation,
JavaTypeName.makeArrayType(SOURCE_MODEL_EXPR_TYPE_NAME),
SOURCE_MODEL_EXPR_APPLICATION_TYPE_NAME);
bindingMethod.addStatement(new ReturnStatement (makeApply));
// If any of the argument types correspond to a Java type.
// (eg. Prelude.Int, Prelude.Long, etc. we can generate a version
// of the binding function that takes these argument types.
boolean primArgs = false;
TypeExpr[] pieces = te.getTypePieces();
for (int i = 0; i < paramNames.length; ++i) {
if (canTypeBeUnboxed(pieces[i])) {
primArgs = true;
// Change the param type.
paramTypes[i] = typeExprToTypeName(pieces[i]);