// Get the value nodes for the list and the items in the list.
ListValueNode listValueNode = (ListValueNode)getValueNode();
List<ValueNode> listElementNodes = listValueNode.getValue();
// Determine whether we are dealing with a generic list, list of tuples or list of records
ValueNode firstChild = listElementNodes.get(0);
boolean isListOfNTupleVNs = firstChild instanceof NTupleValueNode; // isListRecord will also be true.
boolean isListRecord = getListElementType().rootRecordType() != null;
int tupleSize = isListOfNTupleVNs ? ((NTupleValueNode)listElementNodes.get(0)).getTupleSize() : -1;
// Calculate new unconstrained types for the list and the elements of the list.
TypeExpr unconstrainedListType = getContext().getLeastConstrainedTypeExpr();
TypeExpr unconstrainedListElementType;
if (unconstrainedListType.rootTypeVar() != null ||
(!consolidateColumns && isListRecord && unconstrainedListType.rootTypeConsApp().getArg(0).rootTypeVar() != null)) { // check for [a]
// The context is parametric (ie: a or [a]), so create the least constrained type
// depending on the list element type:
if (!consolidateColumns && isListOfNTupleVNs) {
// Tuple least constrained type: (a, a, ... )
unconstrainedListElementType = TypeExpr.makeTupleType(tupleSize);
} else if (!consolidateColumns && isListRecord) {
// Record least constrained type: {field1 = a, field2 = b, ...}
// Build this from the existing fields
List<FieldName> fieldNames = getListElementType().rootRecordType().getHasFieldNames();
Map<FieldName, TypeExpr> fieldNameToTypeMap = new HashMap<FieldName, TypeExpr>();
for (final FieldName fieldName : fieldNames) {
fieldNameToTypeMap.put(fieldName, TypeExpr.makeParametricType());
}
unconstrainedListElementType = TypeExpr.makeNonPolymorphicRecordType(fieldNameToTypeMap);
} else {
// General element least constrained type: (a)
unconstrainedListElementType = TypeExpr.makeParametricType();
}
unconstrainedListType = valueEditorManager.getValueNodeBuilderHelper().getPreludeTypeConstants().makeListType(unconstrainedListElementType);
} else {
// Element type expression is bound to context
unconstrainedListElementType = unconstrainedListType.rootTypeConsApp().getArg(0);
//first build a field map containing all the fields from the context
final Map<FieldName, TypeExpr> fieldMap; //map of all the fields in the context RecordFieldName -> TypeExpr
if (unconstrainedListElementType instanceof RecordType) {
fieldMap = ((RecordType) unconstrainedListElementType).getHasFieldsMap();
} else {
fieldMap = new HashMap<FieldName, TypeExpr>();
}
//add all the additional fields from the editor
if (firstChild.getTypeExpr() instanceof RecordType ) {
RecordType elementType = (RecordType ) firstChild.getTypeExpr(); // unconstrainedListElementType;
for (int i = 0; i < elementType.getNHasFields(); i++) {
final FieldName fieldName = elementType.getHasFieldNames().get(i);
if (!fieldMap.containsKey(fieldName)) {
fieldMap.put(fieldName, TypeExpr.makeParametricType());
}
}
}
//make sure the element type is actually supposed to be a record - otherwise just use generic type
if (!(firstChild.getTypeExpr() instanceof RecordType) &&
! (unconstrainedListElementType instanceof RecordType)) {
unconstrainedListElementType = TypeExpr.makeParametricType();
} else {
unconstrainedListElementType = TypeExpr.makeNonPolymorphicRecordType(fieldMap);
}
unconstrainedListType = valueEditorManager.getValueNodeBuilderHelper().getPreludeTypeConstants().makeListType(unconstrainedListElementType);
}
// Populate the map
// List
returnMap.put(listValueNode, unconstrainedListType);
// List items
for (final ValueNode listElementNode : listElementNodes) {//.iterator(); it.hasNext(); ) {
returnMap.put(listElementNode, unconstrainedListElementType);
if (!consolidateColumns) {
// For tuple and record lists, we have to also put the individual elements of the list items
if (isListOfNTupleVNs) {
NTupleValueNode currentTupleValue = (NTupleValueNode)listElementNode;
RecordType unconstrainedListElementRecordType = (RecordType)unconstrainedListElementType;
Map<FieldName, TypeExpr> hasFieldsMap = unconstrainedListElementRecordType.getHasFieldsMap();
int j = 0;
for (final TypeExpr unconstrainedTupleElementType : hasFieldsMap.values()) {
ValueNode currentTupleItem = currentTupleValue.getValueAt(j);
returnMap.put(currentTupleItem, unconstrainedTupleElementType);
++j;
}
} else if (isListRecord) {
List<FieldName> contextRecordFieldNames = ((RecordType)unconstrainedListElementType).getHasFieldNames();
RecordValueNode currentRecordValue = (RecordValueNode)listElementNode;
for (int j = 0, n = currentRecordValue.getNFieldNames(); j < n; j++) {
ValueNode currentFieldItem = currentRecordValue.getValueAt(j);
TypeExpr unconstrainedFieldType;
if (contextRecordFieldNames.contains(currentRecordValue.getFieldName(j))) {
unconstrainedFieldType = ((RecordType)unconstrainedListElementType).getHasFieldType(currentRecordValue.getFieldName(j));