private ConcreteExpression computeTerm()

in meta/src/main/java/org/arend/lib/meta/linear/TermCompiler.java [189:325]


  private ConcreteExpression computeTerm(CoreExpression expression, Map<Integer, Ring> coefficients, Ring[] freeCoef, Set<Integer> vars) {
    CoreExpression expr = expression.getUnderlyingExpression();
    if (expr instanceof CoreAppExpression || expr instanceof CoreFieldCallExpression) {
      CoreFieldCallExpression fieldCall = null;
      CoreExpression arg1 = null;
      CoreExpression arg2 = null;
      if (expr instanceof CoreFieldCallExpression) {
        fieldCall = (CoreFieldCallExpression) expr;
      } else {
        CoreExpression fun = ((CoreAppExpression) expr).getFunction().getUnderlyingExpression();
        if (fun instanceof CoreFieldCallExpression) {
          fieldCall = (CoreFieldCallExpression) fun;
          arg1 = ((CoreAppExpression) expr).getArgument();
        } else if (fun instanceof CoreAppExpression) {
          CoreExpression fun2 = ((CoreAppExpression) fun).getFunction().getUnderlyingExpression();
          if (fun2 instanceof CoreFieldCallExpression) {
            fieldCall = (CoreFieldCallExpression) fun2;
            arg1 = ((CoreAppExpression) fun).getArgument();
            arg2 = ((CoreAppExpression) expr).getArgument();
          }
        }
      }
      if (fieldCall != null) {
        CoreClassField field = fieldCall.getDefinition();
        if (((field == meta.ext.zro || field == meta.ext.ide) && arg1 == null || (field == meta.plus || field == meta.mul) && arg2 != null || field == meta.negative && arg1 != null && arg2 == null) && typechecker.compare(fieldCall.getArgument(), instance, CMP.EQ, marker, false, true, false)) {
          if (field == meta.ext.zro) {
            return factory.ref(meta.zroTerm.getRef());
          } else if (field == meta.ext.ide) {
            freeCoef[0] = freeCoef[0].add(getOne());
            return factory.ref(meta.ideTerm.getRef());
          } else if (field == meta.negative) {
            return computeNegative(arg1, coefficients, freeCoef, vars);
          } else if (field == meta.plus) {
            return computePlus(arg1, arg2, coefficients, freeCoef, vars);
          } else if (field == meta.mul) {
            return computeMul(arg1, arg2, expr, coefficients, freeCoef, vars);
          }
        }
      }
    }
    expr = expr.normalize(NormalizationMode.WHNF);

    if (zroMatcher.match(expr) != null) {
      return factory.ref(meta.zroTerm.getRef());
    }

    List<CoreExpression> addArgs = addMatcher.match(expr);
    if (addArgs != null) {
      return computePlus(addArgs.get(addArgs.size() - 2), addArgs.get(addArgs.size() - 1), coefficients, freeCoef, vars);
    }

    if (ideMatcher.match(expr) != null) {
      freeCoef[0] = freeCoef[0].add(getOne());
      return factory.ref(meta.ideTerm.getRef());
    }

    if (subTermCompiler != null && subTermCompiler.minusMatcher != null) {
      List<CoreExpression> minusArgs = subTermCompiler.minusMatcher.match(expr);
      if (minusArgs != null) {
        return getSubTermCompiler().computeMinus(minusArgs.get(0), minusArgs.get(1), coefficients, freeCoef, vars);
      }
    }

    if (negativeMatcher != null) {
      List<CoreExpression> negativeArgs = negativeMatcher.match(expr);
      if (negativeArgs != null) {
        return computeNegative(negativeArgs.get(0), coefficients, freeCoef, vars);
      }
    }

    CoreExpression expr1 = kind == RingKind.RAT ? expr : null;
    if (ratAlgebraMatcher != null) {
      List<CoreExpression> ratAlgebraArgs = ratAlgebraMatcher.match(expr);
      if (ratAlgebraArgs != null) {
        expr1 = ratAlgebraArgs.get(0).normalize(NormalizationMode.WHNF);
      }
    }
    if (expr1 instanceof CoreConCallExpression conCall) {
      TypedExpression typedExpr = expr1.computeTyped();
      CoreExpression nomExpr = conCall.getDefCallArguments().get(0).normalize(NormalizationMode.WHNF);
      CoreExpression denomExpr = conCall.getDefCallArguments().get(1).normalize(NormalizationMode.WHNF);
      BigInteger nom = getInt(nomExpr);
      BigInteger denom = getInt(denomExpr);
      if (nom != null && denom != null) {
        freeCoef[0] = freeCoef[0].add(BigRational.make(nom, denom));
        return factory.app(factory.ref(meta.coefTerm.getRef()), true, factory.core(typedExpr));
      }
      if (denom != null && denom.equals(BigInteger.ONE) && subTermCompiler != null) {
        Map<Integer, Ring> newCoefficients = new HashMap<>();
        Ring[] newFreeCoef = new Ring[] { IntRing.ZERO };
        ConcreteExpression term = getSubTermCompiler().computeTerm(nomExpr, newCoefficients, newFreeCoef, vars);
        if (term != null) {
          for (Map.Entry<Integer, Ring> entry : newCoefficients.entrySet()) {
            BigRational value = BigRational.makeInt(((IntRing) entry.getValue()).number);
            coefficients.compute(entry.getKey(), (k,v) -> v == null ? value : v.add(value));
          }
          freeCoef[0] = freeCoef[0].add(BigRational.makeInt(((IntRing) newFreeCoef[0]).number));
          return term;
        }
      }
    }

    Pair<Boolean, CoreExpression> pair = checkInt(expr);
    boolean isNeg = pair != null && pair.proj1;
    List<? extends CoreExpression> coefArgs = pair == null ? null : Collections.singletonList(pair.proj2);

    if (coefArgs == null && kind != RingKind.RAT && kind != RingKind.RAT_ALG) {
      coefArgs = natCoefMatcher.match(expr);
    }
    if (coefArgs != null) {
      CoreExpression arg = coefArgs.get(0).normalize(NormalizationMode.WHNF);
      if (arg instanceof CoreIntegerExpression) {
        BigInteger coef = ((CoreIntegerExpression) arg).getBigInteger();
        if (isNeg) coef = coef.negate();
        freeCoef[0] = freeCoef[0].add(new IntRing(coef));
        return factory.app(factory.ref(meta.coefTerm.getRef()), true, factory.number(coef));
      } else if (subTermCompiler != null) {
        Map<Integer, Ring> newCoefficients = new HashMap<>();
        Ring[] newFreeCoef = new Ring[] { getZero() };
        ConcreteExpression term = getSubTermCompiler().computeTerm(arg, newCoefficients, newFreeCoef, vars);
        if (term != null) {
          for (Map.Entry<Integer, Ring> entry : newCoefficients.entrySet()) {
            coefficients.compute(entry.getKey(), (k,v) -> v == null ? (isNeg ? entry.getValue().negate() : entry.getValue()) : isNeg ? v.subtract(entry.getValue()) : v.add(entry.getValue()));
          }
          freeCoef[0] = isNeg ? freeCoef[0].subtract(newFreeCoef[0]) : freeCoef[0].add(newFreeCoef[0]);
          return isNeg ? factory.app(factory.ref(meta.negativeTerm.getRef()), true, term) : term;
        }
      }
    }

    List<CoreExpression> mulArgs = mulMatcher.match(expr);
    if (mulArgs != null) {
      return computeMul(mulArgs.get(mulArgs.size() - 2), mulArgs.get(mulArgs.size() - 1), expr, coefficients, freeCoef, vars);
    }

    return computeVal(expr, coefficients, vars);
  }