in meta/src/main/java/org/arend/lib/pattern/PatternUtils.java [296:443]
private static boolean computeCovering(List<Pair<? extends List<? extends CorePattern>, Integer>> actualRows, List<? extends CorePattern> row, Set<Integer> indices) {
if (actualRows.isEmpty()) {
return false;
}
if (row.isEmpty()) {
indices.add(actualRows.get(0).proj2);
return true;
}
class MyBinding implements CoreBinding {
final CoreExpression type;
MyBinding(CoreExpression type) {
this.type = type;
}
@Override
public CoreExpression getTypeExpr() {
return type;
}
@Override
public CoreReferenceExpression makeReference() {
return null;
}
@Override
public String getName() {
return null;
}
}
CorePattern pattern = row.get(0);
List<Pair<? extends List<? extends CorePattern>, Integer>> newRows = new ArrayList<>(actualRows.size());
List<? extends CorePattern> rowTail = row.subList(1, row.size());
if (pattern.getBinding() != null) {
boolean allVars = true;
boolean hasVars = false;
Set<CoreDefinition> constructors = new LinkedHashSet<>();
for (Pair<? extends List<? extends CorePattern>, Integer> actualRow : actualRows) {
CorePattern actualPattern = actualRow.proj1.get(0);
if (actualPattern.isAbsurd()) { // TODO: This is not needed if implemented properly; see TODO below
indices.add(actualRow.proj2);
return true;
}
if (actualPattern.getBinding() == null) {
allVars = false;
if (actualPattern.getConstructor() != null) {
constructors.add(actualPattern.getConstructor());
}
} else {
hasVars = true;
}
}
if (allVars) {
for (Pair<? extends List<? extends CorePattern>, Integer> actualRow : actualRows) {
newRows.add(new Pair<>(actualRow.proj1.subList(1, actualRow.proj1.size()), actualRow.proj2));
}
return computeCovering(newRows, rowTail, indices);
}
List<Pair<CoreDefinition, CoreParameter>> consWithParams;
CoreExpression type = pattern.getBinding().getTypeExpr();
if (type != null) type = type.unfoldType();
if (type instanceof CoreSigmaExpression sigmaExpr) {
consWithParams = Collections.singletonList(new Pair<>(null, sigmaExpr.getParameters()));
} else if (type instanceof CoreClassCallExpression classCall) {
consWithParams = Collections.singletonList(new Pair<>(null, classCall.getClassFieldParameters()));
} else {
List<CoreExpression.ConstructorWithDataArguments> constructorsWithArgs = type == null ? null : type.computeMatchedConstructorsWithDataArguments();
if (constructorsWithArgs == null) {
// TODO: We should return null here, but to do this we need to substitute previous patterns in type
consWithParams = new ArrayList<>(constructors.size());
for (CoreDefinition constructor : constructors) {
consWithParams.add(new Pair<>(constructor, constructor.getParameters()));
}
} else {
if (!hasVars) {
for (CoreExpression.ConstructorWithDataArguments cons : constructorsWithArgs) {
if (!constructors.contains(cons.getConstructor())) {
return false;
}
}
}
consWithParams = new ArrayList<>(constructorsWithArgs.size());
for (CoreExpression.ConstructorWithDataArguments cons : constructorsWithArgs) {
consWithParams.add(new Pair<>(cons.getConstructor(), cons.getParameters()));
}
}
}
for (Pair<CoreDefinition, CoreParameter> pair : consWithParams) {
List<CorePattern> newRow = new ArrayList<>();
for (CoreParameter param = pair.proj2; param.hasNext(); param = param.getNext()) {
newRow.add(new ArendPattern(new MyBinding(param.getTypeExpr()), null, Collections.emptyList(), null, null));
}
newRow.addAll(rowTail);
newRows.clear();
for (Pair<? extends List<? extends CorePattern>, Integer> actualRow : actualRows) {
CorePattern actualPattern = actualRow.proj1.get(0);
if (actualPattern.getBinding() != null) {
List<CorePattern> newActualRow = new ArrayList<>();
for (CoreParameter param = pair.proj2; param.hasNext(); param = param.getNext()) {
newActualRow.add(new ArendPattern(new MyBinding(null), null, Collections.emptyList(), null, null));
}
newActualRow.addAll(actualRow.proj1.subList(1, actualRow.proj1.size()));
newRows.add(new Pair<>(newActualRow, actualRow.proj2));
} else if (actualPattern.getConstructor() == pair.proj1) {
List<CorePattern> newActualRow = new ArrayList<>();
newActualRow.addAll(actualPattern.getSubPatterns());
newActualRow.addAll(actualRow.proj1.subList(1, actualRow.proj1.size()));
newRows.add(new Pair<>(newActualRow, actualRow.proj2));
}
}
if (!computeCovering(newRows, newRow, indices)) {
return false;
}
}
return true;
} else {
List<CorePattern> newRow = new ArrayList<>();
newRow.addAll(pattern.getSubPatterns());
newRow.addAll(rowTail);
for (Pair<? extends List<? extends CorePattern>, Integer> actualRow : actualRows) {
CorePattern actualPattern = actualRow.proj1.get(0);
if (actualPattern.getBinding() != null) {
List<CorePattern> newActualRow = new ArrayList<>();
for (CorePattern ignored : pattern.getSubPatterns()) {
newActualRow.add(new ArendPattern(new MyBinding(null), null, Collections.emptyList(), null, null));
}
newActualRow.addAll(actualRow.proj1.subList(1, actualRow.proj1.size()));
newRows.add(new Pair<>(newActualRow, actualRow.proj2));
} else if (actualPattern.getConstructor() == pattern.getConstructor()) {
List<CorePattern> newActualRow = new ArrayList<>();
newActualRow.addAll(actualPattern.getSubPatterns());
newActualRow.addAll(actualRow.proj1.subList(1, actualRow.proj1.size()));
newRows.add(new Pair<>(newActualRow, actualRow.proj2));
}
}
return computeCovering(newRows, newRow, indices);
}
}