in base/src/main/java/org/arend/typechecking/doubleChecker/CoreDefinitionChecker.java [73:195]
private boolean check(FunctionDefinition definition) {
Body body = definition.getReallyActualBody();
boolean checkType = true;
if (body instanceof NewExpression && ((NewExpression) body).getRenewExpression() == null && definition.getResultType() instanceof ClassCallExpression typeClassCall && definition.getResultTypeLevel() == null) {
Map<ClassField, Expression> newImpls = new LinkedHashMap<>();
ClassCallExpression bodyClassCall = ((NewExpression) body).getClassCall();
ClassCallExpression newClassCall = new ClassCallExpression(bodyClassCall.getDefinition(), typeClassCall.getLevels(), newImpls, Sort.PROP, UniverseKind.NO_UNIVERSES);
Expression newThisBinding = new ReferenceExpression(newClassCall.getThisBinding());
boolean ok = true;
for (ClassField field : typeClassCall.getDefinition().getNotImplementedFields()) {
Expression typeImpl = typeClassCall.getAbsImplementationHere(field);
Expression bodyImpl = bodyClassCall.getAbsImplementationHere(field);
if (typeImpl != null && bodyImpl != null) {
ok = false;
break;
}
if (typeImpl != null || bodyImpl != null) {
newImpls.put(field, typeImpl != null ? typeImpl.subst(typeClassCall.getThisBinding(), newThisBinding) : bodyImpl.subst(bodyClassCall.getThisBinding(), newThisBinding));
}
}
for (ClassField field : typeClassCall.getDefinition().getImplementedFields()) {
Expression bodyImpl = bodyClassCall.getAbsImplementationHere(field);
if (bodyImpl != null) {
newImpls.put(field, bodyImpl.subst(bodyClassCall.getThisBinding(), newThisBinding));
}
}
if (ok) {
checkType = false;
body = new NewExpression(null, newClassCall);
}
}
Expression typeType = checkType ? definition.getResultType().accept(myChecker, Type.OMEGA) : null;
Integer level = definition.getResultTypeLevel() == null ? null : myChecker.checkLevelProof(definition.getResultTypeLevel(), definition.getResultType());
if (definition.getKind() == CoreFunctionDefinition.Kind.LEMMA && (level == null || level != -1)) {
if (!DefinitionTypechecker.isBoxed(definition)) {
DefCallExpression resultDefCall = definition.getResultType().cast(DefCallExpression.class);
if (resultDefCall == null || !Objects.equals(resultDefCall.getUseLevel(), -1)) {
Sort sort = typeType == null ? definition.getResultType().getSortOfType() : typeType.toSort();
if (sort == null) {
errorReporter.report(CoreErrorWrapper.make(new TypecheckingError("Cannot infer the sort of the type", null), definition.getResultType()));
return false;
}
if (!sort.isProp()) {
errorReporter.report(CoreErrorWrapper.make(new TypeMismatchError(new UniverseExpression(Sort.PROP), new UniverseExpression(sort), null), definition.getResultType()));
return false;
}
}
}
}
if (definition.isAxiom()) {
if (body != null) {
errorReporter.report(new CertainTypecheckingError(CertainTypecheckingError.Kind.AXIOM_WITH_BODY, null));
return false;
} else {
return true;
}
}
if (body instanceof Expression) {
if (body instanceof CaseExpression) {
myChecker.checkCase((CaseExpression) body, definition.getResultType(), level);
} else {
((Expression) body).accept(myChecker, checkType ? definition.getResultType() : null);
}
return true;
}
ElimBody elimBody;
if (body instanceof IntervalElim intervalElim) {
if (intervalElim.getCases().isEmpty()) {
errorReporter.report(new TypecheckingError("Empty IntervalElim", null));
return false;
}
int offset = intervalElim.getOffset();
DependentLink link = definition.getParameters();
for (int i = 0; i < offset && link.hasNext(); i++) {
link = link.getNext();
}
for (IntervalElim.CasePair ignored : intervalElim.getCases()) {
if (!link.hasNext()) {
errorReporter.report(new TypecheckingError("Interval elim has too many parameters", null));
return false;
}
DataCallExpression dataCall = link.getTypeExpr().normalize(NormalizationMode.WHNF).cast(DataCallExpression.class);
if (!(dataCall != null && dataCall.getDefinition() == Prelude.INTERVAL)) {
errorReporter.report(new TypeMismatchError(DataCallExpression.make(Prelude.INTERVAL, Levels.EMPTY, Collections.emptyList()), link.getTypeExpr(), null));
return false;
}
link = link.getNext();
}
// TODO[double_check]: Check interval conditions
if (intervalElim.getOtherwise() == null) {
errorReporter.report(new TypecheckingError("Missing non-interval clauses", null));
return false;
}
elimBody = intervalElim.getOtherwise();
} else if (body instanceof ElimBody) {
elimBody = (ElimBody) body;
} else if (body == null) {
ClassCallExpression classCall = definition.getResultType().normalize(NormalizationMode.WHNF).cast(ClassCallExpression.class);
if (classCall == null) {
errorReporter.report(new TypecheckingError("Missing a body", null));
return false;
}
myChecker.checkCocoverage(classCall);
return true;
} else {
throw new IllegalStateException();
}
myChecker.checkElimBody(definition, elimBody, definition.getParameters(), definition.getResultType(), level, null, definition.isSFunc(), PatternTypechecking.Mode.FUNCTION);
return true;
}