e.asLiteral().getLiteral() instanceof String ||
e.asLiteral().getLiteral() instanceof BigInteger) {
KernelLiteral kernelLit = getKernelLiteral (e.asLiteral().getLiteral());
return new ExpressionContextPair(kernelLit.getUnboxedReference());
} else {
throw new CodeGenerationException ("Unboxed type mismatch in " + getModuleName() + "." + getFunctionName() + " : expression type = " + e.asLiteral().getLiteral().getClass().getName() + ", desiredType = " + unboxType);
}
}
// If the expression is a primitive op compile it as an unboxed op.
//we don't directly call primitive operators if doing function tracing.
//This will have the effect of ensuring that they get traced when called.
BasicOpTuple bot;
if (LECCMachineConfiguration.generateDirectPrimOpCalls() &&
(bot = BasicOpTuple.isBasicOp(e)) != null) {
// Generally speaking if an argument to a foreign function is expressed as a primitive op/foreign function we can
// assume that the unboxed return value of the argument expression is of the correct type to pass.
// One exception is when dealing with an argument expression of type Prelude.CalValue. In this case we need to
// get the Prelude.CalValue, evaluate, and then unbox the actual type needed by the foreign function.
// Another is when dealing with Prelude.eager
// Finally we need to be sure that the primitiveness of the operation/foreign function and the
// desired unbox type match. For example an operation that produces an int can either unbox to
// an int or an Object.
if (bot.getPrimitiveOp() == PrimOps.PRIMOP_FOREIGN_FUNCTION) {
// If this foreign SC is of type internal value we can't just get the unboxed value and pass
final ForeignFunctionInfo ffi = bot.getForeignFunctionInfo();
final Class<?> foreignReturnType = SCJavaDefn.getJavaReturnType(ffi);
// If this foreign SC is of type Prelude.CalValue we can't just get the unboxed value and pass
final boolean hasCalValueReturnType = isCalValueClass(foreignReturnType);
if (hasCalValueReturnType){
ExpressionContextPair argResult = genS_E (e, variableContext);
return new ExpressionContextPair(unboxValue(unboxType, SCJavaDefn.createInvocation (argResult.getJavaExpression(), SCJavaDefn.EVALUATE, SCJavaDefn.EXECUTION_CONTEXT_VAR)), argResult.getContextBlock());
}
verifyUnboxType(unboxType, JavaTypeName.make(foreignReturnType));
return generatePrimitiveOp (e, false, Scheme.E_SCHEME, variableContext);
} else
if (bot.getPrimitiveOp() == PrimOps.PRIMOP_EAGER) {
throw new CodeGenerationException ("PRIMOP_EAGER encountered in generateUnboxedForeignFunctionArgument.");
} else
if (bot.getPrimitiveOp() != PrimOps.PRIMOP_OBJECT_TO_CAL_VALUE &&
bot.getPrimitiveOp() != PrimOps.PRIMOP_CAL_VALUE_TO_OBJECT) {
verifyUnboxType(unboxType, PrimOp.getTypeNameForPrimOp(bot.getPrimitiveOp()));
return generatePrimitiveOp(e, false, Scheme.E_SCHEME, variableContext);
}
}
if (isNot(e)) {
verifyUnboxType(unboxType, JavaTypeName.BOOLEAN);
return generateNot (e, false, variableContext);
}
if (BasicOpTuple.isAndOr(e) != null) {
verifyUnboxType(unboxType, JavaTypeName.BOOLEAN);
return generateAndOr(e, false, variableContext);
}
if (e.asVar() != null) {
Expression.Var var = e.asVar();
if (variableContext.isLocalVariable(var.getName())) {
final JavaTypeName unboxedTypeOfVar = variableContext.getUnboxedType(var.getName());
if (unboxedTypeOfVar != null) {
verifyUnboxType(unboxType, unboxedTypeOfVar);
}
// At this point we know that the desired unboxType is compatible with the
// unboxed type of the variable (since we called verifyUnboxtype).
// If the desired unbox type is not null and is equal to the variables unboxed type
// we can simply use the unboxed reference.
// If the desired unbox type is Object we can simply use the variables unboxed reference
// since we know the variable can't be primitive (because we called verifyUnboxType) and
// all non-primitives in Java are an instance of Object.
if(unboxType.equals(unboxedTypeOfVar) ||
unboxType.equals(JavaTypeName.OBJECT)) {
JavaExpression unboxedRef = variableContext.getUnboxedReference(var.getName());
if (unboxedRef != null) {
return new ExpressionContextPair (unboxedRef);
}
} else {
if (unboxedTypeOfVar != null) {
// If the variable has an unboxed type, then in fact it should be the same as the desired unboxed type
// or should be java.lang.Object
throw new CodeGenerationException("The code generator should not be generating code where the desired unboxed type is not java.lang.Object nor the unboxed type of the variable.");
}
}
}
}