private BasePiTree make()

in meta/src/main/java/org/arend/lib/meta/pi_tree/PiTreeMaker.java [46:133]


  private BasePiTree make(boolean isRoot, CoreParameter parameter, CoreExpression expr) {
    List<CoreParameter> params = new ArrayList<>();
    expr = expr.normalize(NormalizationMode.WHNF);
    CoreExpression codomain = expr;
    int k = lamParams.size();
    List<Integer> indices1 = new ArrayList<>();
    loop:
    while (codomain instanceof CorePiExpression) {
      CorePiExpression piExpr = (CorePiExpression) codomain;
      Set<? extends CoreBinding> codomainFreeVars = piExpr.getCodomain().findFreeBindings();
      for (CoreParameter param = piExpr.getParameters(); param.hasNext(); param = param.getNext(), k++) {
        ArendRef lamRef = factory.local("x" + (k + 1));
        lamParams.add(factory.param(lamRef));
        substitution.add(new SubstitutionPair(param.getBinding(), factory.ref(lamRef)));

        if (codomainFreeVars.contains(param.getBinding())) {
          if (isRoot && param.getTypeExpr().findFreeBindings(substBindings) == null) {
            indices1.add(k);
          } else {
            break loop;
          }
        }
      }

      for (CoreParameter param = piExpr.getParameters(); param.hasNext(); param = param.getNext()) {
        params.add(param);
      }
      codomain = piExpr.getCodomain();
    }

    Set<? extends CoreBinding> freeVars = expr.findFreeBindings();
    List<Integer> indices = new ArrayList<>(freeVars.size());
    for (int i = 0; i < substitution.size(); i++) {
      if (freeVars.contains(substitution.get(i).binding)) {
        indices.add(i);
      }
    }
    indices.addAll(indices1);

    ConcreteExpression concrete;
    boolean useLet;
    if (indices.isEmpty()) {
      if (!isRoot) {
        params.clear();
        codomain = expr;
      }
      concrete = factory.core(codomain.computeTyped());
      useLet = !(expr instanceof CoreReferenceExpression);
    } else {
      List<ConcreteParameter> redLamParams;
      List<SubstitutionPair> redSubstitution;
      if (indices.size() == substitution.size()) {
        redLamParams = lamParams;
        redSubstitution = substitution;
      } else {
        redLamParams = new ArrayList<>(indices.size());
        redSubstitution = new ArrayList<>(indices.size());
        for (Integer index : indices) {
          redLamParams.add(lamParams.get(index));
          redSubstitution.add(substitution.get(index));
        }
      }

      TypedExpression result = typechecker.typecheck(factory.lam(redLamParams, factory.meta("ext_sigma_pi_param", new SubstitutionMeta(codomain, redSubstitution))), null);
      if (result == null) return null;
      concrete = factory.core(result);
      useLet = !(result.getExpression() instanceof CoreReferenceExpression);
    }

    ConcreteExpression altHead;
    if (useLet) {
      ArendRef letRef = factory.local("T" + index++);
      ConcreteLetClause clause = factory.letClause(letRef, Collections.emptyList(), null, concrete);
      clauses.add(clause);
      clauseMap.put(letRef, clause);
      altHead = factory.ref(letRef);
    } else {
      altHead = concrete;
    }

    List<PiTreeNode> subtrees = new ArrayList<>(params.size());
    for (CoreParameter param : params) {
      PiTreeNode subtree = (PiTreeNode) make(false, param, param.getTypeExpr());
      if (subtree == null) return null;
      subtrees.add(subtree);
    }
    return isRoot ? new PiTreeRoot(concrete, altHead, indices, subtrees, indices.size() == indices1.size()) : new PiTreeNode(parameter, concrete, altHead, indices, subtrees);
  }