args[i] = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());
argTypeNames[i] = argTypeName;
}
returnExpression = new ClassInstanceCreationExpression(JavaTypeName.make(clazz), args, argTypeNames);
if (boxResult) {
ExpressionContextPair pair = returnTypeToCal(constructor.getDeclaringClass(), returnExpression);
returnExpression = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());
}
return new ExpressionContextPair(returnExpression, returnContext);
} else if (kind.isCast()) {
final Class<?> argType = SCJavaDefn.getJavaArgumentType(foreignFunctionInfo, 0);
final Class<?> resultType = SCJavaDefn.getJavaReturnType(foreignFunctionInfo);
final ExpressionContextPair argExprPair = generateUnboxedForeignFunctionArgument(JavaTypeName.make(argType), basicOpExpressions.getArgument(0), variableContext);
final JavaExpression argExpr = argExprPair.getJavaExpression();
returnContext.addStatement(argExprPair.getContextBlock());
if (kind == ForeignFunctionInfo.JavaKind.IDENTITY_CAST ||
kind == ForeignFunctionInfo.JavaKind.WIDENING_REFERENCE_CAST) {
//it is important to do nothing for a widening reference cast (except for evaluating)
//this is because at the JavaTypeName level, where the inheritance hierarchy is not available, it is not possible for
//the bytecode generator to determine if this is truly a widening reference cast i.e. a no-op. Hence we must make
//this optimization at this point.
returnExpression = argExpr;
} else if (kind == ForeignFunctionInfo.JavaKind.NARROWING_PRIMITIVE_CAST ||
kind == ForeignFunctionInfo.JavaKind.WIDENING_PRIMITIVE_CAST ||
kind == ForeignFunctionInfo.JavaKind.NARROWING_REFERENCE_CAST) {
returnExpression = new JavaExpression.CastExpression(JavaTypeName.make(resultType), argExpr);
} else {
throw new CodeGenerationException("Unrecognized foreign function cast kind: " + kind);
}
if (boxResult) {
ExpressionContextPair pair = returnTypeToCal(resultType, returnExpression);
returnExpression = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());
}
return new ExpressionContextPair(returnExpression, returnContext);
} else if (kind.isInstanceOf()) {
final Class<?> argType = SCJavaDefn.getJavaArgumentType(foreignFunctionInfo, 0);
final ForeignFunctionInfo.InstanceOf instanceOfInfo = (ForeignFunctionInfo.InstanceOf)foreignFunctionInfo;
final Class<?> instanceOfType = SCJavaDefn.getInstanceOfType(instanceOfInfo);
final ExpressionContextPair argExprPair = generateUnboxedForeignFunctionArgument(JavaTypeName.make(argType), basicOpExpressions.getArgument(0), variableContext);
final JavaExpression argExpr = argExprPair.getJavaExpression();
returnContext.addStatement(argExprPair.getContextBlock());
returnExpression = new JavaExpression.InstanceOf(argExpr, JavaTypeName.make(instanceOfType));
if (boxResult) {
ExpressionContextPair pair = returnTypeToCal(boolean.class, returnExpression);
returnExpression = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());
}
return new ExpressionContextPair(returnExpression, returnContext);
} else if (kind.isClassLiteral()) {
final ForeignFunctionInfo.ClassLiteral classLiteralInfo = (ForeignFunctionInfo.ClassLiteral)foreignFunctionInfo;
final Class<?> referentType = SCJavaDefn.getReferentType(classLiteralInfo);
returnExpression = new JavaExpression.ClassLiteral(JavaTypeName.make(referentType));
if (boxResult) {
ExpressionContextPair pair = returnTypeToCal(Class.class, returnExpression);
returnExpression = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());
}
return new ExpressionContextPair(returnExpression, returnContext);
} else if (kind.isNullLiteral()) {
returnExpression = JavaExpression.LiteralWrapper.NULL;
if (boxResult) {
final ExpressionContextPair pair = returnTypeToCal(SCJavaDefn.getJavaReturnType(foreignFunctionInfo), returnExpression);
returnExpression = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());
}
return new ExpressionContextPair(returnExpression, returnContext);
} else if (kind.isNullCheck()) {
final ForeignFunctionInfo.NullCheck nullCheckInfo = (ForeignFunctionInfo.NullCheck)foreignFunctionInfo;
final Class<?> argType = SCJavaDefn.getJavaArgumentType(foreignFunctionInfo, 0);
final ExpressionContextPair argExprPair = generateUnboxedForeignFunctionArgument(JavaTypeName.make(argType), basicOpExpressions.getArgument(0), variableContext);
final JavaExpression argExpr = argExprPair.getJavaExpression();
returnContext.addStatement(argExprPair.getContextBlock());
final JavaOperator javaOp = nullCheckInfo.checkIsNull() ? JavaOperator.EQUALS_OBJECT : JavaOperator.NOT_EQUALS_OBJECT;
returnExpression = new JavaExpression.OperatorExpression.Binary(javaOp, argExpr, LiteralWrapper.NULL);
if (boxResult) {
final ExpressionContextPair pair = returnTypeToCal(boolean.class, returnExpression);
returnExpression = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());
}
return new ExpressionContextPair(returnExpression, returnContext);
} else if (kind == ForeignFunctionInfo.JavaKind.NEW_ARRAY) {
//e.g. newString3Array :: Int -> Int -> JString3Array; (for new String[d1][d2][])
//note, this may be less than the dimension of the array e.g. for new String[10][7][] this is 2.
final int nJavaArgs = SCJavaDefn.getNArguments(foreignFunctionInfo);
final Class<?> newArrayType = SCJavaDefn.getJavaReturnType(foreignFunctionInfo);
final JavaExpression[] args = new JavaExpression[nJavaArgs];
final JavaTypeName[] argTypeNames = new JavaTypeName[nJavaArgs];
for (int i = 0; i < nJavaArgs; i++) {
final ExpressionContextPair pair = generateUnboxedForeignFunctionArgument(JavaTypeName.INT, basicOpExpressions.getArgument(i), variableContext);
args[i] = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());
argTypeNames[i] = JavaTypeName.INT;
}
returnExpression = new ClassInstanceCreationExpression(JavaTypeName.make(newArrayType), args, argTypeNames);
if (boxResult) {
final ExpressionContextPair pair = returnTypeToCal(newArrayType, returnExpression);
returnExpression = pair.getJavaExpression();
returnContext.addStatement(pair.getContextBlock());