ExpressionContextPair list = compileLiteralList(constructorOpExpressions, scheme, variableContext);
if (list != null) {
return list;
}
DataConstructor dc = constructorOpExpressions.getDataConstructor ();
// If we are dealing with a data constructor for the CAL type boolean we want to optimize
// by substituting and instance of the literal RTKernel.CAL_Boolean.
if (isTrueOrFalseDataCons(dc)) {
LiteralWrapper boolWrapper = LiteralWrapper.make(Boolean.valueOf(isTrueDataCons(dc)));
return new ExpressionContextPair(createMakeKernelBooleanInvocation(boolWrapper));
}
if (LECCMachineConfiguration.TREAT_ENUMS_AS_INTS) {
if (isEnumDataType(dc)) {
// We should never see a DataConstructor instance for an enumeration type.
throw new CodeGenerationException("Encountered enumeration data constructor: " + dc.getName().getQualifiedName());
}
}
int arity = dc.getArity();
JavaTypeName dcTypeName = CALToJavaNames.createTypeNameFromDC(dc, module);
Block argContext = new Block();
boolean[] fieldStrictness = new boolean [dc.getArity()];
boolean dcHasStrictFields = false;
if (LECCMachineConfiguration.IGNORE_STRICTNESS_ANNOTATIONS) {
Arrays.fill(fieldStrictness, false);
} else {
for (int i = 0; i < dc.getArity(); ++i) {
fieldStrictness[i] = dc.isArgStrict(i);
if (fieldStrictness[i]) {
dcHasStrictFields = true;
}
}
}
// If there are no strict arguments we can simply create an instance of the DC class.
// The simplest way to do this is to treat this DC application as if it were in a strict context.
if (!dcHasStrictFields) {
scheme = Scheme.E_SCHEME;
} else {
// If all strict arguments are already evaluated, or we consider them safe to evaluate (i.e. cheap and
// with no side effects) we can treat this as strict.
boolean allOK = true;
for (int i = 0; i < dc.getArity(); ++i) {
if (dc.getArgStrictness()[i] && !canIgnoreLaziness(constructorOpExpressions.getArgument(i), variableContext)) {
allOK = false;
break;
}
}
if (allOK) {
scheme = Scheme.E_SCHEME;
}
}
if (arity < 0) {
throw new CodeGenerationException("Invalid constructor operator arity: " + arity);
} else
if (arity == 0) {
JavaExpression dcInstance;
JavaTypeName typeName = CALToJavaNames.createTypeNameFromDC(dc, module);
if (LECCMachineConfiguration.generateStatistics()) {
// If this is a TagDC we want to pass the ordinal as an argument
if (isTagDC(dc, getModule())) {
dcInstance = new ClassInstanceCreationExpression(typeName, JavaExpression.LiteralWrapper.make(Integer.valueOf(dc.getOrdinal())), JavaTypeName.INT);
} else {
dcInstance = new ClassInstanceCreationExpression(typeName, SCJavaDefn.EXECUTION_CONTEXT_VAR, JavaTypeNames.RTEXECUTION_CONTEXT);
}
} else {
dcInstance = getReferencedDC(typeName, dc);
}
return new ExpressionContextPair(dcInstance, argContext);
} else{
if (scheme == Scheme.C_SCHEME) {
// This is a fully saturated DC application in a lazy context.
// If there are no strict fields in the data constructor we can
// simply create an instance of it. Otherwise create an
// appropriate application node.
// First generate the java expressions for the CAL expressions.
ExpressionContextPair[] ecp = new ExpressionContextPair[dc.getArity()];
for (int i = 0; i < dc.getArity(); ++i) {
ecp[i] = genS_C(constructorOpExpressions.getArgument(i), variableContext);
}
Block newContext = ecp[0].getContextBlock();
for (int i = 1; i < dc.getArity(); ++i) {
newContext.addStatement(ecp[i].getContextBlock());
}
JavaExpression dcExpr = expressionVarToJavaDef(constructorOpExpressions.getDataConstructorExpression(), scheme, variableContext);
if (dc.getArity() <= LECCMachineConfiguration.OPTIMIZED_APP_CHAIN_LENGTH) {
JavaExpression nodeArgs[] = new JavaExpression[dc.getArity() + 1];
JavaTypeName nodeArgTypes[] = new JavaTypeName[dc.getArity() + 1];
nodeArgs[0] = dcExpr;
nodeArgTypes[0] = JavaTypeNames.RTSUPERCOMBINATOR;
for (int i = 0; i < dc.getArity(); ++i) {
nodeArgs[i+1] = ecp[i].getJavaExpression();
nodeArgTypes[i+1] = JavaTypeNames.RTVALUE;
}
JavaTypeName appNodeType = getTypeNameForApplicationNode(dc.getArity(), false);
return new ExpressionContextPair(new JavaExpression.ClassInstanceCreationExpression(appNodeType, nodeArgs, nodeArgTypes), newContext);
} else {
JavaExpression target = dcExpr;
for (int i = 0; i < dc.getArity(); ++i) {
target = createInvocation(target, APPLY, ecp[i].getJavaExpression());
}
return new ExpressionContextPair (target, newContext);
}
} else {
// This is a fully saturated DC application in a strict context. Create a
// new DC class instance.
// First generate the java expressions for the members.
ExpressionContextPair[] ecp = new ExpressionContextPair[dc.getArity()];
TypeExpr[] fieldTypes = SCJavaDefn.getFieldTypesForDC(dc);
for (int i = 0; i < dc.getArity(); ++i) {
if (fieldStrictness[i]) {
if (SCJavaDefn.canTypeBeUnboxed(fieldTypes[i])) {
ecp[i] = generateUnboxedArgument(typeExprToTypeName(fieldTypes[i]), constructorOpExpressions.getArgument(i), variableContext);
} else {
ecp[i] = genS_E(constructorOpExpressions.getArgument(i), variableContext);
}
} else {
ecp[i] = genS_C(constructorOpExpressions.getArgument(i), variableContext);
}
}
Block newContext = ecp[0].getContextBlock();
for (int i = 1; i < dc.getArity(); ++i) {
newContext.addStatement(ecp[i].getContextBlock());
}
int nArgs = dc.getArity();
boolean addEC = LECCMachineConfiguration.passExecContextToDataConstructors();
if (addEC) {
nArgs++;
}
JavaExpression[] constructorArgs = new JavaExpression [nArgs];
JavaTypeName[] constructorArgTypes = new JavaTypeName [nArgs];
for (int i = 0; i < dc.getArity(); ++i) {
constructorArgs[i] = ecp[i].getJavaExpression();
constructorArgTypes[i] = JavaTypeNames.RTVALUE;
if (fieldStrictness[i] && SCJavaDefn.canTypeBeUnboxed(fieldTypes[i])) {
constructorArgTypes[i] = SCJavaDefn.typeExprToTypeName(fieldTypes[i]);
}
}
if (addEC) {
constructorArgs[dc.getArity()] = EXECUTION_CONTEXT_VAR;
constructorArgTypes[dc.getArity()] = JavaTypeNames.RTEXECUTION_CONTEXT;
}
ClassInstanceCreationExpression cc = new ClassInstanceCreationExpression (dcTypeName, constructorArgs, constructorArgTypes);
return new ExpressionContextPair (cc, newContext);
}