in meta/src/main/java/org/arend/lib/meta/ExistsMeta.java [141:276]
private ConcreteExpression processParameters(List<? extends ConcreteParameter> parameters, int abstracted, ExpressionTypechecker typechecker) {
if (parameters.isEmpty()) {
return getResult();
}
ConcreteParameter param = parameters.get(0);
ConcreteExpression cType = Objects.requireNonNull(param.getType());
ConcreteExpression aType;
List<ConcreteParameter> varParams;
TypedExpression typedType;
CoreExpression type = null;
if (cType instanceof ConcreteHoleExpression) {
typedType = typechecker.typecheckType(cType);
if (typedType == null) return null;
aType = factory.core(typedType);
} else {
CoreExpression[] types = new CoreExpression[] { null };
Pair<AbstractedExpression, TypedExpression> pair = typechecker.typecheckAbstracted(cType, null, abstracted, typed -> {
typed = typed.normalizeType();
types[0] = typed.getType();
if (!(types[0] instanceof CoreUniverseExpression || types[0] instanceof CorePiExpression || types[0] instanceof CoreClassCallExpression && ((CoreClassCallExpression) types[0]).getDefinition() == ext.prelude.getDArray())) {
typed = typechecker.coerceToType(typed, cType);
if (typed == null) {
if (!types[0].reportIfError(typechecker.getErrorReporter(), cType)) {
typechecker.getErrorReporter().report(new TypeMismatchError(DocFactory.text("\\Type"), types[0], cType));
}
return null;
}
}
return typed;
});
if (pair == null) return null;
aType = factory.withData(cType.getData()).abstracted(pair.proj1, new ArrayList<>(arguments));
typedType = pair.proj2;
type = types[0];
}
List<ArendRef> refs;
if (type instanceof CorePiExpression) {
List<CoreParameter> piParams = new ArrayList<>();
CoreExpression cod = type.getPiParameters(piParams);
if (!(cod instanceof CoreUniverseExpression)) {
typechecker.getErrorReporter().report(new TypeMismatchError(DocFactory.text("_ -> \\Type"), type, cType));
return null;
}
refs = null;
List<ArendRef> sigmaRefs = new ArrayList<>(param.getRefList().size());
List<? extends ArendRef> paramRefList = param.getRefList();
if (param.getRefList().isEmpty() || param.getRefList().size() == 1 && param.getRefList().get(0) == null) {
paramRefList = new ArrayList<>(piParams.size());
for (CoreParameter ignored : piParams) {
paramRefList.add(null);
}
}
int i = 0;
for (ArendRef ref : paramRefList) {
sigmaRefs.add(ref != null ? ref : factory.local(ext.renamerFactory.getNameFromType(piParams.get(i % piParams.size()).getTypeExpr(), null)));
i++;
}
if (sigmaRefs.size() % piParams.size() != 0) {
typechecker.getErrorReporter().report(new TypecheckingError("Expected (" + piParams.size() + " * n) parameters", param));
return null;
}
varParams = new ArrayList<>(piParams.size());
int j = 0;
for (CoreParameter piParam : piParams) {
List<ArendRef> curRef = new ArrayList<>();
for (i = j; i < sigmaRefs.size(); i += piParams.size()) {
curRef.add(sigmaRefs.get(i));
}
ConcreteParameter varParam = produceParam(param.isExplicit(), curRef, factory.withData(cType.getData()).core(piParam.getTypedType()), null);
sigmaParams.add(varParam);
varParams.add(varParam);
j++;
}
i = 0;
while (i < sigmaRefs.size()) {
List<ConcreteArgument> args = new ArrayList<>(piParams.size());
for (CoreParameter piParam : piParams) {
args.add(factory.arg(factory.ref(sigmaRefs.get(i++)), piParam.isExplicit()));
}
sigmaParams.add(produceParam(true, null, factory.app(aType, args), null));
}
j = 0;
for (CoreParameter ignored : piParams) {
for (i = j; i < paramRefList.size(); i += piParams.size()) {
ArendRef ref = paramRefList.get(i);
arguments.add(ref == null ? null : factory.ref(ref));
}
j++;
}
} else if (type instanceof CoreClassCallExpression && ((CoreClassCallExpression) type).getDefinition() == ext.prelude.getDArray()) {
refs = new ArrayList<>(param.getRefList().size());
for (ArendRef ignored : param.getRefList()) {
refs.add(factory.local("j" + (arrayIndex == 0 ? "" : arrayIndex)));
arrayIndex++;
}
ConcreteParameter varParam = produceParam(param.isExplicit(), refs, factory.app(factory.ref(ext.prelude.getFin().getRef()), true, Collections.singletonList(factory.app(factory.ref(ext.prelude.getArrayLength().getRef()), false, Collections.singletonList(aType)))), param.getData());
varParams = Collections.singletonList(varParam);
sigmaParams.add(varParam);
for (ArendRef ref : refs) {
arguments.add(factory.ref(ref));
}
} else {
refs = null;
varParams = Collections.singletonList(factory.withData(param.getData()).param(param.isExplicit(), param.getRefList(), factory.withData(cType.getData()).core(typedType)));
sigmaParams.add(produceParam(param.isExplicit(), param.getRefList(), aType, null));
for (ArendRef ref : param.getRefList()) {
arguments.add(ref == null ? null : factory.ref(ref));
}
}
if (parameters.size() == 1) {
return getResult();
}
return typechecker.withFreeBindings(new FreeBindingsModifier().addParams(varParams), tc -> {
List<? extends ConcreteParameter> newParams = parameters.subList(1, parameters.size());
int newAbstracted = abstracted + param.getNumberOfParameters();
if (refs == null) {
return processParameters(newParams, newAbstracted, tc);
}
List<Pair<ArendRef, CoreBinding>> list = new ArrayList<>(refs.size());
for (int i = 0; i < refs.size(); i++) {
TypedExpression result = tc.typecheck(factory.app(factory.ref(ext.prelude.getArrayIndex().getRef()), true, Arrays.asList(factory.withData(cType.getData()).core(typedType), factory.ref(refs.get(i)))), null);
if (result == null) return null;
ArendRef ref = param.getRefList().get(i);
list.add(new Pair<>(ref, result.makeEvaluatingBinding(ref != null ? ref.getRefName() : ext.renamerFactory.getNameFromType(result.getType(), null))));
}
return tc.withFreeBindings(new FreeBindingsModifier().addRef(list), tc2 -> processParameters(newParams, newAbstracted, tc2));
});
}