Search in sources :

Example 1 with Automap

use of org.finos.legend.pure.m3.compiler.postprocessing.processor.Automap 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();
}
Also used : ParameterValueSpecificationContext(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ParameterValueSpecificationContext) SimpleFunctionExpression(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.SimpleFunctionExpression) ImportGroup(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel._import.ImportGroup) SetIterable(org.eclipse.collections.api.set.SetIterable) MilestonedPropertyMetaData(org.finos.legend.pure.m3.compiler.postprocessing.processor.milestoning.MilestonedPropertyMetaData) ClassProjection(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.ClassProjection) FunctionDefinitionProcessor(org.finos.legend.pure.m3.compiler.postprocessing.processor.FunctionDefinitionProcessor) MutableList(org.eclipse.collections.api.list.MutableList) ProcessorState(org.finos.legend.pure.m3.compiler.postprocessing.ProcessorState) PureUnmatchedFunctionException(org.finos.legend.pure.m3.exception.PureUnmatchedFunctionException) ProcessorSupport(org.finos.legend.pure.m3.navigation.ProcessorSupport) MutableSet(org.eclipse.collections.api.set.MutableSet) TypeInferenceContext(org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceContext) FunctionType(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType) RichIterable(org.eclipse.collections.api.RichIterable) GenericTypeTraceability(org.finos.legend.pure.m3.compiler.postprocessing.GenericTypeTraceability) PostProcessor(org.finos.legend.pure.m3.compiler.postprocessing.PostProcessor) Automap(org.finos.legend.pure.m3.compiler.postprocessing.processor.Automap) PureCompilationException(org.finos.legend.pure.m4.exception.PureCompilationException) ModelRepository(org.finos.legend.pure.m4.ModelRepository) KeyValueValueSpecificationContext(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.KeyValueValueSpecificationContext) TypeInference(org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInference) ListHelper(org.finos.legend.pure.m3.tools.ListHelper) Matcher(org.finos.legend.pure.m3.tools.matcher.Matcher) Objects(java.util.Objects) UnbindState(org.finos.legend.pure.m3.compiler.unload.unbind.UnbindState) Multiplicity(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.multiplicity.Multiplicity) GenericType(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType) org.finos.legend.pure.m3.navigation._class._Class(org.finos.legend.pure.m3.navigation._class._Class) ValueSpecificationBootstrap(org.finos.legend.pure.m3.navigation.ValueSpecificationBootstrap) ImportStub(org.finos.legend.pure.m3.navigation.importstub.ImportStub) MilestoningDatesPropagationFunctions(org.finos.legend.pure.m3.compiler.postprocessing.processor.milestoning.MilestoningDatesPropagationFunctions) ListIterable(org.eclipse.collections.api.list.ListIterable) Processor(org.finos.legend.pure.m3.compiler.postprocessing.processor.Processor) FunctionExpressionMatcher(org.finos.legend.pure.m3.compiler.postprocessing.functionmatch.FunctionExpressionMatcher) VariableExpression(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.VariableExpression) AbstractProperty(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.AbstractProperty) Instance(org.finos.legend.pure.m3.navigation.Instance) Unbinder(org.finos.legend.pure.m3.compiler.unload.Unbinder) QualifiedProperty(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty) Lists(org.eclipse.collections.api.factory.Lists) FunctionDefinition(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.FunctionDefinition) PartitionSet(org.eclipse.collections.api.partition.set.PartitionSet) M3Paths(org.finos.legend.pure.m3.navigation.M3Paths) Context(org.finos.legend.pure.m3.compiler.Context) VariableNameConflictException(org.finos.legend.pure.m3.compiler.postprocessing.VariableContext.VariableNameConflictException) ImportAccessor(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel._import.ImportAccessor) Function(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.Function) FunctionExpression(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.FunctionExpression) TypeInferenceObserver(org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceObserver) Package(org.finos.legend.pure.m3.coreinstance.Package) LambdaFunctionInstance(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.LambdaFunctionInstance) Sets(org.eclipse.collections.api.factory.Sets) PackageableElement(org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement) SourceInformation(org.finos.legend.pure.m4.coreinstance.SourceInformation) MilestoningFunctions(org.finos.legend.pure.m3.compiler.postprocessing.processor.milestoning.MilestoningFunctions) ClassInstance(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.ClassInstance) CoreInstance(org.finos.legend.pure.m4.coreinstance.CoreInstance) Type(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type) ValueSpecification(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification) LambdaFunction(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.LambdaFunction) InstanceValue(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.InstanceValue) Visibility(org.finos.legend.pure.m3.compiler.visibility.Visibility) KeyExpression(org.finos.legend.pure.m3.coreinstance.meta.pure.functions.lang.KeyExpression) M3Properties(org.finos.legend.pure.m3.navigation.M3Properties) ValueSpecification(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification) InstanceValue(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.InstanceValue) VariableNameConflictException(org.finos.legend.pure.m3.compiler.postprocessing.VariableContext.VariableNameConflictException) Function(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.Function) LambdaFunction(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.LambdaFunction) SimpleFunctionExpression(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.SimpleFunctionExpression) FunctionExpression(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.FunctionExpression) SimpleFunctionExpression(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.SimpleFunctionExpression) Multiplicity(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.multiplicity.Multiplicity) TypeInferenceObserver(org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceObserver) TypeInferenceContext(org.finos.legend.pure.m3.compiler.postprocessing.inference.TypeInferenceContext) ClassInstance(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.ClassInstance) PureCompilationException(org.finos.legend.pure.m4.exception.PureCompilationException) GenericType(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType) FunctionType(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType) VariableExpression(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.VariableExpression) LambdaFunction(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.LambdaFunction) CoreInstance(org.finos.legend.pure.m4.coreinstance.CoreInstance) QualifiedProperty(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty)

Example 2 with Automap

use of org.finos.legend.pure.m3.compiler.postprocessing.processor.Automap in project legend-engine by finos.

the class HelperValueSpecificationBuilder method processProperty.

public static org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification processProperty(CompileContext context, MutableList<String> openVariables, ProcessingContext processingContext, List<org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.ValueSpecification> parameters, String property, SourceInformation sourceInformation) {
    // for X.property. X is the first parameter
    processingContext.push("Processing property " + property);
    org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.ValueSpecification firstArgument = parameters.get(0);
    MutableList<org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification> processedParameters = ListIterate.collect(parameters, p -> p.accept(new ValueSpecificationBuilder(context, openVariables, processingContext)));
    org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType genericType;
    org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.multiplicity.Multiplicity multiplicity;
    org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification inferredVariable;
    org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification result;
    if (// Only for backward compatibility!
    firstArgument instanceof org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Enum || (processedParameters.get(0)._genericType()._rawType().equals(context.pureModel.getType("meta::pure::metamodel::type::Enumeration")))) {
        org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity m = new org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity();
        m.lowerBound = 1;
        m.setUpperBound(1);
        CString enumValue = new CString();
        enumValue.values = Lists.mutable.of(property);
        enumValue.multiplicity = m;
        // validation to make sure the enum value can be found
        context.resolveEnumValue(((PackageableElementPtr) firstArgument).fullPath, enumValue.values.get(0), firstArgument.sourceInformation, sourceInformation);
        AppliedFunction extractEnum = new AppliedFunction();
        extractEnum.function = "extractEnumValue";
        extractEnum.parameters = Lists.mutable.of(firstArgument, enumValue);
        result = extractEnum.accept(new ValueSpecificationBuilder(context, openVariables, processingContext));
    } else {
        if (firstArgument instanceof Variable) {
            inferredVariable = processingContext.getInferredVariable(((Variable) firstArgument).name);
        } else {
            inferredVariable = processedParameters.get(0);
        }
        Type inferredType = inferredVariable._genericType()._rawType();
        if (// is an enum
        !(inferredType instanceof org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class)) {
            inferredType = context.pureModel.getType("meta::pure::metamodel::type::Enum");
        }
        org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.AbstractProperty<?> foundProperty = findProperty(context, (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class<?>) inferredType, parameters, property, sourceInformation);
        if (foundProperty instanceof Property) {
            genericType = (foundProperty._classifierGenericType()._typeArguments()).getLast();
            multiplicity = foundProperty._multiplicity();
        } else if (foundProperty instanceof QualifiedProperty) {
            FunctionType fType = (FunctionType) foundProperty._classifierGenericType()._typeArguments().getFirst()._rawType();
            genericType = fType._returnType();
            multiplicity = fType._returnMultiplicity();
        } else {
            throw new UnsupportedOperationException("Unhandled property: " + foundProperty);
        }
        if (// autoMap
        !inferredVariable._multiplicity().getName().equals("PureOne")) {
            processingContext.push("Building Automap for  " + property);
            org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity m = new org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity();
            m.lowerBound = 1;
            m.setUpperBound(1);
            List<org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.ValueSpecification> localParameters = Lists.mutable.ofAll(parameters);
            final String automapName = "v_automap";
            Lambda automapLambda = new Lambda();
            AppliedProperty appliedProperty = new AppliedProperty();
            appliedProperty.property = property;
            Variable automapvar = new Variable();
            Variable automaLambdaparam = new Variable();
            automapvar.name = automapName;
            appliedProperty.parameters = Lists.mutable.of(automapvar);
            if (!localParameters.isEmpty()) {
                localParameters.remove(0);
            }
            appliedProperty.parameters.addAll(localParameters);
            automaLambdaparam.name = automapName;
            automaLambdaparam._class = HelperModelBuilder.getElementFullPath(inferredVariable._genericType()._rawType(), context.pureModel.getExecutionSupport());
            automaLambdaparam.multiplicity = m;
            automapLambda.body = Lists.mutable.of(appliedProperty);
            List<Variable> lambdaParams = new FastList<>();
            lambdaParams.add(automaLambdaparam);
            automapLambda.parameters = lambdaParams;
            List<org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.ValueSpecification> newParams = Lists.mutable.of(parameters.get(0), automapLambda);
            result = context.buildFunctionExpression("map", null, newParams, openVariables, null, processingContext).getOne();
            processingContext.pop();
        } else {
            result = new Root_meta_pure_metamodel_valuespecification_SimpleFunctionExpression_Impl("")._func(foundProperty)._propertyName(new Root_meta_pure_metamodel_valuespecification_InstanceValue_Impl("")._values(Lists.fixedSize.of(foundProperty.getName())))._genericType(genericType)._multiplicity(multiplicity)._parametersValues(processedParameters);
        }
    }
    processingContext.pop();
    return result;
}
Also used : ValueSpecification(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.ValueSpecification) CString(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.CString) Multiplicity(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity) FastList(org.eclipse.collections.impl.list.mutable.FastList) GenericType(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType) Class(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class) QualifiedProperty(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty) Variable(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.Variable) CString(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.CString) Multiplicity(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity) AbstractProperty(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.AbstractProperty) QualifiedProperty(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty) Property(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.Property) AppliedProperty(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.application.AppliedProperty) Lambda(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda) FunctionType(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType) ValueSpecification(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.ValueSpecification) FunctionType(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType) Type(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type) GenericType(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType) AppliedFunction(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.application.AppliedFunction) AppliedProperty(org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.application.AppliedProperty)

Aggregations

AbstractProperty (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.AbstractProperty)2 QualifiedProperty (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty)2 Objects (java.util.Objects)1 RichIterable (org.eclipse.collections.api.RichIterable)1 Lists (org.eclipse.collections.api.factory.Lists)1 Sets (org.eclipse.collections.api.factory.Sets)1 ListIterable (org.eclipse.collections.api.list.ListIterable)1 MutableList (org.eclipse.collections.api.list.MutableList)1 PartitionSet (org.eclipse.collections.api.partition.set.PartitionSet)1 MutableSet (org.eclipse.collections.api.set.MutableSet)1 SetIterable (org.eclipse.collections.api.set.SetIterable)1 FastList (org.eclipse.collections.impl.list.mutable.FastList)1 Multiplicity (org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity)1 ValueSpecification (org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.ValueSpecification)1 Variable (org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.Variable)1 AppliedFunction (org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.application.AppliedFunction)1 AppliedProperty (org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.application.AppliedProperty)1 CString (org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.CString)1 Lambda (org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda)1 Context (org.finos.legend.pure.m3.compiler.Context)1