use of org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceContext in project legend-pure by finos.
the class TypeInference method storeInferredTypeParametersInFunctionExpression.
public static void storeInferredTypeParametersInFunctionExpression(FunctionExpression functionExpression, ProcessorState state, ProcessorSupport processorSupport, Function<?> foundFunction) throws PureCompilationException {
// Store the inferred params in the FunctionExpression
if (!(foundFunction instanceof QualifiedProperty)) {
TypeInferenceContext typeInferenceContext = state.getTypeInferenceContext();
FunctionType functionType = (FunctionType) processorSupport.function_getFunctionType(foundFunction);
functionType._typeParameters().forEach(typeParameter -> {
CoreInstance value = typeInferenceContext.getTypeParameterValue(typeParameter._name());
if (value != null) {
functionExpression._resolvedTypeParametersAdd((GenericType) value);
} else if (typeInferenceContext.getParent() == null) {
StringBuilder builder = new StringBuilder("The type parameter ").append(typeParameter._name()).append(" was not resolved (").append(foundFunction._functionName()).append(" / ");
org.finos.legend.pure.m3.navigation.function.FunctionType.print(builder, functionType, processorSupport).append(")!");
throw new PureCompilationException(functionExpression.getSourceInformation(), builder.toString());
}
});
functionType._multiplicityParameters().forEach(multiplicityParameter -> {
String parameterName = multiplicityParameter._valuesCoreInstance().getFirst().getName();
CoreInstance value = typeInferenceContext.getMultiplicityParameterValue(parameterName);
if (value != null) {
functionExpression._resolvedMultiplicityParametersAdd((Multiplicity) value);
} else {
throw new PureCompilationException(functionExpression.getSourceInformation(), "The multiplicity parameter " + parameterName + " was not resolved!");
}
});
}
}
use of org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceContext in project legend-pure by finos.
the class TypeInference method potentiallyUpdateParentTypeParamForInstanceValueWithManyElements.
public static void potentiallyUpdateParentTypeParamForInstanceValueWithManyElements(InstanceValue instance, TypeInferenceContext typeInferenceContext, ProcessorState state, ProcessorSupport processorSupport) {
MutableList<TypeInferenceContextState> set = typeInferenceContext.drop(instance._values().size());
if (typeInferenceContext.getParent() != null) {
TypeInferenceContextState nonInstanceSpecificState = set.get(0);
RichIterable<TypeInferenceContextState> instanceStates = ListHelper.tail(set);
// Accumulate changes so as not to modify during iteration
MutableMap<GenericType, GenericType> toRegisterTypes = Maps.mutable.empty();
for (String typeParam : nonInstanceSpecificState.getTypeParameters()) {
CoreInstance possibleParentTypeParam = nonInstanceSpecificState.getTypeParameterValue(typeParam);
if (!org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(possibleParentTypeParam)) {
MutableList<CoreInstance> allGenericTypes = Lists.mutable.empty();
for (TypeInferenceContextState v : instanceStates) {
allGenericTypes.add(v.getTypeParameterValue(typeParam));
}
CoreInstance res = org.finos.legend.pure.m3.navigation.generictype.GenericType.findBestCommonGenericType(allGenericTypes, org.finos.legend.pure.m3.navigation.typeparameter.TypeParameter.isCovariant(possibleParentTypeParam), false, processorSupport);
toRegisterTypes.put((GenericType) possibleParentTypeParam, (GenericType) res);
}
}
// Accumulate changes so as not to modify during iteration
MutableMap<Multiplicity, Multiplicity> toRegisterMultiplicities = Maps.mutable.empty();
for (String multiplicityParam : nonInstanceSpecificState.getMultiplicityParameters()) {
CoreInstance possibleParentMultiplicityTypeParam = nonInstanceSpecificState.getMultiplicityParameterValue(multiplicityParam);
if (!org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.isMultiplicityConcrete(possibleParentMultiplicityTypeParam) && !instanceStates.isEmpty()) {
CoreInstance res = instanceStates.getFirst().getMultiplicityParameterValue(multiplicityParam);
for (TypeInferenceContextState v : instanceStates) {
res = org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.minSubsumingMultiplicity(res, v.getMultiplicityParameterValue(multiplicityParam), processorSupport);
}
toRegisterMultiplicities.put((Multiplicity) possibleParentMultiplicityTypeParam, (Multiplicity) res);
}
}
toRegisterTypes.forEachKeyValue((from, to) -> typeInferenceContext.getParent().register(from, to, typeInferenceContext.getParent(), state.getObserver()));
toRegisterMultiplicities.forEachKeyValue((from, to) -> typeInferenceContext.getParent().registerMul(from, to, typeInferenceContext.getParent(), state.getObserver()));
}
}
use of org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceContext in project legend-pure by finos.
the class TypeInferenceContext method register.
public void register(GenericType templateGenType, GenericType genericType, TypeInferenceContext targetGenericsContext, TypeInferenceObserver observer) {
Objects.requireNonNull(targetGenericsContext);
if (genericType != null) {
GenericType genericTypeCopy = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.copyGenericType(genericType, true, this.processorSupport);
String name = org.finos.legend.pure.m3.navigation.generictype.GenericType.getTypeParameterName(templateGenType);
if (name != null) {
ParameterValueWithFlag existing = this.states.getLast().getTypeParameterValueWithFlag(name);
List<RegistrationRequest> forwards = Lists.mutable.empty();
if (existing == null) {
// New registration
this.states.getLast().putTypeParameterValue(name, genericTypeCopy, targetGenericsContext, false);
} else if (org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(existing.getParameterValue()) && org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(genericTypeCopy)) {
// Merge two concrete types
GenericType merged = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.findBestCommonGenericType(Lists.mutable.with(existing.getParameterValue(), genericTypeCopy), TypeParameter.isCovariant(templateGenType), false, genericType.getSourceInformation(), this.processorSupport);
this.states.getLast().putTypeParameterValue(name, merged, targetGenericsContext, false);
// See if the replacement is the more concrete version of a previously semi-concrete type (List<T> replaced by List<String>)
CoreInstance existingRawType = ((GenericType) existing.getParameterValue())._rawType();
CoreInstance replacementRawType = merged._rawType();
if (existingRawType.equals(replacementRawType)) {
Iterator<? extends GenericType> existingTypeArguments = ((GenericType) existing.getParameterValue())._typeArguments().iterator();
Iterator<? extends GenericType> replacementTypeArguments = merged._typeArguments().iterator();
while (existingTypeArguments.hasNext()) {
GenericType existingArgument = existingTypeArguments.next();
GenericType replacementArgument = replacementTypeArguments.next();
if (!org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(existingArgument) && org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(replacementArgument)) {
forwards.add(new RegistrationRequest(existing.getTargetGenericsContext(), existingArgument, replacementArgument));
}
}
}
} else if (this.states.size() > 1) {
// We are processing elements of a collection, record what we learn for the element which will later
// be processed by TypeInference.potentiallyUpdateParentTypeParamForInstanceValueWithManyElements later
this.states.getLast().putTypeParameterValue(name, genericTypeCopy, targetGenericsContext, false);
} else if (org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(existing.getParameterValue())) {
// Replace the existing concrete registration with a generic one and move the concrete one to the referenced type
this.states.getLast().putTypeParameterValue(name, genericTypeCopy, targetGenericsContext, false);
forwards.add(new RegistrationRequest(targetGenericsContext, genericTypeCopy, existing.getParameterValue()));
} else if (org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(genericTypeCopy)) {
if (!existing.getTargetGenericsContext().equals(this)) {
// forward the registration of this concrete type to the already referenced type
forwards.add(new RegistrationRequest(existing.getTargetGenericsContext(), existing.getParameterValue(), genericTypeCopy));
}
} else {
if (!existing.getTargetGenericsContext().equals(this)) {
// forward the registration of this generic type to the already referenced type
forwards.add(new RegistrationRequest(existing.getTargetGenericsContext(), existing.getParameterValue(), genericTypeCopy));
}
}
observer.register(templateGenType, genericTypeCopy, this, targetGenericsContext);
observer.shiftTab();
forwards.forEach(request -> request.context.register((GenericType) request.template, (GenericType) request.value, targetGenericsContext, observer));
observer.unShiftTab();
}
if (org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(templateGenType) && org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(genericTypeCopy)) {
if (!Type.isBottomType(ImportStub.withImportStubByPass(templateGenType._rawTypeCoreInstance(), this.processorSupport), this.processorSupport) && !Type.isBottomType(ImportStub.withImportStubByPass(genericTypeCopy._rawTypeCoreInstance(), this.processorSupport), this.processorSupport) && !Type.isTopType(ImportStub.withImportStubByPass(templateGenType._rawTypeCoreInstance(), this.processorSupport), this.processorSupport) && !Type.isTopType(ImportStub.withImportStubByPass(genericTypeCopy._rawTypeCoreInstance(), this.processorSupport), this.processorSupport)) {
ListIterable<? extends CoreInstance> typeValues;
ListIterable<? extends CoreInstance> mulValues;
ListIterable<? extends CoreInstance> typeTemplates;
ListIterable<? extends CoreInstance> mulTemplates;
if (Type.subTypeOf(ImportStub.withImportStubByPass(templateGenType._rawTypeCoreInstance(), this.processorSupport), ImportStub.withImportStubByPass(genericTypeCopy._rawTypeCoreInstance(), this.processorSupport), this.processorSupport)) {
typeTemplates = extractTypes(org.finos.legend.pure.m3.navigation.generictype.GenericType.resolveClassTypeParameterUsingInheritance(templateGenType, genericTypeCopy, this.processorSupport));
mulTemplates = extractMuls(org.finos.legend.pure.m3.navigation.generictype.GenericType.resolveClassMultiplicityParameterUsingInheritance(templateGenType, ImportStub.withImportStubByPass(genericTypeCopy._rawTypeCoreInstance(), this.processorSupport), this.processorSupport));
typeValues = ListHelper.wrapListIterable(genericTypeCopy._typeArguments());
mulValues = ListHelper.wrapListIterable(genericTypeCopy._multiplicityArguments());
} else {
typeTemplates = ListHelper.wrapListIterable(templateGenType._typeArguments());
mulTemplates = ListHelper.wrapListIterable(templateGenType._multiplicityArguments());
typeValues = extractTypes(org.finos.legend.pure.m3.navigation.generictype.GenericType.resolveClassTypeParameterUsingInheritance(genericTypeCopy, templateGenType, this.processorSupport));
mulValues = extractMuls(org.finos.legend.pure.m3.navigation.generictype.GenericType.resolveClassMultiplicityParameterUsingInheritance(genericTypeCopy, ImportStub.withImportStubByPass(templateGenType._rawTypeCoreInstance(), this.processorSupport), this.processorSupport));
}
for (int z = 0; z < mulValues.size(); z++) {
registerMul((Multiplicity) mulTemplates.get(z), (Multiplicity) mulValues.get(z), targetGenericsContext, observer);
}
for (int z = 0; z < typeValues.size(); z++) {
GenericType first = (GenericType) typeTemplates.get(z);
GenericType second = (GenericType) typeValues.get(z);
if (org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(first) && first._rawTypeCoreInstance() instanceof org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType && org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(second) && second._rawTypeCoreInstance() instanceof org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType) {
org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType firstFuncType = (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType) first._rawTypeCoreInstance();
org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType secondFuncType = (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType) second._rawTypeCoreInstance();
observer.register(first, second, this, targetGenericsContext);
observer.shiftTab();
ListIterable<? extends VariableExpression> firstParams = ListHelper.wrapListIterable(firstFuncType._parameters());
ListIterable<? extends VariableExpression> secondParams = ListHelper.wrapListIterable(secondFuncType._parameters());
for (int i = 0; i < firstParams.size(); i++) {
register(firstParams.get(i)._genericType(), secondParams.get(i)._genericType(), targetGenericsContext, observer);
registerMul(firstParams.get(i)._multiplicity(), secondParams.get(i)._multiplicity(), targetGenericsContext, observer);
}
register(firstFuncType._returnType(), secondFuncType._returnType(), targetGenericsContext, observer);
registerMul(firstFuncType._returnMultiplicity(), secondFuncType._returnMultiplicity(), targetGenericsContext, observer);
observer.unShiftTab();
} else {
register(first, second, targetGenericsContext, observer);
}
}
}
}
}
}
use of org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceContext in project legend-pure by finos.
the class ProcessorState method popTypeInferenceContextAhead.
public void popTypeInferenceContextAhead() {
this.observer.unShiftTab();
TypeInferenceContext tc = this.typeInferenceContext.pop();
if (tc.getParent() != null) {
this.typeInferenceContext.push(tc.getParent());
}
}
use of org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceContext in project legend-pure by finos.
the class FunctionExpressionProcessor method process.
@Override
public void process(FunctionExpression functionExpression, final ProcessorState state, final Matcher matcher, final ModelRepository repository, final Context context, final ProcessorSupport processorSupport) {
TypeInferenceObserver observer = state.getObserver();
state.pushTypeInferenceContext();
ListIterable<? extends ValueSpecification> parametersValues = ListHelper.wrapListIterable(functionExpression._parametersValues());
// Process the function's parameters (FIRST PASS)
boolean inferenceSuccess = firstPassTypeInference(functionExpression, parametersValues, state, matcher, repository, context, processorSupport);
// Function matching
ListIterable<? extends Function<?>> foundFunctions = null != functionExpression._funcCoreInstance() ? Lists.immutable.with((Function<?>) ImportStub.withImportStubByPass(functionExpression._funcCoreInstance(), processorSupport)) : Lists.immutable.empty();
String functionName = null;
if (foundFunctions.isEmpty()) {
// Check if the function is a property
InstanceValue propertyNameInstanceVal = functionExpression._propertyName();
if (null != propertyNameInstanceVal) {
ValueSpecification source = parametersValues.get(0);
String propertyName = ImportStub.withImportStubByPass(propertyNameInstanceVal._valuesCoreInstance().toList().get(0), processorSupport).getName();
GenericType sourceGenericType = extractAndValidateGenericType(processorSupport, propertyName, source);
// Is it an enum?
if (org.finos.legend.pure.m3.navigation.generictype.GenericType.subTypeOf(sourceGenericType, org.finos.legend.pure.m3.navigation.type.Type.wrapGenericType(processorSupport.package_getByUserPath(M3Paths.Enumeration), processorSupport), processorSupport)) {
reprocessEnumValueInExtractEnumValue(functionExpression, propertyName, state, repository, processorSupport);
} else {
Multiplicity sourceMultiplicity = source._multiplicity();
if (org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.isToOne(sourceMultiplicity, true)) {
AbstractProperty<?> propertyFunc = findFunctionForPropertyBasedOnMultiplicity(functionExpression, sourceGenericType, state, processorSupport, matcher);
if (null != propertyFunc) {
if (MilestoningFunctions.isGeneratedMilestonedQualifiedPropertyWithMissingDates(propertyFunc, processorSupport)) {
propertyFunc = (AbstractProperty<?>) MilestoningDatesPropagationFunctions.getMilestoningQualifiedPropertyWithAllDatesSupplied(functionExpression, state, repository, context, processorSupport, propertyNameInstanceVal, source, propertyName, propertyFunc);
}
foundFunctions = Lists.immutable.with(propertyFunc);
}
} else {
// Automap
reprocessPropertyForManySources(functionExpression, parametersValues, M3Properties.propertyName, sourceGenericType, repository, processorSupport);
// The parameters values are now different, so update
parametersValues = functionExpression._parametersValues().toList();
// Have another go at type inference
inferenceSuccess = firstPassTypeInference(functionExpression, parametersValues, state, matcher, repository, context, processorSupport);
// return;
}
}
} else // Check if the function is a qualifiedProperty
{
InstanceValue qualifiedPropertyNameVal = functionExpression._qualifiedPropertyName();
if (null != qualifiedPropertyNameVal) {
ValueSpecification source = parametersValues.get(0);
String qualifiedPropertyName = ImportStub.withImportStubByPass(qualifiedPropertyNameVal._valuesCoreInstance().toList().get(0), processorSupport).getName();
GenericType sourceGenericType = extractAndValidateGenericType(processorSupport, qualifiedPropertyName, source);
Multiplicity sourceMultiplicity = source._multiplicity();
// }
if (org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.isToOne(sourceMultiplicity, true)) {
ListIterable<QualifiedProperty<?>> qualifiedPropertyFuncs = findFunctionsForQualifiedPropertyBasedOnMultiplicity(functionExpression, sourceGenericType, parametersValues, processorSupport, matcher, state);
if (qualifiedPropertyFuncs.size() == 1 && MilestoningFunctions.isGeneratedMilestonedQualifiedPropertyWithMissingDates(qualifiedPropertyFuncs.getFirst(), processorSupport)) {
Function<?> mqp = (Function<?>) MilestoningDatesPropagationFunctions.getMilestoningQualifiedPropertyWithAllDatesSupplied(functionExpression, state, repository, context, processorSupport, qualifiedPropertyNameVal, source, qualifiedPropertyName, qualifiedPropertyFuncs.getFirst());
foundFunctions = Lists.immutable.with(mqp);
} else {
foundFunctions = qualifiedPropertyFuncs;
}
} else {
// Automap
reprocessPropertyForManySources(functionExpression, parametersValues, M3Properties.qualifiedPropertyName, sourceGenericType, repository, processorSupport);
// The parameters values are now different, so update
parametersValues = functionExpression._parametersValues().toList();
// Have another go at type inference
inferenceSuccess = firstPassTypeInference(functionExpression, parametersValues, state, matcher, repository, context, processorSupport);
}
}
}
if (foundFunctions.isEmpty()) {
// Match the functionExpression with the Function library (may still need to do it even if the function is a property because it may have been reprocessed as a Collect!)
foundFunctions = FunctionExpressionMatcher.findMatchingFunctionsInTheRepository(functionExpression, true, processorSupport);
functionName = getFunctionName(functionExpression);
}
}
Function<?> finalFunction = null;
boolean someInferenceFailed = false;
for (Function<?> foundFunction : foundFunctions) {
functionExpression._funcRemove();
functionExpression._funcCoreInstance(foundFunction);
state.getTypeInferenceContext().setScope(foundFunction);
FunctionType foundFunctionType = (FunctionType) processorSupport.function_getFunctionType(foundFunction);
observer.functionMatched(foundFunction, foundFunctionType);
// SECOND PASS
ListIterable<? extends VariableExpression> paramsType = foundFunctionType._parameters().toList();
// enumValues, autoMaps, etc...
parametersValues = functionExpression._parametersValues().toList();
boolean success = true;
if (!inferenceSuccess) {
observer.firstPassInferenceFailed();
observer.shiftTab();
observer.shiftTab();
observer.matchTypeParamsFromFoundFunction(foundFunction);
observer.shiftTab();
for (int z = 0; z < parametersValues.size(); z++) {
ValueSpecification instance = parametersValues.get(z);
if (isInferenceSuccess(instance, processorSupport)) {
observer.matchParam(z);
GenericType templateGenType = paramsType.get(z)._genericType();
TypeInferenceContext typeInferenceContext = state.getTypeInferenceContext();
typeInferenceContext.register(templateGenType, instance._genericType(), typeInferenceContext.getTopContext(), observer);
typeInferenceContext.registerMul(paramsType.get(z)._multiplicity(), instance._multiplicity(), typeInferenceContext.getTopContext(), observer);
} else {
observer.paramInferenceFailed(z);
}
}
observer.unShiftTab();
observer.reverseMatching();
for (int z = 0; z < parametersValues.size(); z++) {
final ValueSpecification instance = parametersValues.get(z);
observer.processingParameter(functionExpression, z, instance);
GenericType templateGenType = paramsType.get(z)._genericType();
Multiplicity templateMultiplicity = paramsType.get(z)._multiplicity();
GenericType resolvedGenericType = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.makeTypeArgumentAsConcreteAsPossible(templateGenType, state.getTypeInferenceContext().getTypeParameterToGenericType(), state.getTypeInferenceContext().getMultiplicityParameterToMultiplicity(), processorSupport);
Multiplicity resolvedMultiplicity = (Multiplicity) org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.makeMultiplicityAsConcreteAsPossible(templateMultiplicity, state.getTypeInferenceContext().getMultiplicityParameterToMultiplicity());
if (isLambdaWithEmptyParamType(instance, processorSupport)) {
observer.shiftTab();
final VariableExpression templateToMatchLambdaTo = Objects.requireNonNull(getRawTypeFromGenericType(foundFunction, processorSupport))._parameters().toList().get(z);
observer.register(templateToMatchLambdaTo, templateToMatchLambdaTo, state.getTypeInferenceContext(), state.getTypeInferenceContext());
for (final CoreInstance val : ((InstanceValue) instance)._valuesCoreInstance()) {
if (val instanceof LambdaFunction) {
org.eclipse.collections.api.block.function.Function<CoreInstance, Boolean> processParamTypesOfLambdaUsedAsAFunctionExpressionParamValue = coreInstance -> !TypeInference.processParamTypesOfLambdaUsedAsAFunctionExpressionParamValue(instance, (LambdaFunction<?>) val, templateToMatchLambdaTo, matcher, state, repository, processorSupport);
success = success && MilestoningDatesPropagationFunctions.possiblyExecuteInNewMilestoningDateContext(functionExpression, val, processParamTypesOfLambdaUsedAsAFunctionExpressionParamValue, state, repository, context, processorSupport);
// Manage return type in any case
GenericType templateGenericType = templateToMatchLambdaTo._genericType();
ClassInstance functionClass = (ClassInstance) processorSupport.package_getByUserPath(M3Paths.Function);
if (org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(templateGenericType, processorSupport) && org.finos.legend.pure.m3.navigation.type.Type.subTypeOf(ImportStub.withImportStubByPass(templateGenericType._rawTypeCoreInstance(), processorSupport), functionClass, processorSupport)) {
GenericType templateGenFunctionType = templateGenericType._typeArguments().toList().get(0);
if (org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(templateGenFunctionType, processorSupport) && !org.finos.legend.pure.m3.navigation.type.Type.isTopType(Instance.getValueForMetaPropertyToOneResolved(templateGenFunctionType, M3Properties.rawType, processorSupport), processorSupport)) {
GenericType templateReturnType = null != ImportStub.withImportStubByPass(templateGenFunctionType._rawTypeCoreInstance(), processorSupport) ? ((FunctionType) ImportStub.withImportStubByPass(templateGenFunctionType._rawTypeCoreInstance(), processorSupport))._returnType() : null;
// Generics in lambdas are relative to their environment (i.e. the function in which they are defined)
TypeInferenceContext lambdaInferenceContext = state.getTypeInferenceContext().getTopContext();
if (null != templateReturnType) {
FunctionType lambdaFunctionType = Objects.requireNonNull(getRawTypeFromGenericType((LambdaFunction<?>) val, processorSupport));
GenericType concreteGenericType = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.makeTypeArgumentAsConcreteAsPossible(lambdaFunctionType._returnType(), lambdaInferenceContext.getTypeParameterToGenericType(), lambdaInferenceContext.getMultiplicityParameterToMultiplicity(), processorSupport);
lambdaFunctionType._returnTypeRemove();
lambdaFunctionType._returnType(concreteGenericType);
if (!org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(templateReturnType, processorSupport)) {
TypeInferenceContext typeInferenceContext = state.getTypeInferenceContext();
typeInferenceContext.register(templateReturnType, concreteGenericType, typeInferenceContext.getParent(), observer);
}
}
Multiplicity templateReturnMultiplicity = null != ImportStub.withImportStubByPass(templateGenFunctionType._rawTypeCoreInstance(), processorSupport) ? ((FunctionType) ImportStub.withImportStubByPass(templateGenFunctionType._rawTypeCoreInstance(), processorSupport))._returnMultiplicity() : null;
if (null != templateReturnMultiplicity) {
FunctionType lambdaFunctionType = Objects.requireNonNull(getRawTypeFromGenericType((LambdaFunction<?>) val, processorSupport));
Multiplicity concreteMultiplicity = (Multiplicity) org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.makeMultiplicityAsConcreteAsPossible(Instance.getValueForMetaPropertyToOneResolved(lambdaFunctionType, M3Properties.returnMultiplicity, processorSupport), lambdaInferenceContext.getMultiplicityParameterToMultiplicity());
lambdaFunctionType._returnMultiplicityRemove();
lambdaFunctionType._returnMultiplicity(concreteMultiplicity);
if (null != concreteMultiplicity) {
TypeInferenceContext typeInferenceContext = state.getTypeInferenceContext();
typeInferenceContext.registerMul(templateReturnMultiplicity, concreteMultiplicity, typeInferenceContext.getParent(), observer);
}
}
}
}
}
}
observer.unShiftTab();
} else {
state.pushTypeInferenceContextAhead();
TypeInferenceContext typeInferenceContext = state.getTypeInferenceContext();
typeInferenceContext.setScope(instance instanceof SimpleFunctionExpression ? ((SimpleFunctionExpression) instance)._funcCoreInstance() : null);
typeInferenceContext.register(instance._genericType(), resolvedGenericType, typeInferenceContext.getParent(), observer);
typeInferenceContext.registerMul(instance._multiplicity(), resolvedMultiplicity, typeInferenceContext.getParent(), observer);
cleanProcess(instance, state, repository, context, processorSupport);
PostProcessor.processElement(matcher, instance, state, processorSupport);
state.popTypeInferenceContextAhead();
}
}
observer.unShiftTab();
observer.unShiftTab();
} else {
observer.parameterInferenceSucceeded();
observer.shiftTab();
observer.shiftTab();
parametersValues.forEachWithIndex((instance, z) -> {
TypeInferenceContext typeInferenceContext = state.getTypeInferenceContext();
typeInferenceContext.register(paramsType.get(z)._genericType(), instance._genericType(), typeInferenceContext.getTopContext(), observer);
typeInferenceContext.registerMul(paramsType.get(z)._multiplicity(), instance._multiplicity(), typeInferenceContext.getTopContext(), observer);
});
// WARNING / returnType may need reverse matching to be found
GenericType returnGenericType = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.makeTypeArgumentAsConcreteAsPossible(foundFunctionType._returnType(), state.getTypeInferenceContext().getTypeParameterToGenericType(), state.getTypeInferenceContext().getMultiplicityParameterToMultiplicity(), processorSupport);
observer.returnType(returnGenericType);
if (!org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(returnGenericType, processorSupport) && !state.getTypeInferenceContext().isTop(org.finos.legend.pure.m3.navigation.generictype.GenericType.getTypeParameterName(returnGenericType, processorSupport))) {
observer.shiftTab();
observer.returnTypeNotConcrete();
// reverse matching
parametersValues.forEachWithIndex((instance, z) -> {
GenericType templateGenType = paramsType.get(z)._genericType();
Multiplicity templateMultiplicity = paramsType.get(z)._multiplicity();
GenericType resolvedGenericType = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.makeTypeArgumentAsConcreteAsPossible(templateGenType, state.getTypeInferenceContext().getTypeParameterToGenericType(), state.getTypeInferenceContext().getMultiplicityParameterToMultiplicity(), processorSupport);
Multiplicity resolvedMultiplicity = (Multiplicity) org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.makeMultiplicityAsConcreteAsPossible(templateMultiplicity, state.getTypeInferenceContext().getMultiplicityParameterToMultiplicity());
state.pushTypeInferenceContextAhead();
state.getTypeInferenceContext().setScope(instance instanceof FunctionExpression ? ((FunctionExpression) instance)._funcCoreInstance() : null);
observer.processingParameter(functionExpression, z, instance);
TypeInferenceContext typeInferenceContext = state.getTypeInferenceContext();
typeInferenceContext.register(instance._genericType(), resolvedGenericType, typeInferenceContext.getParent(), observer);
typeInferenceContext.registerMul(instance._multiplicity(), resolvedMultiplicity, typeInferenceContext.getParent(), observer);
observer.shiftTab();
observer.reprocessingTheParameter();
observer.shiftTab();
cleanProcess(instance, state, repository, context, processorSupport);
PostProcessor.processElement(matcher, instance, state, processorSupport);
observer.unShiftTab();
observer.finishedProcessParameter();
observer.unShiftTab();
state.popTypeInferenceContextAhead();
});
observer.unShiftTab();
returnGenericType = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.makeTypeArgumentAsConcreteAsPossible(foundFunctionType._returnType(), state.getTypeInferenceContext().getTypeParameterToGenericType(), state.getTypeInferenceContext().getMultiplicityParameterToMultiplicity(), processorSupport);
observer.newReturnType(returnGenericType);
}
observer.unShiftTab();
observer.unShiftTab();
observer.finishedRegisteringParametersAndMultiplicities();
}
// We can infer the parameter types for Lambdas given as parameters (now that we know which function to use).
if (success) {
TypeInference.storeInferredTypeParametersInFunctionExpression(functionExpression, state, processorSupport, foundFunction);
// Get the return type information
// Pair<CoreInstance, CoreInstance> result = FunctionExpression.resolveFunctionGenericReturnTypeAndMultiplicity(functionExpression, context, processorSupport);
// result.getOne();
GenericType returnGenericType = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.makeTypeArgumentAsConcreteAsPossible(foundFunctionType._returnType(), state.getTypeInferenceContext().getTypeParameterToGenericType(), state.getTypeInferenceContext().getMultiplicityParameterToMultiplicity(), processorSupport);
Multiplicity returnMultiplicity = (Multiplicity) org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.makeMultiplicityAsConcreteAsPossible(foundFunctionType._returnMultiplicity(), state.getTypeInferenceContext().getMultiplicityParameterToMultiplicity());
if (!org.finos.legend.pure.m3.navigation.generictype.GenericType.isGenericTypeConcrete(returnGenericType, processorSupport) && !state.getTypeInferenceContext().isTop(org.finos.legend.pure.m3.navigation.generictype.GenericType.getTypeParameterName(returnGenericType, processorSupport))) {
throw new PureCompilationException(functionExpression.getSourceInformation(), "The system is not capable of inferring the return type of the function '" + functionExpression.getValueForMetaPropertyToOne(M3Properties.func).getValueForMetaPropertyToOne(M3Properties.functionName).getName() + "'. Check your signatures!");
}
// Update the type
GenericType genericTypeCopy = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.copyGenericTypeAsInferredGenericType(returnGenericType, functionExpression.getSourceInformation(), processorSupport);
functionExpression._genericType(genericTypeCopy);
// Update the multiplicity
Multiplicity returnMultiplicityCopy = (Multiplicity) org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.copyMultiplicity(returnMultiplicity, functionExpression.getSourceInformation(), processorSupport);
functionExpression._multiplicity(returnMultiplicityCopy);
} else {
// Inference failed...
FunctionType functionType = (FunctionType) processorSupport.function_getFunctionType(foundFunction);
GenericType returnGenericType = functionType._returnType();
GenericType genericTypeCopy = (GenericType) org.finos.legend.pure.m3.navigation.generictype.GenericType.copyGenericTypeAsInferredGenericType(returnGenericType, functionExpression.getSourceInformation(), processorSupport);
functionExpression._genericType(genericTypeCopy);
Multiplicity returnMultiplicity = functionType._returnMultiplicity();
Multiplicity returnMultiplicityCopy = (Multiplicity) org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity.copyMultiplicity(returnMultiplicity, functionExpression.getSourceInformation(), processorSupport);
functionExpression._multiplicity(returnMultiplicityCopy);
}
if (null == functionName) {
finalFunction = foundFunction;
} else if (!success) {
someInferenceFailed = true;
} else {
Function<?> bestMatch = FunctionExpressionMatcher.getBestFunctionMatch(foundFunctions, parametersValues, functionName, functionExpression.getSourceInformation(), false, processorSupport);
if (bestMatch == foundFunction) {
finalFunction = foundFunction;
}
}
if (null != finalFunction) {
break;
}
// Clean up before re-trying
if (1 < foundFunctions.size()) {
for (ValueSpecification parameterValue : parametersValues) {
cleanProcess(parameterValue, state, repository, context, processorSupport);
}
inferenceSuccess = firstPassTypeInference(functionExpression, parametersValues, state, matcher, repository, context, processorSupport);
}
}
if (null != finalFunction) {
finalFunction._applications(Lists.immutable.<FunctionExpression>withAll(finalFunction._applications()).newWith(functionExpression));
// Update the function in the function expression in the reverse
if ("new_Class_1__String_1__KeyExpression_MANY__T_1_".equals(finalFunction.getName()) || "new_Class_1__String_1__T_1_".equals(finalFunction.getName())) {
this.addTraceForKeyExpressions(functionExpression, processorSupport);
}
if ("copy_T_1__String_1__KeyExpression_MANY__T_1_".equals(finalFunction.getName()) || "copy_T_1__String_1__T_1_".equals(finalFunction.getName())) {
this.addTraceForKeyExpressions(functionExpression, processorSupport);
}
if ("letFunction_String_1__T_m__T_m_".equals(finalFunction.getName())) {
try {
state.getVariableContext().getParent().registerValue(((InstanceValue) parametersValues.get(0))._valuesCoreInstance().toList().get(0).getName(), parametersValues.get(1));
} catch (VariableNameConflictException e) {
throw new PureCompilationException(functionExpression.getSourceInformation(), e.getMessage());
}
}
} else if (!someInferenceFailed) {
throwNoMatchException(functionExpression, state, processorSupport);
}
observer.unShiftTab();
observer.finishedProcessingFunctionExpression(functionExpression);
state.popTypeInferenceContext();
}
Aggregations