private DependentLink reportNoClauses()

in base/src/main/java/org/arend/typechecking/patternmatching/ElimTypechecking.java [531:648]


  private DependentLink reportNoClauses(DependentLink parameters, List<DependentLink> elimParams) {
    if (myErrorReporter == null) return null;
    if (elimParams.isEmpty()) {
      for (int i = 0; i < myNumberOfExternalParameters && parameters.hasNext(); i++) {
        parameters = parameters.getNext();
      }
    }

    if (parameters.hasNext() && !parameters.getNext().hasNext()) {
      DataCallExpression dataCall = parameters.getTypeExpr().cast(DataCallExpression.class);
      if (dataCall != null && dataCall.getDefinition() == Prelude.INTERVAL) {
        myErrorReporter.report(new TypecheckingError("Pattern matching on the interval is not allowed here", mySourceNode));
        return null;
      }
    }

    // If paramSpec[p] is non-null, then it gives a specification for parameter p.
    // We should generate the list of patterns corresponding to the first projection of elements of paramSpec[p].
    // Moreover, for every index i and every parameter p' such that paramSpec[p][i].proj2[p'] is non-null and is equal to con,
    // then this spec applies only if the pattern generated for parameter p is of the form (con p_1 ... p_k).
    Map<DependentLink, List<Pair<ExpressionPattern, Map<DependentLink, Constructor>>>> paramSpec = new HashMap<>();
    Map<DependentLink, List<ConCallExpression>> paramSpec2 = new HashMap<>();
    DependentLink emptyLink = null;
    for (DependentLink param = parameters; param.hasNext(); param = param.getNext()) {
      if (!elimParams.isEmpty() && !elimParams.contains(param)) {
        continue;
      }
      DataCallExpression dataCall = param.getTypeExpr().normalize(NormalizationMode.WHNF).cast(DataCallExpression.class);
      if (dataCall != null) {
        Map<DependentLink, List<Pair<ExpressionPattern, Map<DependentLink, Constructor>>>> newParamSpec = computeParamSpec(param, dataCall, elimParams, paramSpec2, parameters);
        if (newParamSpec == null) {
          return null;
        }
        if (!newParamSpec.isEmpty()) {
          emptyLink = param;
        }
        for (Map.Entry<DependentLink, List<Pair<ExpressionPattern, Map<DependentLink, Constructor>>>> entry : newParamSpec.entrySet()) {
          paramSpec.compute(entry.getKey(), (k,list) -> {
            if (list == null) {
              return entry.getValue();
            }
            List<Pair<ExpressionPattern, Map<DependentLink, Constructor>>> result = new ArrayList<>();
            for (Pair<ExpressionPattern, Map<DependentLink, Constructor>> pair1 : list) {
              for (Pair<ExpressionPattern, Map<DependentLink, Constructor>> pair2 : entry.getValue()) {
                ExpressionPattern pattern = pair1.proj1.intersect(pair2.proj1);
                if (pattern != null) {
                  Map<DependentLink, Constructor> newMap = new HashMap<>();
                  newMap.putAll(pair1.proj2);
                  newMap.putAll(pair2.proj2);
                  result.add(new Pair<>(pattern, newMap));
                }
              }
            }
            return result;
          });
        }
      }
    }

    List<List<ExpressionPattern>> missingClauses = generateMissingClauses(elimParams.isEmpty() ? DependentLink.Helper.toList(parameters) : elimParams, 0, new ExprSubstitution(), paramSpec, paramSpec2);
    for (int i = 0; i < missingClauses.size(); i++) {
      for (int j = i + 1; j < missingClauses.size(); j++) {
        if (ExpressionPattern.compare(missingClauses.get(i), missingClauses.get(j))) {
          missingClauses.remove(j--);
        }
      }
    }

    if (myLevel != null) {
      missingClauses.removeIf(clause -> numberOfIntervals(clause) > myLevel);
    }

    if (missingClauses.isEmpty()) {
      return emptyLink;
    }

    for (List<ExpressionPattern> patterns : missingClauses) {
      Collections.reverse(patterns);
    }

    boolean allVars = missingClauses.size() == 1;
    for (List<ExpressionPattern> patterns : missingClauses) {
      DependentLink param = parameters;
      for (int i = 0; i < patterns.size(); i++, param = param.getNext()) {
        if (!(patterns.get(i) instanceof BindingPattern)) {
          allVars = false;
        }
        if (patterns.get(i) instanceof BindingPattern && !paramSpec.containsKey(param)) {
          ConstructorExpressionPattern newPattern;
          List<ExpressionPattern> subPatterns;
          Expression type = ((BindingPattern) patterns.get(i)).getBinding().getTypeExpr().getUnderlyingExpression();
          if (type instanceof SigmaExpression) {
            subPatterns = new ArrayList<>();
            newPattern = new ConstructorExpressionPattern((SigmaExpression) type, subPatterns);
          } else if (type instanceof ClassCallExpression) {
            subPatterns = new ArrayList<>();
            newPattern = new ConstructorExpressionPattern((ClassCallExpression) type, subPatterns);
          } else {
            continue;
          }

          allVars = false;
          patterns.set(i, newPattern);
          for (DependentLink link = newPattern.getParameters(); link.hasNext(); link = link.getNext()) {
            subPatterns.add(new BindingPattern(link));
          }
        }
      }
    }

    if (allVars) {
      myErrorReporter.report(new CertainTypecheckingError(CertainTypecheckingError.Kind.BODY_REQUIRED, mySourceNode));
      return null;
    }

    myErrorReporter.report(new MissingClausesError(missingClauses, parameters, elimParams, true, mySourceNode));
    return null;
  }