//inputRecord recordDict inputList.
//we iterate in FieldName order over the field names so that the function is well-defined in the presence of side effects.
//If f is the nth field in the recordDictionary, then recordDictionary.f is the dictionary for use when calling the
//class method Prelude.input on the nth element of the input list.
final RTRecordValue recordDict = (RTRecordValue)recordDictionary;
final int nOrdinalFields = recordDict.getNOrdinalFields();
final int nTextualFields = recordDict.getNTextualFields();
final int nFields = nOrdinalFields + nTextualFields;
//check that the number of fields in the inputList is the same as the number of fields in the record.
//without this check it is possible that inputList could have more elements than the size of the record and still succeed.
//This would still "work" but this check is useful to alert clients to potential bugs in their code.
if (nFields != inputMap.size()) {
throw new IllegalArgumentException("A Java map of size " + inputMap.size() + " cannot be input to a record with " + nFields + " fields.");
}
//inputMap, but with the keys sorted in FieldName order.
final SortedMap<?, ?> fieldNameSortedInputMap;
//In the case when inputMap is in fact a SortedMap that is using the comparator on the keys, then we can just use it directly.
//We still need to verify that the keys are in fact FieldNames, but that will be done later.
//Otherwise we need to copy the map to get a proper iteration order.
if (inputMap instanceof SortedMap && ((SortedMap<?, ?>)inputMap).comparator() == null) {
fieldNameSortedInputMap = (SortedMap<?, ?>)inputMap;
} else {
fieldNameSortedInputMap = new TreeMap<Object, Object>(inputMap);
}
if (nOrdinalFields > 0) {
final Iterator<?> inputEntrySetIterator = fieldNameSortedInputMap.entrySet().iterator();
final RTValue[] ordinalValues = new RTValue[nOrdinalFields];
for (int i = 0; i < nOrdinalFields; ++i) {
final Map.Entry<?, ?> inputEntry = (Map.Entry<?, ?>)inputEntrySetIterator.next();
final FieldName fieldName = (FieldName)inputEntry.getKey();
if (!(fieldName instanceof FieldName.Ordinal)
|| ((FieldName.Ordinal)fieldName).getOrdinal() != recordDict.getNthOrdinalFieldName(i)) {
throw new IllegalArgumentException("The field names of the input map and target record must match exactly.");
}
final RTValue fieldDict = recordDict.getNthOrdinalValue(i);
final RTValue fieldValue = RTData.CAL_Opaque.make(inputEntry.getValue());
//compute "Prelude.input fieldDict fieldValue"
//this is just (after inlining Prelude.input d = d)
//fieldDict fieldValue
ordinalValues[i] = fieldDict.apply(fieldValue);
}
if (nTextualFields > 0) {
final RTValue[] textualValues = new RTValue[nTextualFields];
for (int i = 0; i < nTextualFields; ++i) {
final Map.Entry<?, ?> inputEntry = (Map.Entry<?, ?>)inputEntrySetIterator.next();
final FieldName fieldName = (FieldName)inputEntry.getKey();
if (!(fieldName instanceof FieldName.Textual)
|| (fieldName.getCalSourceForm() != recordDict.getNthTextualFieldName(i))) {
throw new IllegalArgumentException("The field names of the input map and target record must match exactly.");
}
final RTValue fieldDict = recordDict.getNthTextualValue(i);
final RTValue fieldValue = RTData.CAL_Opaque.make(inputEntry.getValue());
textualValues[i] = fieldDict.apply(fieldValue);
}
return recordDict.makeFromValues(ordinalValues, textualValues);
}
return recordDict.makeFromValues(ordinalValues, null);
}
if (nTextualFields > 0) {
final Iterator<?> inputEntrySetIterator = fieldNameSortedInputMap.entrySet().iterator();
final RTValue[] textualValues = new RTValue[nTextualFields];
for (int i = 0; i < nTextualFields; ++i) {
final Map.Entry<?, ?> inputEntry = (Map.Entry<?, ?>)inputEntrySetIterator.next();
final FieldName fieldName = (FieldName)inputEntry.getKey();
if (!(fieldName instanceof FieldName.Textual)
|| !(fieldName.getCalSourceForm().equals(recordDict.getNthTextualFieldName(i)))) {
throw new IllegalArgumentException("The field names of the input map and target record must match exactly.");
}
final RTValue fieldDict = recordDict.getNthTextualValue(i);
final RTValue fieldValue = RTData.CAL_Opaque.make(inputEntry.getValue());
textualValues[i] = fieldDict.apply(fieldValue);
}
return recordDict.makeFromValues(null, textualValues);
}
//empty record
return RTRecordValue.EMPTY_RECORD;
}