in meta/src/main/java/org/arend/lib/meta/equation/MonoidSolver.java [543:583]
private boolean typeToRule(TypedExpression typed, CoreBinding binding, boolean alwaysForward, List<RuleExt> rules) {
if (binding == null && typed == null) {
return false;
}
CoreExpression type = binding != null ? binding.getTypeExpr() : typed.getType();
CoreFunCallExpression eq = Utils.toEquality(type, null, null);
if (eq == null) {
CoreExpression typeNorm = type.normalize(NormalizationMode.WHNF);
if (!(typeNorm instanceof CoreClassCallExpression classCall)) {
return false;
}
boolean isLDiv = classCall.getDefinition().isSubClassOf(meta.ldiv);
boolean isRDiv = classCall.getDefinition().isSubClassOf(meta.rdiv);
if (!isLDiv && !isRDiv) {
return false;
}
List<ConcreteExpression> args = singletonList(binding != null ? factory.ref(binding) : factory.core(null, typed));
return (!isLDiv || typeToRule(typechecker.typecheck(factory.app(factory.ref(meta.ldiv.getPersonalFields().get(0).getRef()), false, args), null), null, true, rules)) &&
(!isRDiv || typeToRule(typechecker.typecheck(factory.app(factory.ref(meta.rdiv.getPersonalFields().get(0).getRef()), false, args), null), null, true, rules));
}
if (!typechecker.compare(eq.getDefCallArguments().get(0), getValuesType(), CMP.EQ, refExpr, false, true, false)) {
return false;
}
List<Integer> lhs = new ArrayList<>();
List<Integer> rhs = new ArrayList<>();
ConcreteExpression lhsTerm = computeTerm(eq.getDefCallArguments().get(1), lhs);
ConcreteExpression rhsTerm = computeTerm(eq.getDefCallArguments().get(2), rhs);
if (binding == null) {
rules.add(new RuleExt(typed, null, Direction.FORWARD, lhs, rhs, lhsTerm, rhsTerm));
} else {
Direction direction = alwaysForward || lhs.size() > rhs.size() ? Direction.FORWARD : Direction.UNKNOWN;
RuleExt rule = new RuleExt(typed, binding, direction, lhs, rhs, lhsTerm, rhsTerm);
if (!alwaysForward && lhs.size() < rhs.size()) {
rule.setBackward();
}
rules.add(rule);
}
return true;
}