in base/src/main/java/org/arend/typechecking/patternmatching/ElimTypechecking.java [198:326]
public Body typecheckElim(List<? extends ElimClause<ExpressionPattern>> clauses, DependentLink parameters, List<DependentLink> elimParams) {
myOK = true;
myUnusedClauses = new LinkedHashSet<>();
for (int i = 0; i < clauses.size(); i++) {
myUnusedClauses.add(i);
}
List<ElimClause<ExpressionPattern>> intervalClauses;
List<ExtElimClause> nonIntervalClauses = new ArrayList<>();
if (myAllowInterval && myMode.allowInterval()) {
intervalClauses = new ArrayList<>();
Concrete.SourceNode errorClause = null;
for (int i = 0; i < clauses.size(); i++) {
ElimClause<ExpressionPattern> clause = clauses.get(i);
boolean hasNonIntervals = false;
int intervals = 0;
for (Pattern pattern : clause.getPatterns()) {
if (pattern instanceof BindingPattern) {
continue;
}
if (pattern instanceof ConstructorPattern) {
Definition constructor = pattern.getDefinition();
if (constructor == Prelude.LEFT || constructor == Prelude.RIGHT) {
intervals++;
continue;
}
}
hasNonIntervals = true;
break;
}
if (hasNonIntervals || intervals == 0) {
nonIntervalClauses.add(new ExtElimClause(clause.getPatterns(), clause.getExpression(), i));
if (!intervalClauses.isEmpty() && errorClause == null && myErrorReporter != null) {
errorClause = getClause(i, null);
}
} else {
if (intervals > 1) {
if (myErrorReporter != null) myErrorReporter.report(new TypecheckingError("Only a single interval pattern per row is allowed", getClause(i, null)));
myUnusedClauses.remove(i);
} else {
intervalClauses.add(clause);
}
clauses.remove(i--);
}
}
if (errorClause != null) {
myErrorReporter.report(new TypecheckingError("Non-interval clauses must be placed before the interval ones", errorClause));
}
} else {
intervalClauses = Collections.emptyList();
for (int i = 0; i < clauses.size(); i++) {
nonIntervalClauses.add(new ExtElimClause(clauses.get(i).getPatterns(), clauses.get(i).getExpression(), i));
}
}
List<IntervalElim.CasePair> cases = intervalClauses.isEmpty() ? null : clausesToIntervalElim(intervalClauses, nonIntervalClauses.size(), parameters);
if (cases != null) {
int i = 0;
for (; i < cases.size(); i++) {
if (cases.get(i).proj1 != null || cases.get(i).proj2 != null) {
break;
}
}
cases = cases.subList(i, cases.size());
for (int k = 0; k < nonIntervalClauses.size(); k++) {
for (int j = i; j < nonIntervalClauses.get(k).getPatterns().size(); j++) {
if (!(nonIntervalClauses.get(k).getPatterns().get(j) instanceof BindingPattern) && myErrorReporter != null) {
myErrorReporter.report(new TypecheckingError("A pattern matching on a data type is allowed only before the pattern matching on the interval", getClause(k, null)));
myOK = false;
}
}
}
}
ElimTree elimTree;
if (nonIntervalClauses.isEmpty()) {
DependentLink emptyLink = null;
if (elimParams.isEmpty()) {
for (DependentLink link = parameters; link.hasNext(); link = link.getNext()) {
link = link.getNextTyped(null);
List<ConCallExpression> conCalls = getMatchedConstructors(TypeConstructorExpression.unfoldType(link.getTypeExpr()));
if (conCalls != null && conCalls.isEmpty()) {
emptyLink = link;
break;
}
}
} else {
for (DependentLink link : elimParams) {
List<ConCallExpression> conCalls = getMatchedConstructors(TypeConstructorExpression.unfoldType(link.getTypeExpr()));
if (conCalls != null && conCalls.isEmpty()) {
emptyLink = link;
break;
}
}
}
if (emptyLink == null && myMode.checkCoverage()) {
if (!reportMissingClauses(null, parameters, elimParams)) {
emptyLink = reportNoClauses(parameters, elimParams);
}
}
if (emptyLink != null) {
int index = 0;
for (DependentLink link = parameters; link != emptyLink; link = link.getNext()) {
index++;
}
elimTree = new BranchElimTree(index, false);
} else {
elimTree = null;
}
} else {
myContext = new Stack<>();
myCoreClauses = nonIntervalClauses;
elimTree = clausesToElimTree(nonIntervalClauses, 0, 0);
reportMissingClauses(elimTree, parameters, elimParams);
if (myOK && myErrorReporter != null) {
for (Integer clauseIndex : myUnusedClauses) {
myErrorReporter.report(new RedundantClauseError(getClause(clauseIndex, null)));
}
}
}
ElimBody elimBody = elimTree == null ? null : new ElimBody(removeExpressionsFromPatterns(clauses), elimTree);
return cases == null ? elimBody : new IntervalElim(DependentLink.Helper.size(parameters), cases, elimBody);
}