in meta/src/main/java/org/arend/lib/meta/cong/CongVisitor.java [240:284]
public Result visitClassCall(@NotNull CoreClassCallExpression expr, ParamType param) {
CoreExpression otherExpr = param.other.getUnderlyingExpression();
if (!(otherExpr instanceof CoreClassCallExpression)) {
return visit(expr, param);
}
CoreClassCallExpression other = (CoreClassCallExpression) otherExpr;
if (expr.getDefinition() != other.getDefinition() || expr.getImplementations().size() != other.getImplementations().size()) {
return visit(expr, param);
}
List<ConcreteClassElement> args = new ArrayList<>();
boolean abstracted = false;
Set<CoreClassField> fieldsToCheck = new HashSet<>();
for (Map.Entry<? extends CoreClassField, ? extends CoreExpression> entry : expr.getImplementations()) {
if (entry.getKey().isProperty()) continue;
CoreExpression otherImpl = other.getAbsImplementationHere(entry.getKey());
if (otherImpl == null) {
return visit(expr, param);
}
Result arg = entry.getValue().accept(this, new ParamType(() -> new Result(null), otherImpl));
if (arg != null) {
if (arg.expression != null) {
abstracted = true;
fieldsToCheck.add(entry.getKey());
}
args.add(factory.implementation(entry.getKey().getRef(), arg.getExpression(entry.getValue(), factory)));
}
}
if (!fieldsToCheck.isEmpty()) {
boolean check = false;
for (Map.Entry<? extends CoreClassField, ? extends CoreExpression> entry : expr.getImplementations()) {
if (!check) {
check = true;
continue;
}
if (entry.getKey().getResultType().processSubexpression(subexpr -> subexpr instanceof CoreFieldCallExpression && fieldsToCheck.contains(((CoreFieldCallExpression) subexpr).getDefinition()) ? CoreExpression.FindAction.STOP : CoreExpression.FindAction.CONTINUE)) {
return null;
}
}
}
return new Result(abstracted ? factory.classExt(factory.ref(expr.getDefinition().getRef()), args) : null);
}