in base/src/main/java/org/arend/core/expr/visitor/CompareVisitor.java [234:386]
public boolean normalizedCompare(Expression expr1, Expression expr2, Expression type, boolean useType) {
Expression stuck1 = expr1.getStuckExpression();
Expression stuck2 = expr2.getStuckExpression();
if (stuck1 != null) stuck1 = stuck1.getUnderlyingExpression();
if (stuck2 != null) stuck2 = stuck2.getUnderlyingExpression();
if (stuck1 instanceof ErrorExpression && !(stuck2 instanceof InferenceReferenceExpression) ||
stuck2 instanceof ErrorExpression && !(stuck1 instanceof InferenceReferenceExpression)) {
return true;
}
if ((stuck1 instanceof InferenceReferenceExpression || stuck2 instanceof InferenceReferenceExpression) && myAllowEquations) {
InferenceVariable var1 = stuck1 instanceof InferenceReferenceExpression ? ((InferenceReferenceExpression) stuck1).getVariable() : null;
InferenceVariable var2 = stuck2 instanceof InferenceReferenceExpression ? ((InferenceReferenceExpression) stuck2).getVariable() : null;
if (var1 instanceof MetaInferenceVariable || var2 instanceof MetaInferenceVariable || var1 != null && var2 != null && !(expr1 instanceof DefCallExpression && !(expr1 instanceof FieldCallExpression) && expr2 instanceof DefCallExpression && ((DefCallExpression) expr1).getDefinition() == ((DefCallExpression) expr2).getDefinition())) {
if (!myEquations.addEquation(expr1, substitute(expr2), type, myCMP, (var1 != null ? var1 : var2).getSourceNode(), var1, var2)) {
initResult(expr1, expr2);
return false;
}
return true;
}
}
InferenceVariable stuckVar1 = expr1.getInferenceVariable(true);
InferenceVariable stuckVar2 = expr2.getInferenceVariable(true);
if (stuckVar1 != null || stuckVar2 != null) {
if (!(myNormalCompare && myEquations.addEquation(expr1, substitute(expr2), type, myCMP, stuckVar1 != null ? stuckVar1.getSourceNode() : stuckVar2.getSourceNode(), stuckVar1, stuckVar2))) {
initResult(expr1, expr2);
return false;
}
return true;
}
if (expr1 instanceof FieldCallExpression && ((FieldCallExpression) expr1).getDefinition().isProperty() && expr2 instanceof FieldCallExpression && ((FieldCallExpression) expr2).getDefinition().isProperty()) {
return true;
}
boolean onlySolveVars = myOnlySolveVars;
if (myNormalCompare && !myOnlySolveVars && expr1.isBoxed() && expr2.isBoxed() && (type != null || compare(expr1.getType(), expr2.getType(), Type.OMEGA, true))) {
myOnlySolveVars = true;
}
if (useType && myNormalCompare && !myOnlySolveVars) {
Expression normType = type == null ? null : type.getUnderlyingExpression();
boolean allowProp = normType instanceof DataCallExpression && ((DataCallExpression) normType).getDefinition().getConstructors().isEmpty() || !expr1.canBeConstructor() && !expr2.canBeConstructor();
if (normType instanceof SigmaExpression && !((SigmaExpression) normType).getParameters().hasNext() ||
normType instanceof ClassCallExpression && (((ClassCallExpression) normType).getNumberOfNotImplementedFields() == 0 || Boolean.TRUE.equals(ConstructorExpressionPattern.isArrayEmpty(normType)) && ((ClassCallExpression) normType).isImplemented(Prelude.ARRAY_ELEMENTS_TYPE)) ||
allowProp && normType != null && Sort.PROP.equals(normType.getSortOfType())) {
myOnlySolveVars = true;
}
if (!myOnlySolveVars && (normType == null || normType.getStuckInferenceVariable() != null || normType instanceof ClassCallExpression)) {
Expression type1 = expr1.getType();
if (type1 != null && type1.getStuckInferenceVariable() != null) {
type1 = null;
}
if (type1 != null) {
type1 = myNormalize ? type1.normalize(NormalizationMode.WHNF) : type1;
if (allowProp) {
Sort sort1 = type1.getSortOfType();
if (sort1 != null && sort1.isProp() && !type1.isInstance(ClassCallExpression.class)) {
myOnlySolveVars = true;
}
}
}
if (!myOnlySolveVars && type1 != null) {
Expression type2 = expr2.getType();
if (type2 != null && type2.getStuckInferenceVariable() != null) {
type2 = null;
}
if (type2 != null) {
type2 = myNormalize ? type2.normalize(NormalizationMode.WHNF) : type2;
if (allowProp) {
Sort sort2 = type2.getSortOfType();
if (sort2 != null && sort2.isProp() && !type2.isInstance(ClassCallExpression.class)) {
myOnlySolveVars = true;
}
}
}
if (!myOnlySolveVars && type2 != null) {
ClassCallExpression classCall1 = type1.cast(ClassCallExpression.class);
ClassCallExpression classCall2 = type2.cast(ClassCallExpression.class);
if (classCall1 != null && classCall2 != null && compareClassInstances(expr1, classCall1, expr2, classCall2, normType)) {
return true;
}
}
}
}
}
CMP origCMP = myCMP;
if (!myOnlySolveVars && myAllowEquations) {
Boolean dataAndApp = checkDefCallAndApp(expr1, expr2, true);
if (dataAndApp != null) {
if (!dataAndApp) initResult(expr1, expr2);
return dataAndApp;
}
dataAndApp = checkDefCallAndApp(expr2, expr1, false);
if (dataAndApp != null) {
if (!dataAndApp) initResult(expr1, expr2);
return dataAndApp;
}
}
if (!myOnlySolveVars && myNormalCompare) {
Boolean result = expr1 instanceof AppExpression && (stuck2 == null || stuck2.getInferenceVariable() == null) ? checkApp((AppExpression) expr1, expr2, true) : null;
if (result != null) {
if (!result) initResult(expr1, expr2);
return result;
}
result = expr2 instanceof AppExpression && (stuck1 == null || stuck1.getInferenceVariable() == null) ? checkApp((AppExpression) expr2, expr1, false) : null;
if (result != null) {
if (!result) initResult(expr1, expr2);
return result;
}
}
if (expr1 instanceof ErrorExpression) {
return true;
}
if (!(expr1 instanceof UniverseExpression || expr1 instanceof PiExpression || expr1 instanceof ClassCallExpression || expr1 instanceof DataCallExpression || expr1 instanceof AppExpression || expr1 instanceof SigmaExpression || expr1 instanceof LamExpression)) {
myCMP = CMP.EQ;
}
boolean ok;
if (expr2 instanceof ErrorExpression) {
return true;
}
if (expr2 instanceof PathExpression && !(expr1 instanceof PathExpression)) {
ok = comparePathEta((PathExpression) expr2, expr1, type, false);
} else if (expr2 instanceof LamExpression) {
ok = visitLam((LamExpression) expr2, expr1, type, false);
} else if (expr2 instanceof TupleExpression) {
ok = visitTuple((TupleExpression) expr2, expr1, false);
} else if (expr2 instanceof TypeConstructorExpression) {
ok = visitTypeConstructor((TypeConstructorExpression) expr2, expr1, false);
} else if (expr2 instanceof FunCallExpression && ((FunCallExpression) expr2).getDefinition() == Prelude.ARRAY_INDEX && !(expr1 instanceof FunCallExpression && ((FunCallExpression) expr1).getDefinition() == Prelude.ARRAY_INDEX)) {
ok = compareConstArray((FunCallExpression) expr2, expr1, type, false);
} else {
ok = expr1.accept(this, expr2, type);
}
if (!ok && !myOnlySolveVars && myAllowEquations) {
InferenceVariable variable1 = stuck1 == null ? null : stuck1.getInferenceVariable();
InferenceVariable variable2 = stuck2 == null ? null : stuck2.getInferenceVariable();
ok = (variable1 != null || variable2 != null) && myNormalCompare && myEquations.addEquation(expr1, substitute(expr2), type, origCMP, variable1 != null ? variable1.getSourceNode() : variable2.getSourceNode(), variable1, variable2);
}
if (myOnlySolveVars) {
ok = true;
}
myOnlySolveVars = onlySolveVars;
return ok;
}