}
// R is a variable?
if (e.asVar() != null) {
Expression.Var var = e.asVar();
JavaExpression varExpression = expressionVarToJavaDef(var, Scheme.R_SCHEME, variableContext);
// If the variable is already evaluated we want to call getValue(), which will follow any
// indirection chains and return the final value. However, if we are simply returning
// a strict unboxed function argument this isn't necessary.
if (variableContext.isLocalVariable(var.getName()) &&
variableContext.isVarPreEvaluated(var.getName()) &&
(!variableContext.isFunctionArgument(var.getName()) || !isArgUnboxable(var.getName()))) {
// Variable is already evaluated so simply do a 'getValue()' on it.
varExpression = new MethodInvocation.Instance(varExpression, "getValue", JavaTypeNames.RTVALUE, MethodInvocation.InvocationType.VIRTUAL);
}
return generateReturn(varExpression, variableContext);
}
// Is e a conditional op (if <cond expr> <then expr> <else expr>)?
// Since this is the top level compilation scheme we can generate an actual 'if' statement.
CondTuple conditionExpressions = CondTuple.isCondOp(e);
if (conditionExpressions != null) {
if (codeGenerationStats != null) {
codeGenerationStats.incrementOptimizedIfThenElse();
}
// This is a conditional op. The conditionExpressions tuple holds (kCond, kThen, kElse) expressions
// Generate the code for kThen and kElse, as arguments to a new I_Cond instruction
Expression condExpression = conditionExpressions.getConditionExpression();
ExpressionContextPair pair = generateUnboxedArgument(JavaTypeName.BOOLEAN, condExpression, variableContext);
// Then
variableContext.pushJavaScope();
JavaStatement thenPart = genS_R (conditionExpressions.getThenExpression(), variableContext);
Block thenBlock = variableContext.popJavaScope();
thenBlock.addStatement(thenPart);
// Else
variableContext.pushJavaScope();
JavaStatement elsePart = genS_R (conditionExpressions.getElseExpression(), variableContext);
Block elseBlock = variableContext.popJavaScope();
elseBlock.addStatement(elsePart);
JavaExpression conditionExpression = pair.getJavaExpression();
JavaStatement ite = new IfThenElseStatement(conditionExpression, thenBlock, elseBlock);
Block contextBlock = pair.getContextBlock();
contextBlock.addStatement(ite);
// We don't need to call generateReturn() at this point. Any return statements
// will have been generated in the sub-parts of the if-then-else.
return contextBlock;
}
// Expression is a case/switch?
Expression.Switch eswitch = e.asSwitch();
if (eswitch != null) {
// We don't need to call generateReturn() at this point. Any return statements
// will have been generated in the sub-parts of the switch.
return generateSwitch (eswitch, variableContext);
}
// Expression is a data constructor field selection?
Expression.DataConsSelection eDCSelection = e.asDataConsSelection();
if (eDCSelection != null) {
return generateReturn(generateDCFieldSelection(eDCSelection, Scheme.R_SCHEME, variableContext), variableContext);
}
// e is a let var.
if (e.asLetNonRec() != null) {
return generateReturn (generateLetNonRec(e.asLetNonRec(), Scheme.R_SCHEME, null, variableContext), variableContext);
}
if (e.asLetRec() != null) {
return generateReturn(generateLetRec(e.asLetRec(), Scheme.R_SCHEME, variableContext), variableContext);
}
// e is an application?
Expression.Appl appl = e.asAppl();
if (appl != null) {
JavaStatement topLevelSeq = buildTopLevelSeq (appl, false, variableContext);
if (topLevelSeq != null) {
return topLevelSeq;
}
ExpressionContextPair ecp = buildApplicationChain (appl, Scheme.R_SCHEME, variableContext);
if (ecp != null) {
return generateReturn(ecp, variableContext);
} else {
// This is a general application
ExpressionContextPair target;
if (appl.getE1().asDataConsSelection() != null) {
target = generateDCFieldSelection(appl.getE1().asDataConsSelection(), Scheme.E_SCHEME, variableContext);
} else {
target = genS_C(appl.getE1(), variableContext);
}
ExpressionContextPair arg = genS_C(appl.getE2(), variableContext);
JavaStatement.Block returnBlock = target.getContextBlock();
returnBlock.addStatement(arg.getContextBlock());
MethodInvocation mi = createInvocation(target.getJavaExpression(), APPLY, arg.getJavaExpression());
return generateReturn (new ExpressionContextPair(mi, returnBlock), variableContext);
}
}
//e is a record update
Expression.RecordUpdate recordUpdate = e.asRecordUpdate();
if (recordUpdate != null) {
ExpressionContextPair ecPair = generateStrictRecordUpdate(recordUpdate, variableContext);
return generateReturn(ecPair, variableContext);
}
// e is a record extension
Expression.RecordExtension recordExtension = e.asRecordExtension();
if (recordExtension != null) {
ExpressionContextPair ecPair = generateStrictRecordExtension(recordExtension, variableContext);
return generateReturn(ecPair, variableContext);
}
// e is a record selection
Expression.RecordSelection recordSelection = e.asRecordSelection();
if (recordSelection != null) {
return generateReturn(generateStrictRecordSelection(recordSelection, true, variableContext), variableContext);
}
// e is a record case
Expression.RecordCase recordCase = e.asRecordCase();
if (recordCase != null) {
return generateRecordCase (recordCase, variableContext);
}
// e is a cast
Expression.Cast cast = e.asCast();
if (cast != null) {
Expression.Var varToCast = cast.getVarToCast();
if (!variableContext.isFunctionArgument(varToCast.getName())) {
throw new CodeGenerationException("Expression.Cast is applied to a non-argument variable.");
}
if (!isArgStrict(varToCast.getName()) || !isArgUnboxable(varToCast.getName())) {
throw new CodeGenerationException("Expression.Cast is applied to a non-strict or non-primitive argument.");
}
JavaTypeName castType = JavaTypeName.make (getCastType(cast));
JavaExpression returnVal = boxExpression(castType, new JavaExpression.CastExpression(castType, variableContext.getUnboxedReference(varToCast.getName())));
return generateReturn(returnVal, variableContext);
}
throw new CodeGenerationException("Unrecognized expression: " + e);