同じ式がMap型, List型, Tuple型, Pair型の異なるグループに同時に所属している場合に,推論が正しく進まない不具合を修正.
1 parent f9dbfc0 commit 9a30af6cd5c166ce991774666d45696f6fdb1a6d
Naoya Nitta authored on 17 May 2022
Showing 1 changed file
View
673
AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java
Map<Integer, Type> map = new HashMap<>();
Map<Integer, List<Expression>> expToResource = new HashMap<>();
Map<Integer, List<Expression>> expToVariable = new HashMap<>();
Map<Integer, List<Expression>> expToMessage = new HashMap<>();
Map<Integer, List<Expression>> expToCons = new HashMap<>();
Map<Integer, List<Expression>> expToTuple = new HashMap<>();
Map<Integer, List<Expression>> expToPair = new HashMap<>();
Map<Integer, List<Expression>> expToMap = new HashMap<>();
Map<Integer, Set<List<Expression>>> expToCons = new HashMap<>();
Map<Integer, Set<List<Expression>>> expToTuple = new HashMap<>();
Map<Integer, Set<List<Expression>>> expToPair = new HashMap<>();
Map<Integer, Set<List<Expression>>> expToMap = new HashMap<>();
 
Map<IdentifierTemplate, ResourceNode> idToRes = new HashMap<>();
Map<Integer, Map<Integer, Expression>> updateFromResource = new HashMap<>();
Map<Integer, Map<Integer, Expression>> updateFromVariable = new HashMap<>();
if (symbol.equals(DataConstraintModel.cons)) {
// If the root symbol of the term is cons.
List<Expression> consExps = new ArrayList<>();
consExps.add(t);
expToCons.put(System.identityHashCode(t), consExps);
updateExpressionBelonging(expToCons, t, consExps);
for (Expression e : t.getChildren()) {
consExps.add(e);
expToCons.put(System.identityHashCode(e), consExps);
updateExpressionBelonging(expToCons, e, consExps);
}
Type newType = getExpTypeIfUpdatable(t.getType(), consExps.get(2));
if (newType != null) {
// If the type of the second argument is more concrete than the type of the
// If the root symbol of the term is tuple.
List<Expression> tupleExps = new ArrayList<>();
List<Type> argsTypeList = new ArrayList<>();
tupleExps.add(t);
expToTuple.put(System.identityHashCode(t), tupleExps);
updateExpressionBelonging(expToTuple, t, tupleExps);
for (Expression e : t.getChildren()) {
tupleExps.add(e);
expToTuple.put(System.identityHashCode(e), tupleExps);
updateExpressionBelonging(expToTuple, e, tupleExps);
if (e instanceof Variable) {
argsTypeList.add(((Variable) e).getType());
} else if (e instanceof Term) {
argsTypeList.add(((Term) e).getType());
} else if (symbol.equals(DataConstraintModel.pair)) {
// If the root symbol of the term is pair.
List<Expression> pairExps = new ArrayList<>();
pairExps.add(t);
expToPair.put(System.identityHashCode(t), pairExps);
updateExpressionBelonging(expToPair, t, pairExps);
if (t.getType() == DataConstraintModel.typePair) {
for (Expression e : t.getChildren()) {
pairExps.add(e);
expToPair.put(System.identityHashCode(e), pairExps);
updateExpressionBelonging(expToPair, e, pairExps);
Type argType = null;
if (e instanceof Variable) {
argType = (((Variable) e).getType());
// If the root symbol of the term is fst.
List<Expression> tupleExps = new ArrayList<>();
Expression arg = t.getChildren().get(0);
tupleExps.add(arg);
expToTuple.put(System.identityHashCode(arg), tupleExps);
updateExpressionBelonging(expToTuple, arg, tupleExps);
tupleExps.add(t);
expToTuple.put(System.identityHashCode(t), tupleExps);
updateExpressionBelonging(expToTuple, t, tupleExps);
tupleExps.add(null);
Type argType = null;
if (arg instanceof Variable) {
argType = ((Variable) arg).getType();
// If the root symbol of the term is snd.
List<Expression> tupleExps = new ArrayList<>();
Expression arg = t.getChildren().get(0);
tupleExps.add(arg);
expToTuple.put(System.identityHashCode(arg), tupleExps);
updateExpressionBelonging(expToTuple, arg, tupleExps);
tupleExps.add(null);
tupleExps.add(t);
expToTuple.put(System.identityHashCode(t), tupleExps);
updateExpressionBelonging(expToTuple, t, tupleExps);
Type argType = null;
if (arg instanceof Variable) {
argType = ((Variable) arg).getType();
} else if (arg instanceof Term) {
// If the root symbol of the term is left.
List<Expression> pairExps = new ArrayList<>();
Expression arg = t.getChildren().get(0);
pairExps.add(arg);
expToPair.put(System.identityHashCode(arg), pairExps);
updateExpressionBelonging(expToPair, arg, pairExps);
pairExps.add(t);
expToPair.put(System.identityHashCode(t), pairExps);
updateExpressionBelonging(expToPair, t, pairExps);
pairExps.add(null);
Type argType = null;
if (arg instanceof Variable) {
argType = ((Variable) arg).getType();
// If the root symbol of the term is right.
List<Expression> pairExps = new ArrayList<>();
Expression arg = t.getChildren().get(0);
pairExps.add(arg);
expToPair.put(System.identityHashCode(arg), pairExps);
updateExpressionBelonging(expToPair, arg, pairExps);
pairExps.add(null);
pairExps.add(t);
expToPair.put(System.identityHashCode(t), pairExps);
updateExpressionBelonging(expToPair, t, pairExps);
Type argType = null;
if (arg instanceof Variable) {
argType = ((Variable) arg).getType();
} else if (arg instanceof Term) {
// If the root symbol of the term is lookup.
List<Expression> mapExps = new ArrayList<>();
Expression arg1 = t.getChildren().get(0); // map
mapExps.add(arg1);
expToMap.put(System.identityHashCode(arg1), mapExps);
updateExpressionBelonging(expToMap, arg1, mapExps);
Expression arg2 = t.getChildren().get(1); // key
mapExps.add(arg2);
expToMap.put(System.identityHashCode(arg2), mapExps);
updateExpressionBelonging(expToMap, arg2, mapExps);
mapExps.add(t); // value
expToMap.put(System.identityHashCode(t), mapExps);
updateExpressionBelonging(expToMap, t, mapExps);
Type arg1Type = null;
if (arg1 instanceof Variable) {
arg1Type = ((Variable) arg1).getType();
} else if (arg1 instanceof Term) {
} else if (symbol.equals(DataConstraintModel.insert)) {
// If the root symbol of the term is insert.
List<Expression> mapExps = new ArrayList<>();
mapExps.add(t); // map
expToMap.put(System.identityHashCode(t), mapExps);
updateExpressionBelonging(expToMap, t, mapExps);
Expression arg1 = t.getChildren().get(1); // key
mapExps.add(arg1);
expToMap.put(System.identityHashCode(arg1), mapExps);
updateExpressionBelonging(expToMap, arg1, mapExps);
Expression arg2 = t.getChildren().get(2); // value
mapExps.add(arg2);
expToMap.put(System.identityHashCode(arg2), mapExps);
updateExpressionBelonging(expToMap, arg2, mapExps);
Expression arg0 = t.getChildren().get(0); // map
mapExps.add(arg0);
expToMap.put(System.identityHashCode(arg0), mapExps);
updateExpressionBelonging(expToMap, arg0, mapExps);
Type termType = t.getType();
List<Type> compTypeList = new ArrayList<>();
if (arg1 instanceof Variable) {
compTypeList.add(((Variable) arg1).getType());
}
}
}
 
private static void updateExpressionBelonging(Map<Integer, Set<List<Expression>>> belonging, Expression exp, List<Expression> group) {
Set<List<Expression>> groups = belonging.get(System.identityHashCode(exp));
if (groups == null) {
groups = new HashSet<>();
belonging.put(System.identityHashCode(exp), groups);
groups.add(group);
return;
}
if (!groups.contains(group)) {
groups.add(group);
}
}
 
private static void updateResourceTypes(Expression exp, Map<IdentifierTemplate, List<Expression>> resources,
Map<Integer, List<Expression>> expToResource, Map<Integer, Map<Integer, Expression>> updateFromResource) {
List<Expression> sameResource = expToResource.get(System.identityHashCode(exp));
if (sameResource == null)
return;
if (sameResource == null) return;
for (IdentifierTemplate id : resources.keySet()) {
if (resources.get(id) == sameResource) {
Type resType = id.getResourceStateType();
Type newResType = getExpTypeIfUpdatable(resType, exp);
 
private static void updateVaribleTypes(Expression exp, Map<Integer, Type> variables,
Map<Integer, List<Expression>> expToVariable, Map<Integer, Map<Integer, Expression>> updateFromVariable) {
List<Expression> sameVariable = expToVariable.get(System.identityHashCode(exp));
if (sameVariable == null)
return;
if (sameVariable == null) return;
Type varType = variables.get(System.identityHashCode(sameVariable));
Type newVarType = getExpTypeIfUpdatable(varType, exp);
if (newVarType != null) {
variables.put(System.identityHashCode(sameVariable), newVarType);
private static void updateMessageTypes(Expression exp,
Map<ChannelGenerator, Map<Integer, Map.Entry<List<Expression>, Type>>> messages,
Map<Integer, List<Expression>> expToMessage, Map<Integer, Map<Integer, Expression>> updateFromMessage) {
List<Expression> messageExps = expToMessage.get(System.identityHashCode(exp));
if (messageExps == null)
return;
if (messageExps == null) return;
Type msgType = null;
Map.Entry<List<Expression>, Type> expsAndType = null;
for (ChannelGenerator c : messages.keySet()) {
for (int i : messages.get(c).keySet()) {
msgType = expsAndType.getValue();
break;
}
}
if (msgType != null)
break;
}
if (msgType == null)
return;
if (msgType != null) break;
}
if (msgType == null) return;
Type newMsgType = getExpTypeIfUpdatable(msgType, exp);
if (newMsgType != null) {
expsAndType.setValue(newMsgType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromMessage, messageExps);
}
}
 
private static void updateConsTypes(Expression exp, Map<Integer, Type> cons,
Map<Integer, List<Expression>> expToCons, Map<Integer, Map<Integer, Expression>> updateFromCons) {
List<Expression> consComponents = expToCons.get(System.identityHashCode(exp));
if (consComponents == null)
return;
int idx = consComponents.indexOf(exp);
switch (idx) {
case 0:
if (!(exp instanceof Term))
return;
Type listType = cons.get(System.identityHashCode(consComponents));
Type expType = getExpTypeIfUpdatable(listType, exp);
if (expType != null) {
cons.put(System.identityHashCode(consComponents), expType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromCons, consComponents);
if (consComponents.get(2) instanceof Variable) {
((Variable) consComponents.get(2)).setType(expType);
updateExps.put(System.identityHashCode(consComponents.get(2)), consComponents.get(2));
} else if (consComponents.get(2) instanceof Term) {
((Term) consComponents.get(2)).setType(expType);
updateExps.put(System.identityHashCode(consComponents.get(2)), consComponents.get(2));
}
Type compType = listComponentTypes.get(expType);
if (consComponents.get(1) != null && consComponents.get(1) instanceof Variable) {
((Variable) consComponents.get(1)).setType(compType);
updateExps.put(System.identityHashCode(consComponents.get(1)), consComponents.get(1));
} else if (consComponents.get(1) != null && consComponents.get(1) instanceof Term) {
((Term) consComponents.get(1)).setType(compType);
updateExps.put(System.identityHashCode(consComponents.get(1)), consComponents.get(1));
}
}
break;
case 1:
listType = cons.get(System.identityHashCode(consComponents));
Type compType = listComponentTypes.get(listType);
Type newCompType = getExpTypeIfUpdatable(compType, exp);
if (newCompType != null) {
Type newListType = listTypes.get(newCompType);
if (newListType == null) {
// Create new list type.
newListType = createNewListType(newCompType, listType);
}
cons.put(System.identityHashCode(consComponents), newListType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromCons, consComponents);
if (consComponents.get(0) instanceof Term) {
((Term) consComponents.get(0)).setType(newListType);
updateExps.put(System.identityHashCode(consComponents.get(0)), consComponents.get(0));
}
if (consComponents.get(2) instanceof Variable) {
((Variable) consComponents.get(2)).setType(newListType);
updateExps.put(System.identityHashCode(consComponents.get(2)), consComponents.get(2));
} else if (consComponents.get(2) instanceof Term) {
((Term) consComponents.get(2)).setType(newListType);
updateExps.put(System.identityHashCode(consComponents.get(2)), consComponents.get(2));
}
}
break;
case 2:
listType = cons.get(System.identityHashCode(consComponents));
expType = getExpTypeIfUpdatable(listType, exp);
if (expType != null) {
cons.put(System.identityHashCode(consComponents), expType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromCons, consComponents);
if (consComponents.get(0) instanceof Term) {
((Term) consComponents.get(0)).setType(expType);
updateExps.put(System.identityHashCode(consComponents.get(0)), consComponents.get(0));
}
compType = listComponentTypes.get(expType);
if (consComponents.get(1) != null && consComponents.get(1) instanceof Variable) {
((Variable) consComponents.get(1)).setType(compType);
updateExps.put(System.identityHashCode(consComponents.get(1)), consComponents.get(1));
} else if (consComponents.get(1) != null && consComponents.get(1) instanceof Term) {
((Term) consComponents.get(1)).setType(compType);
updateExps.put(System.identityHashCode(consComponents.get(1)), consComponents.get(1));
Map<Integer, Set<List<Expression>>> expToCons, Map<Integer, Map<Integer, Expression>> updateFromCons) {
Set<List<Expression>> consComponentGroups = expToCons.get(System.identityHashCode(exp));
if (consComponentGroups == null) return;
for (List<Expression> consComponentGroup: consComponentGroups) {
int idx = consComponentGroup.indexOf(exp);
switch (idx) {
case 0:
if (!(exp instanceof Term)) break;
Type listType = cons.get(System.identityHashCode(consComponentGroup));
Type expType = getExpTypeIfUpdatable(listType, exp);
if (expType != null) {
cons.put(System.identityHashCode(consComponentGroup), expType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromCons, consComponentGroup);
if (consComponentGroup.get(2) instanceof Variable) {
((Variable) consComponentGroup.get(2)).setType(expType);
updateExps.put(System.identityHashCode(consComponentGroup.get(2)), consComponentGroup.get(2));
} else if (consComponentGroup.get(2) instanceof Term) {
((Term) consComponentGroup.get(2)).setType(expType);
updateExps.put(System.identityHashCode(consComponentGroup.get(2)), consComponentGroup.get(2));
}
Type compType = listComponentTypes.get(expType);
if (consComponentGroup.get(1) != null && consComponentGroup.get(1) instanceof Variable) {
((Variable) consComponentGroup.get(1)).setType(compType);
updateExps.put(System.identityHashCode(consComponentGroup.get(1)), consComponentGroup.get(1));
} else if (consComponentGroup.get(1) != null && consComponentGroup.get(1) instanceof Term) {
((Term) consComponentGroup.get(1)).setType(compType);
updateExps.put(System.identityHashCode(consComponentGroup.get(1)), consComponentGroup.get(1));
}
}
break;
case 1:
listType = cons.get(System.identityHashCode(consComponentGroup));
Type compType = listComponentTypes.get(listType);
Type newCompType = getExpTypeIfUpdatable(compType, exp);
if (newCompType != null) {
Type newListType = listTypes.get(newCompType);
if (newListType == null) {
// Create new list type.
newListType = createNewListType(newCompType, listType);
}
cons.put(System.identityHashCode(consComponentGroup), newListType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromCons, consComponentGroup);
if (consComponentGroup.get(0) instanceof Term) {
((Term) consComponentGroup.get(0)).setType(newListType);
updateExps.put(System.identityHashCode(consComponentGroup.get(0)), consComponentGroup.get(0));
}
if (consComponentGroup.get(2) instanceof Variable) {
((Variable) consComponentGroup.get(2)).setType(newListType);
updateExps.put(System.identityHashCode(consComponentGroup.get(2)), consComponentGroup.get(2));
} else if (consComponentGroup.get(2) instanceof Term) {
((Term) consComponentGroup.get(2)).setType(newListType);
updateExps.put(System.identityHashCode(consComponentGroup.get(2)), consComponentGroup.get(2));
}
}
break;
case 2:
listType = cons.get(System.identityHashCode(consComponentGroup));
expType = getExpTypeIfUpdatable(listType, exp);
if (expType != null) {
cons.put(System.identityHashCode(consComponentGroup), expType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromCons, consComponentGroup);
if (consComponentGroup.get(0) instanceof Term) {
((Term) consComponentGroup.get(0)).setType(expType);
updateExps.put(System.identityHashCode(consComponentGroup.get(0)), consComponentGroup.get(0));
}
compType = listComponentTypes.get(expType);
if (consComponentGroup.get(1) != null && consComponentGroup.get(1) instanceof Variable) {
((Variable) consComponentGroup.get(1)).setType(compType);
updateExps.put(System.identityHashCode(consComponentGroup.get(1)), consComponentGroup.get(1));
} else if (consComponentGroup.get(1) != null && consComponentGroup.get(1) instanceof Term) {
((Term) consComponentGroup.get(1)).setType(compType);
updateExps.put(System.identityHashCode(consComponentGroup.get(1)), consComponentGroup.get(1));
}
}
}
}
}
 
private static void updateTupleTypes(Expression exp, Map<Integer, Type> tuple,
Map<Integer, List<Expression>> expToTuple, Map<Integer, Map<Integer, Expression>> updateFromTuple) {
List<Expression> components = expToTuple.get(System.identityHashCode(exp));
if (components == null)
return;
int idx = components.indexOf(exp);
if (idx == 0) {
Type tupleType = tuple.get(System.identityHashCode(components));
Type newTupleType = getExpTypeIfUpdatable(tupleType, exp);
if (newTupleType != null) {
// Propagate an update of a tuple's type to its components' types.
tuple.put(System.identityHashCode(components), newTupleType);
List<Type> componentTypes = tupleComponentTypes.get(newTupleType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromTuple, components);
for (int i = 1; i < components.size(); i++) {
Expression compExp = components.get(i);
if (compExp instanceof Variable) {
if (compareTypes(((Variable) compExp).getType(), componentTypes.get(i - 1))) {
((Variable) compExp).setType(componentTypes.get(i - 1));
updateExps.put(System.identityHashCode(compExp), compExp);
}
} else if (compExp instanceof Term) {
if (compareTypes(((Term) compExp).getType(), componentTypes.get(i - 1))) {
((Term) compExp).setType(componentTypes.get(i - 1));
updateExps.put(System.identityHashCode(compExp), compExp);
}
}
}
}
} else {
Type tupleType = tuple.get(System.identityHashCode(components));
List<Type> componentTypes = tupleComponentTypes.get(tupleType);
Type compType = componentTypes.get(idx - 1);
Type newCompType = getExpTypeIfUpdatable(compType, exp);
if (newCompType != null) {
// Propagate an update of a component's type to its container's (tuple's) type.
componentTypes = new ArrayList<>(componentTypes);
componentTypes.set(idx - 1, newCompType);
Type newTupleType = tupleTypes.get(componentTypes);
if (newTupleType == null) {
// Create new tuple type;
newTupleType = createNewTupleType(componentTypes, tupleType);
}
Map<Integer, Expression> updateExps = getUpdateSet(updateFromTuple, components);
Expression tupleExp = components.get(0);
if (tupleExp instanceof Variable) {
((Variable) tupleExp).setType(newTupleType);
updateExps.put(System.identityHashCode(tupleExp), tupleExp);
} else if (tupleExp instanceof Term) {
((Term) tupleExp).setType(newTupleType);
updateExps.put(System.identityHashCode(tupleExp), tupleExp);
}
tuple.put(System.identityHashCode(components), newTupleType);
Map<Integer, Set<List<Expression>>> expToTuple, Map<Integer, Map<Integer, Expression>> updateFromTuple) {
Set<List<Expression>> tupleComponentGroups = expToTuple.get(System.identityHashCode(exp));
if (tupleComponentGroups == null) return;
for (List<Expression> tupleComponentGroup: tupleComponentGroups) {
int idx = tupleComponentGroup.indexOf(exp);
if (idx == 0) {
Type tupleType = tuple.get(System.identityHashCode(tupleComponentGroup));
Type newTupleType = getExpTypeIfUpdatable(tupleType, exp);
if (newTupleType != null) {
// Propagate an update of a tuple's type to its components' types.
tuple.put(System.identityHashCode(tupleComponentGroup), newTupleType);
List<Type> componentTypes = tupleComponentTypes.get(newTupleType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromTuple, tupleComponentGroup);
for (int i = 1; i < tupleComponentGroup.size(); i++) {
Expression compExp = tupleComponentGroup.get(i);
if (compExp instanceof Variable) {
if (compareTypes(((Variable) compExp).getType(), componentTypes.get(i - 1))) {
((Variable) compExp).setType(componentTypes.get(i - 1));
updateExps.put(System.identityHashCode(compExp), compExp);
}
} else if (compExp instanceof Term) {
if (compareTypes(((Term) compExp).getType(), componentTypes.get(i - 1))) {
((Term) compExp).setType(componentTypes.get(i - 1));
updateExps.put(System.identityHashCode(compExp), compExp);
}
}
}
}
} else {
Type tupleType = tuple.get(System.identityHashCode(tupleComponentGroup));
List<Type> componentTypes = tupleComponentTypes.get(tupleType);
Type compType = componentTypes.get(idx - 1);
Type newCompType = getExpTypeIfUpdatable(compType, exp);
if (newCompType != null) {
// Propagate an update of a component's type to its container's (tuple's) type.
componentTypes = new ArrayList<>(componentTypes);
componentTypes.set(idx - 1, newCompType);
Type newTupleType = tupleTypes.get(componentTypes);
if (newTupleType == null) {
// Create new tuple type;
newTupleType = createNewTupleType(componentTypes, tupleType);
}
Map<Integer, Expression> updateExps = getUpdateSet(updateFromTuple, tupleComponentGroup);
Expression tupleExp = tupleComponentGroup.get(0);
if (tupleExp instanceof Variable) {
((Variable) tupleExp).setType(newTupleType);
updateExps.put(System.identityHashCode(tupleExp), tupleExp);
} else if (tupleExp instanceof Term) {
((Term) tupleExp).setType(newTupleType);
updateExps.put(System.identityHashCode(tupleExp), tupleExp);
}
tuple.put(System.identityHashCode(tupleComponentGroup), newTupleType);
}
}
}
}
 
private static void updatePairTypes(Expression exp, Map<Integer, Type> pair,
Map<Integer, List<Expression>> expToPair, Map<Integer, Map<Integer, Expression>> updateFromPair) {
List<Expression> components = expToPair.get(System.identityHashCode(exp));
if (components == null)
return;
int idx = components.indexOf(exp);
if (idx == 0) {
Type pairType = pair.get(System.identityHashCode(components));
Type newPairType = getExpTypeIfUpdatable(pairType, exp);
if (newPairType != null) {
// Propagate an update of a pair's type to its components' types.
pair.put(System.identityHashCode(components), newPairType);
Type componentType = pairComponentTypes.get(newPairType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromPair, components);
for (int i = 1; i < components.size(); i++) {
Expression compExp = components.get(i);
if (compExp instanceof Variable) {
if (compareTypes(((Variable) compExp).getType(), componentType)) {
((Variable) compExp).setType(componentType);
updateExps.put(System.identityHashCode(compExp), compExp);
}
} else if (compExp instanceof Term) {
if (compareTypes(((Term) compExp).getType(), componentType)) {
((Term) compExp).setType(componentType);
updateExps.put(System.identityHashCode(compExp), compExp);
}
}
}
}
} else {
Type pairType = pair.get(System.identityHashCode(components));
Type compType = pairComponentTypes.get(pairType);
Type newCompType = getExpTypeIfUpdatable(compType, exp);
if (newCompType != null) {
// Propagate an update of a component's type to its container's (pair's) type.
Type newPairType = pairTypes.get(compType);
Map<Integer, Set<List<Expression>>> expToPair, Map<Integer, Map<Integer, Expression>> updateFromPair) {
Set<List<Expression>> pairComponentGroups = expToPair.get(System.identityHashCode(exp));
if (pairComponentGroups == null) return;
for (List<Expression> pairComponentGroup: pairComponentGroups) {
int idx = pairComponentGroup.indexOf(exp);
if (idx == 0) {
Type pairType = pair.get(System.identityHashCode(pairComponentGroup));
Type newPairType = getExpTypeIfUpdatable(pairType, exp);
if (newPairType != null) {
Map<Integer, Expression> updateExps = getUpdateSet(updateFromPair, components);
Expression pairExp = components.get(0);
if (pairExp instanceof Variable) {
((Variable) pairExp).setType(newPairType);
updateExps.put(System.identityHashCode(pairExp), pairExp);
} else if (pairExp instanceof Term) {
((Term) pairExp).setType(newPairType);
updateExps.put(System.identityHashCode(pairExp), pairExp);
}
pair.put(System.identityHashCode(components), newPairType);
}
}
}
}
// Propagate an update of a pair's type to its components' types.
pair.put(System.identityHashCode(pairComponentGroup), newPairType);
Type componentType = pairComponentTypes.get(newPairType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromPair, pairComponentGroup);
for (int i = 1; i < pairComponentGroup.size(); i++) {
Expression compExp = pairComponentGroup.get(i);
if (compExp instanceof Variable) {
if (compareTypes(((Variable) compExp).getType(), componentType)) {
((Variable) compExp).setType(componentType);
updateExps.put(System.identityHashCode(compExp), compExp);
}
} else if (compExp instanceof Term) {
if (compareTypes(((Term) compExp).getType(), componentType)) {
((Term) compExp).setType(componentType);
updateExps.put(System.identityHashCode(compExp), compExp);
}
}
}
}
} else {
Type pairType = pair.get(System.identityHashCode(pairComponentGroup));
Type compType = pairComponentTypes.get(pairType);
Type newCompType = getExpTypeIfUpdatable(compType, exp);
if (newCompType != null) {
// Propagate an update of a component's type to its container's (pair's) type.
Type newPairType = pairTypes.get(compType);
if (newPairType != null) {
Map<Integer, Expression> updateExps = getUpdateSet(updateFromPair, pairComponentGroup);
Expression pairExp = pairComponentGroup.get(0);
if (pairExp instanceof Variable) {
((Variable) pairExp).setType(newPairType);
updateExps.put(System.identityHashCode(pairExp), pairExp);
} else if (pairExp instanceof Term) {
((Term) pairExp).setType(newPairType);
updateExps.put(System.identityHashCode(pairExp), pairExp);
}
pair.put(System.identityHashCode(pairComponentGroup), newPairType);
}
}
}
}
}
private static void updateMapTypes(Expression exp, Map<Integer, Type> map,
Map<Integer, List<Expression>> expToMap, Map<Integer, Map<Integer, Expression>> updateFromMap) {
List<Expression> components = expToMap.get(System.identityHashCode(exp));
if (components == null)
return;
int idx = components.indexOf(exp);
if (idx == 0 || idx == 3) {
Type mapType = map.get(System.identityHashCode(components));
Type newMapType = getExpTypeIfUpdatable(mapType, exp);
if (newMapType != null) {
// Propagate an update of a map's type to its components' types.
map.put(System.identityHashCode(components), newMapType);
List<Type> componentTypes = mapComponentTypes.get(newMapType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromMap, components);
for (int i = 1; i < components.size() && i < 3; i++) {
Expression compExp = components.get(i);
if (compExp instanceof Variable) {
if (compareTypes(((Variable) compExp).getType(), componentTypes.get(i - 1))) {
((Variable) compExp).setType(componentTypes.get(i - 1));
updateExps.put(System.identityHashCode(compExp), compExp);
}
} else if (compExp instanceof Term) {
if (compareTypes(((Term) compExp).getType(), componentTypes.get(i - 1))) {
((Term) compExp).setType(componentTypes.get(i - 1));
updateExps.put(System.identityHashCode(compExp), compExp);
}
}
}
// Propagate an update of a map's type to another map's type.
Expression compExp = null;
if (idx == 0 && components.size() == 4) { // for lookup
compExp = components.get(3);
} else if (idx == 3) {
compExp = components.get(0);
}
if (compExp != null) {
if (compExp instanceof Variable) {
if (compareTypes(((Variable) compExp).getType(), newMapType)) {
((Variable) compExp).setType(newMapType);
updateExps.put(System.identityHashCode(compExp), compExp);
}
} else if (compExp instanceof Term) {
if (compareTypes(((Term) compExp).getType(), newMapType)) {
((Term) compExp).setType(newMapType);
updateExps.put(System.identityHashCode(compExp), compExp);
}
}
}
}
} else {
Type mapType = map.get(System.identityHashCode(components));
List<Type> componentTypes = mapComponentTypes.get(mapType);
Type compType = componentTypes.get(idx - 1);
Type newCompType = getExpTypeIfUpdatable(compType, exp);
if (newCompType != null) {
// Propagate an update of a component's type to its container's (map's) type.
componentTypes = new ArrayList<>(componentTypes);
componentTypes.set(idx - 1, newCompType);
Type newMapType = mapTypes.get(componentTypes);
if (newMapType == null) {
// Create new map type;
newMapType = createNewMapType(componentTypes, mapType);
}
Map<Integer, Expression> updateExps = getUpdateSet(updateFromMap, components);
Expression mapExp = components.get(0);
if (mapExp instanceof Variable) {
((Variable) mapExp).setType(newMapType);
updateExps.put(System.identityHashCode(mapExp), mapExp);
} else if (mapExp instanceof Term) {
((Term) mapExp).setType(newMapType);
updateExps.put(System.identityHashCode(mapExp), mapExp);
}
if (components.size() == 4) { // for lookup
mapExp = components.get(3);
Map<Integer, Set<List<Expression>>> expToMap, Map<Integer, Map<Integer, Expression>> updateFromMap) {
Set<List<Expression>> mapComponentGroups = expToMap.get(System.identityHashCode(exp));
if (mapComponentGroups == null) return;
for (List<Expression> mapComponentGroup: mapComponentGroups) {
int idx = mapComponentGroup.indexOf(exp);
if (idx == 0 || idx == 3) {
Type mapType = map.get(System.identityHashCode(mapComponentGroup));
Type newMapType = getExpTypeIfUpdatable(mapType, exp);
if (newMapType != null) {
// Propagate an update of a map's type to its components' types.
map.put(System.identityHashCode(mapComponentGroup), newMapType);
List<Type> componentTypes = mapComponentTypes.get(newMapType);
Map<Integer, Expression> updateExps = getUpdateSet(updateFromMap, mapComponentGroup);
for (int i = 1; i < mapComponentGroup.size() && i < 3; i++) {
Expression compExp = mapComponentGroup.get(i);
if (compExp instanceof Variable) {
if (compareTypes(((Variable) compExp).getType(), componentTypes.get(i - 1))) {
((Variable) compExp).setType(componentTypes.get(i - 1));
updateExps.put(System.identityHashCode(compExp), compExp);
}
} else if (compExp instanceof Term) {
if (compareTypes(((Term) compExp).getType(), componentTypes.get(i - 1))) {
((Term) compExp).setType(componentTypes.get(i - 1));
updateExps.put(System.identityHashCode(compExp), compExp);
}
}
}
// Propagate an update of a map's type to another map's type.
Expression compExp = null;
if (idx == 0 && mapComponentGroup.size() == 4) { // for lookup
compExp = mapComponentGroup.get(3);
} else if (idx == 3) {
compExp = mapComponentGroup.get(0);
}
if (compExp != null) {
if (compExp instanceof Variable) {
if (compareTypes(((Variable) compExp).getType(), newMapType)) {
((Variable) compExp).setType(newMapType);
updateExps.put(System.identityHashCode(compExp), compExp);
}
} else if (compExp instanceof Term) {
if (compareTypes(((Term) compExp).getType(), newMapType)) {
((Term) compExp).setType(newMapType);
updateExps.put(System.identityHashCode(compExp), compExp);
}
}
}
}
} else {
Type mapType = map.get(System.identityHashCode(mapComponentGroup));
List<Type> componentTypes = mapComponentTypes.get(mapType);
Type compType = componentTypes.get(idx - 1);
Type newCompType = getExpTypeIfUpdatable(compType, exp);
if (newCompType != null) {
// Propagate an update of a component's type to its container's (map's) type.
componentTypes = new ArrayList<>(componentTypes);
componentTypes.set(idx - 1, newCompType);
Type newMapType = mapTypes.get(componentTypes);
if (newMapType == null) {
// Create new map type;
newMapType = createNewMapType(componentTypes, mapType);
}
Map<Integer, Expression> updateExps = getUpdateSet(updateFromMap, mapComponentGroup);
Expression mapExp = mapComponentGroup.get(0);
if (mapExp instanceof Variable) {
((Variable) mapExp).setType(newMapType);
updateExps.put(System.identityHashCode(mapExp), mapExp);
} else if (mapExp instanceof Term) {
((Term) mapExp).setType(newMapType);
updateExps.put(System.identityHashCode(mapExp), mapExp);
}
}
map.put(System.identityHashCode(components), newMapType);
}
}
}
}
if (mapComponentGroup.size() == 4) { // for lookup
mapExp = mapComponentGroup.get(3);
if (mapExp instanceof Variable) {
((Variable) mapExp).setType(newMapType);
updateExps.put(System.identityHashCode(mapExp), mapExp);
} else if (mapExp instanceof Term) {
((Term) mapExp).setType(newMapType);
updateExps.put(System.identityHashCode(mapExp), mapExp);
}
}
map.put(System.identityHashCode(mapComponentGroup), newMapType);
}
}
}
}
private static Type createNewListType(Type compType, Type parentType) {
String compTypeName = getInterfaceTypeName(compType);
List<Type> childrenTypes = getChildrenTypes(parentType, listComponentTypes.keySet());