in meta/src/main/java/org/arend/lib/meta/linear/LinearSolver.java [68:150]
private Hypothesis<CoreExpression> typeToEquation(CoreExpression type, CoreBinding binding, boolean reportError) {
ConcreteExpression expr = binding == null ? null : factory.ref(binding);
if (expr != null && type instanceof CorePiExpression) {
ConcreteExpression newExpr = expr;
while (type instanceof CorePiExpression) {
List<ConcreteArgument> args = new ArrayList<>();
for (CoreParameter param = ((CorePiExpression) type).getParameters(); param.hasNext(); param = param.getNext()) {
args.add(factory.arg(factory.hole(), param.isExplicit()));
}
newExpr = factory.app(newExpr, args);
type = ((CorePiExpression) type).getCodomain().normalize(NormalizationMode.WHNF);
}
TypedExpression typedExpr = typechecker.typecheck(newExpr, null);
if (typedExpr != null) {
expr = factory.core(typedExpr);
type = typedExpr.getType();
}
}
CoreFunCallExpression eq = type.toEquality();
if (eq != null) {
CoreExpression instance = findInstance(eq.getDefCallArguments().get(0), reportError);
if (instance == null) return null;
return new Hypothesis<>(expr, instance, Equation.Operation.EQUALS, eq.getDefCallArguments().get(1), eq.getDefCallArguments().get(2), BigInteger.ONE);
}
RelationData relationData = RelationData.getRelationData(type.normalize(NormalizationMode.WHNF));
if (relationData == null) {
if (reportError) reportTypeError(type);
return null;
}
if (relationData.defCall instanceof CoreFieldCallExpression fieldCall) {
CoreClassField field = fieldCall.getDefinition();
if (field == ext.equationMeta.less || field == ext.equationMeta.lessOrEquals) {
CoreExpression arg = fieldCall.getArgument();
CoreExpression argType = arg.computeType().normalize(NormalizationMode.WHNF);
if (argType instanceof CoreClassCallExpression classCall && classCall.getDefinition().isSubClassOf(getInstanceClass())) {
return new Hypothesis<>(expr, arg, field == ext.equationMeta.less ? Equation.Operation.LESS : Equation.Operation.LESS_OR_EQUALS, relationData.leftExpr, relationData.rightExpr, BigInteger.ONE);
} else {
if (reportError) errorReporter.report(new TypeError(typechecker.getExpressionPrettifier(), "", argType, marker) {
@Override
public LineDoc getShortHeaderDoc(PrettyPrinterConfig ppConfig) {
return DocFactory.hList(DocFactory.text("The type of the equation should be "), DocFactory.refDoc(getInstanceClass().getRef()));
}
});
return null;
}
}
if (reportError) reportTypeError(type);
return null;
}
if (relationData.defCall.getDefinition() == ext.equationMeta.linearOrederLeq) {
return new Hypothesis<>(expr, relationData.defCall.getDefCallArguments().get(0), Equation.Operation.LESS_OR_EQUALS, relationData.leftExpr, relationData.rightExpr, BigInteger.ONE);
}
if (relationData.defCall.getDefinition() == ext.equationMeta.addGroupLess) {
CoreExpression instance = relationData.defCall.getDefCallArguments().get(0);
TypedExpression typedInstance = instance.computeTyped();
CoreExpression instanceType = typedInstance.getType().normalize(NormalizationMode.WHNF);
if (!(instanceType instanceof CoreClassCallExpression classCall && classCall.getDefinition().isSubClassOf(getInstanceClass()))) {
instance = findInstance(instanceType instanceof CoreClassCallExpression classCall ? Utils.getClassifyingExpression(classCall, typedInstance) : null, reportError);
if (instance == null) return null;
}
return new Hypothesis<>(expr, instance, Equation.Operation.LESS, relationData.leftExpr, relationData.rightExpr, BigInteger.ONE);
}
var pair = instanceCache.computeIfAbsent(relationData.defCall.getDefinition(), def -> {
DefImplInstanceSearchParameters parameters = new DefImplInstanceSearchParameters(def) {
@Override
protected List<CoreClassField> getRelationFields(CoreClassDefinition classDef) {
return classDef.isSubClassOf(getInstanceClass()) ? Arrays.asList(ext.equationMeta.less, ext.equationMeta.lessOrEquals) : Collections.emptyList();
}
};
TypedExpression instance = typechecker.findInstance(parameters, null, null, marker);
return instance == null ? null : new Pair<>(instance, parameters.getRelationField());
});
if (pair == null) {
if (reportError) reportTypeError(type);
return null;
}
return new Hypothesis<>(expr, pair.proj1.getExpression(), pair.proj2 == ext.equationMeta.less ? Equation.Operation.LESS : Equation.Operation.LESS_OR_EQUALS, relationData.leftExpr, relationData.rightExpr, BigInteger.ONE);
}