// Import the top level class as a foreign type.
// ex. data foreign unsafe import jvm "org.olap.CubeType" public JCubeType;
makeForeignClassDeclaration(topLevelDefnsList);
for (int i = 0, n = typeConstructor.getNDataConstructors(); i < n; ++i) {
DataConstructor dc = typeConstructor.getNthDataConstructor(i);
makeForeignClassDeclaration(dc, topLevelDefnsList);
}
TypeExprDefn.TypeCons jClassTypeExpr =
TypeExprDefn.TypeCons.make(Name.TypeCons.makeUnqualified(typeConstructorInfo.calForeignTypeName));
// Import the constructors for each inner class (i.e. each data constructor)
// Pull in the constructor for the Java class.
for (int i = 0, n = javaClass.getNInnerClasses(); i < n; ++i) {
JavaClassRep innerClass = javaClass.getInnerClass(i);
assert (innerClass.getNConstructors() == 1);
JavaConstructor constructor = innerClass.getConstructor(0);
topLevelDefnsList.add(importJavaConstructor(constructor, true));
}
// Create accessors for fields in the top level class.
for (FieldName fn : typeConstructorInfo.commonFieldNames) {
Set<JavaTypeName> fieldTypes = typeConstructorInfo.allFieldTypeNames.get(fn);
// There will only be one type for common fields.
Iterator<JavaTypeName> types = fieldTypes.iterator();
JavaTypeName fieldType = types.next();
String foreignFieldTypeSting = typeConstructorInfo.calFieldForeignTypes.get(fn).get(fieldType);
generateFieldAccessor (
typeConstructorInfo.calForeignTypeName,
fn,
fieldType,
foreignFieldTypeSting,
typeConstructor.getNthDataConstructor(0),
topLevelDefnsList);
}
// Create accessors for the fields in the inner classes.
for (int i = 0, n = typeConstructor.getNDataConstructors(); i < n; ++i) {
DataConstructor dc = typeConstructor.getNthDataConstructor(i);
DataConstructorInfo dcInfo = (DataConstructorInfo)typeConstructorInfo.dataConstructorInfo.get(dc);
for (FieldName fn : dcInfo.allFieldNames) {
if (typeConstructorInfo.commonFieldNames.contains(fn)) {
continue;
}
JavaTypeName fieldType = (JavaTypeName)dcInfo.fieldTypeNames.get(fn);
String foreignFieldTypeSting = typeConstructorInfo.calFieldForeignTypes.get(fn).get(fieldType);
generateFieldAccessor (
dcInfo.calForeignTypeName,
fn,
fieldType,
foreignFieldTypeSting,
dc,
topLevelDefnsList);
}
}
// Bring in the 'getDCOrdinal()' method of the Java class.
String getDCOrdinalName = "j" + javaClass.getClassName().getUnqualifiedJavaSourceName() + "_getDCOrdinal";
SourceModel.TypeSignature getDCOrdinalTypeSignature =
TypeSignature.make(
TypeExprDefn.Function.make(
jClassTypeExpr,
INT_TYPE_EXPR_DEFN));
SourceModel.CALDoc.Comment.Function getDCOrdinalComment;
{
SourceModel.CALDoc.TextSegment.Plain textSegment =
SourceModel.CALDoc.TextSegment.Plain.make(
"\nRetrieve the ordinal value from an instance of " + typeConstructorInfo.calForeignTypeName + ".\n" +
"The ordinal can be used to determine which data constructor the " + typeConstructorInfo.calForeignTypeName + "\n" +
"instance corresponds to.");
SourceModel.CALDoc.TextBlock textBlock =
SourceModel.CALDoc.TextBlock.make(new SourceModel.CALDoc.TextSegment.TopLevel[]{textSegment});
getDCOrdinalComment =
SourceModel.CALDoc.Comment.Function.make(
textBlock,
null);
}
SourceModel.FunctionDefn getDCOrdinal =
FunctionDefn.Foreign.make(
getDCOrdinalComment,
getDCOrdinalName,
Scope.PRIVATE,
true,
"method getDCOrdinal",
getDCOrdinalTypeSignature);
topLevelDefnsList.add(getDCOrdinal);
// Create input function.
// inputCube :: JCube -> Cube;
// inputCube jCube =
// case (jCube_getDCOrdinal JCube) of
// 0 -> ...;
// 1 -> ...;
String inputFunctionName =
"input" + typeConstructor.getName().getUnqualifiedName();
String inputFunctionArgName = "j" + typeConstructorInfo.calForeignTypeName.substring(1);
Expr.Var inputFunctionArg = Expr.Var.make(Name.Function.makeUnqualified(inputFunctionArgName));
// Do the function type declaration.
// JCube -> Cube
TypeExprDefn inputFunctionType =
TypeExprDefn.Function.make(
TypeExprDefn.TypeCons.make(Name.TypeCons.makeUnqualified(typeConstructorInfo.calForeignTypeName)),
TypeExprDefn.TypeCons.make(Name.TypeCons.makeUnqualified(typeConstructorName.getUnqualifiedName())));
SourceModel.CALDoc.Comment.Function inputFunctionComment;
{
SourceModel.CALDoc.TextSegment.Plain textSegment =
SourceModel.CALDoc.TextSegment.Plain.make(
"\nInput an instance of " + typeConstructor.getName().getUnqualifiedName() + ".\n" +
"Translates an instance of " + typeConstructorInfo.calForeignTypeName + " to\n" +
"an instance of "+ typeConstructor.getName().getUnqualifiedName() + ".");
SourceModel.CALDoc.TextBlock textBlock =
SourceModel.CALDoc.TextBlock.make(new SourceModel.CALDoc.TextSegment.TopLevel[]{textSegment});
inputFunctionComment =
SourceModel.CALDoc.Comment.Function.make(
textBlock,
null);
}
SourceModel.FunctionTypeDeclaration inputFunctionTypeDecl =
FunctionTypeDeclaration.make(
inputFunctionComment,
inputFunctionName,
TypeSignature.make(inputFunctionType));
topLevelDefnsList.add(inputFunctionTypeDecl);
// build up the function body
SourceModel.Expr condition =
Expr.Application.make(
new Expr[]{Expr.Var.make(Name.Function.makeUnqualified(getDCOrdinalName)),
inputFunctionArg});
SourceModel.Expr.Case.Alt caseAlts[] =
new SourceModel.Expr.Case.Alt[typeConstructor.getNDataConstructors()];
for (int i = 0, n = caseAlts.length; i < n; ++i) {
DataConstructor dc = typeConstructor.getNthDataConstructor(i);
// Build up an application of the data constructor.
SourceModel.Expr dcApplication =
makeDCCall(dc, inputFunctionArg);
caseAlts[i] =
Expr.Case.Alt.UnpackInt.make(
new BigInteger[]{BigInteger.valueOf(dc.getOrdinal())},
dcApplication);
}
SourceModel.Expr body =
Expr.Case.make(condition, caseAlts);
SourceModel.FunctionDefn.Algebraic inputFunction =
FunctionDefn.Algebraic.make(
inputFunctionName,
Scope.PUBLIC,
new SourceModel.Parameter[]{Parameter.make(inputFunctionArgName, false)},
body);
topLevelDefnsList.add(inputFunction);
// Create an inputCubeFromJObject function.
String inputFromJObjectFunctionName = inputFunctionName + "FromJObject";
createInputFromJObjectFunction(inputFromJObjectFunctionName, inputFunctionName, topLevelDefnsList);
// Create Inputable instance.
SourceModel.InstanceDefn instanceDefn =
InstanceDefn.make(
Name.TypeClass.make(CAL_Prelude.TypeClasses.Inputable),
InstanceDefn.InstanceTypeCons.TypeCons.make(Name.TypeCons.make(typeConstructorName), null),
null,
new InstanceDefn.InstanceMethod[]{
InstanceDefn.InstanceMethod.make(CAL_Prelude.Functions.input.getUnqualifiedName(), Name.Function.makeUnqualified(inputFromJObjectFunctionName))
});
topLevelDefnsList.add(instanceDefn);
// Now we want to make the outputable instance.
// Build up a function body that converts
// from 'Cube' to 'JCube'.
Expr.Var dcInstance = Expr.Var.makeUnqualified("dcInstance");
caseAlts =
new SourceModel.Expr.Case.Alt[typeConstructor.getNDataConstructors()];
for (int i = 0, n = caseAlts.length; i < n; ++i) {
DataConstructor dc = typeConstructor.getNthDataConstructor(i);
SourceModel.Pattern patterns[] = new SourceModel.Pattern[dc.getArity()];
Arrays.fill(patterns, SourceModel.Pattern.Wildcard.make());
caseAlts[i] =
Expr.Case.Alt.UnpackDataCons.make(
Name.DataCons.make(dc.getName()),
patterns,
makeConstructorCall(dc, dcInstance, true));
}
SourceModel.Expr.Case conversionFunctionBody =