use of org.finos.legend.pure.m3.compiler.postprocessing.VariableContext in project legend-pure by finos.
the class FunctionDefinitionProcessor method process.
public static void process(FunctionDefinition<?> functionDefinition, ProcessorState state, Matcher matcher, ModelRepository repository) {
ProcessorSupport processorSupport = state.getProcessorSupport();
VariableContext variableContext = state.getVariableContext();
FunctionType functionType = (FunctionType) processorSupport.function_getFunctionType(functionDefinition);
state.getObserver().startProcessingFunction(functionDefinition, functionType);
URLPatternLibrary urlPatternLibrary = state.getURLPatternLibrary();
if (urlPatternLibrary != null) {
urlPatternLibrary.possiblyRegister(functionDefinition, processorSupport);
}
boolean shouldSetTypeInferenceContext = (functionDefinition instanceof ConcreteFunctionDefinition) && (functionDefinition._classifierGenericType() != null) && (functionDefinition._classifierGenericType()._rawTypeCoreInstance() != null) && "ConcreteFunctionDefinition".equals(functionDefinition._classifierGenericType()._rawTypeCoreInstance().getName());
if (shouldSetTypeInferenceContext) {
state.newTypeInferenceContext(functionType);
}
functionType._parameters().forEach(var -> {
try {
variableContext.registerValue(var._name(), var);
} catch (VariableNameConflictException e) {
throw new PureCompilationException(functionDefinition.getSourceInformation(), e.getMessage());
}
GenericType propertyType = var._genericType();
// The property type may be null if it's a lambda expression...
if (propertyType != null) {
// We resolve because we want to fail fast if a given type is unknown...
org.finos.legend.pure.m3.navigation.generictype.GenericType.resolveGenericTypeUsingImports(propertyType, repository, processorSupport);
}
});
ListIterable<? extends ValueSpecification> expressions = functionDefinition._expressionSequence().toList();
if (expressions.isEmpty()) {
throw new PureCompilationException(functionDefinition.getSourceInformation(), "Function definition must contain at least one expression");
}
// The function is going to be processed again after inference
if (TypeInference.canProcessLambda(functionDefinition, state, processorSupport)) {
state.getObserver().shiftTab();
state.getObserver().startProcessingFunctionBody();
processExpressions(functionDefinition, expressions, matcher, state, processorSupport);
findReturnTypesForLambda(functionDefinition, functionType, processorSupport);
FunctionDefinitionValidator.validateFunctionReturnType(functionDefinition, functionType, processorSupport);
state.getObserver().finishedProcessingFunctionBody();
state.getObserver().unShiftTab();
state.addFunctionDefinition(functionDefinition);
}
if (shouldSetTypeInferenceContext) {
state.deleteTypeInferenceContext();
}
state.getVariableContext().buildAndRegister("return", functionType._returnType(), functionType._returnMultiplicity(), processorSupport);
RichIterable<? extends Constraint> constraints = functionDefinition._preConstraints();
if (constraints.notEmpty()) {
processConstraints(functionDefinition, constraints.toList(), matcher, state, processorSupport);
}
RichIterable<? extends Constraint> postConstraints = functionDefinition._postConstraints();
if (postConstraints.notEmpty()) {
processConstraints(functionDefinition, postConstraints.toList(), matcher, state, processorSupport);
}
state.getObserver().finishedProcessingFunction(functionType);
}
use of org.finos.legend.pure.m3.compiler.postprocessing.VariableContext in project legend-pure by finos.
the class Tag method execute.
@Override
public CoreInstance execute(ListIterable<? extends CoreInstance> params, Stack<MutableMap<String, CoreInstance>> resolvedTypeParameters, Stack<MutableMap<String, CoreInstance>> resolvedMultiplicityParameters, VariableContext variableContext, CoreInstance functionExpressionToUseInStack, Profiler profiler, InstantiationContext instantiationContext, ExecutionSupport executionSupport, Context context, ProcessorSupport processorSupport) throws PureExecutionException {
String tagName = Instance.getValueForMetaPropertyToOneResolved(params.get(1), M3Properties.values, processorSupport).getName();
CoreInstance profile = Instance.getValueForMetaPropertyToOneResolved(params.get(0), M3Properties.values, processorSupport);
CoreInstance tag = Profile.findTag(profile, tagName);
if (tag == null) {
throw new PureExecutionException(functionExpressionToUseInStack.getSourceInformation(), "The tag '" + tagName + "' can't be found in the profile '" + profile.getName() + "'");
}
return ValueSpecificationBootstrap.wrapValueSpecification(tag, ValueSpecification.isExecutable(params.get(0), processorSupport), processorSupport);
}
use of org.finos.legend.pure.m3.compiler.postprocessing.VariableContext in project legend-pure by finos.
the class ToMultiplicity method execute.
@Override
public CoreInstance execute(ListIterable<? extends CoreInstance> params, Stack<MutableMap<String, CoreInstance>> resolvedTypeParameters, Stack<MutableMap<String, CoreInstance>> resolvedMultiplicityParameters, VariableContext variableContext, CoreInstance functionExpressionToUseInStack, Profiler profiler, InstantiationContext instantiationContext, ExecutionSupport executionSupport, Context context, ProcessorSupport processorSupport) throws PureExecutionException {
CoreInstance returnMultiplicity = getReturnMultiplicity(processorSupport);
CoreInstance param = params.get(0);
if (Multiplicity.multiplicitiesEqual(returnMultiplicity, Instance.getValueForMetaPropertyToOneResolved(param, M3Properties.multiplicity, processorSupport))) {
return param;
}
ListIterable<? extends CoreInstance> values = Instance.getValueForMetaPropertyToManyResolved(param, M3Properties.values, processorSupport);
if (!Multiplicity.isValid(returnMultiplicity, values.size())) {
throw new PureExecutionException(functionExpressionToUseInStack.getSourceInformation(), "Cannot cast a collection of size " + values.size() + " to multiplicity " + Multiplicity.print(returnMultiplicity));
}
CoreInstance result = this.repository.newAnonymousCoreInstance(param.getSourceInformation(), param.getClassifier());
Instance.addValueToProperty(result, M3Properties.genericType, Instance.getValueForMetaPropertyToOneResolved(param, M3Properties.genericType, processorSupport), processorSupport);
Instance.setValuesForProperty(result, M3Properties.values, values, processorSupport);
Instance.addValueToProperty(result, M3Properties.multiplicity, returnMultiplicity, processorSupport);
return result;
}
use of org.finos.legend.pure.m3.compiler.postprocessing.VariableContext in project legend-pure by finos.
the class Cast method execute.
@Override
public CoreInstance execute(ListIterable<? extends CoreInstance> params, Stack<MutableMap<String, CoreInstance>> resolvedTypeParameters, Stack<MutableMap<String, CoreInstance>> resolvedMultiplicityParameters, VariableContext variableContext, CoreInstance functionExpressionToUseInStack, Profiler profiler, InstantiationContext instantiationContext, ExecutionSupport executionSupport, Context context, ProcessorSupport processorSupport) throws PureExecutionException {
CoreInstance valuesParam = params.get(0);
CoreInstance sourceGenericType = valuesParam.getValueForMetaPropertyToOne(M3Properties.genericType);
CoreInstance targetGenericType = params.get(1).getValueForMetaPropertyToOne(M3Properties.genericType);
targetGenericType = makeGenericTypeAsConcreteAsPossible(targetGenericType, resolvedTypeParameters, resolvedMultiplicityParameters, processorSupport);
CoreInstance inst = this.repository.newAnonymousCoreInstance(functionExpressionToUseInStack.getSourceInformation(), valuesParam.getClassifier());
Instance.addValueToProperty(inst, M3Properties.genericType, targetGenericType, processorSupport);
Instance.addValueToProperty(inst, M3Properties.multiplicity, Instance.getValueForMetaPropertyToOneResolved(valuesParam, M3Properties.multiplicity, processorSupport), processorSupport);
if (GenericTypeMatch.genericTypeMatches(targetGenericType, sourceGenericType, true, ParameterMatchBehavior.MATCH_CAUTIOUSLY, ParameterMatchBehavior.MATCH_CAUTIOUSLY, processorSupport)) {
CoreInstance sourceRawType = Instance.getValueForMetaPropertyToOneResolved(sourceGenericType, M3Properties.rawType, processorSupport);
CoreInstance targetRawType = Instance.getValueForMetaPropertyToOneResolved(targetGenericType, M3Properties.rawType, processorSupport);
// If up-casting unit type to measure type, keep unit type.
if (sourceRawType instanceof Unit && targetRawType instanceof Measure) {
Instance.setValueForProperty(inst, M3Properties.genericType, sourceGenericType, processorSupport);
}
// Up cast (e.g., List<Integer> to Any) - no further type checking required
Instance.setValuesForProperty(inst, M3Properties.values, valuesParam.getValueForMetaPropertyToMany(M3Properties.values), processorSupport);
} else {
// Down cast (e.g., Number to Integer) - must check types of individual values
ListIterable<? extends CoreInstance> values = valuesParam.getValueForMetaPropertyToMany(M3Properties.values);
for (CoreInstance val : values) {
CoreInstance valGenericType = Instance.extractGenericTypeFromInstance(val, processorSupport);
if (!GenericTypeMatch.genericTypeMatches(targetGenericType, valGenericType, true, ParameterMatchBehavior.MATCH_ANYTHING, ParameterMatchBehavior.MATCH_ANYTHING, processorSupport)) {
throw new PureExecutionException(functionExpressionToUseInStack.getSourceInformation(), "Cast exception: " + GenericType.print(valGenericType, processorSupport) + " cannot be cast to " + GenericType.print(targetGenericType, processorSupport));
}
}
Instance.setValuesForProperty(inst, M3Properties.values, valuesParam.getValueForMetaPropertyToMany(M3Properties.values), processorSupport);
}
return inst;
}
use of org.finos.legend.pure.m3.compiler.postprocessing.VariableContext in project legend-pure by finos.
the class Copy method execute.
@Override
public CoreInstance execute(ListIterable<? extends CoreInstance> params, Stack<MutableMap<String, CoreInstance>> resolvedTypeParameters, Stack<MutableMap<String, CoreInstance>> resolvedMultiplicityParameters, VariableContext variableContext, final CoreInstance functionExpressionToUseInStack, Profiler profiler, final InstantiationContext instantiationContext, final ExecutionSupport executionSupport, final Context context, final ProcessorSupport processorSupport) throws PureExecutionException {
final CoreInstance instance = Instance.getValueForMetaPropertyToOneResolved(params.get(0), M3Properties.values, processorSupport);
CoreInstance classifierGenericType = Instance.extractGenericTypeFromInstance(instance, processorSupport);
final CoreInstance sourceClassifier = Instance.getValueForMetaPropertyToOneResolved(classifierGenericType, M3Properties.rawType, processorSupport);
instantiationContext.push(sourceClassifier);
// TODO should we start a repository transaction here?
final CoreInstance newInstance = this.repository.newEphemeralAnonymousCoreInstance(null, sourceClassifier);
ListIterable<? extends CoreInstance> keyValues = (params.size() > 2) ? Instance.getValueForMetaPropertyToManyResolved(params.get(2), M3Properties.values, processorSupport) : Lists.immutable.<CoreInstance>with();
MutableSet<CoreInstance> addedValues = UnifiedSet.newSet();
MutableMap<CoreInstance, MutableMap> propertyTree = Maps.mutable.empty();
// Add the modified properties
VariableContext evaluationVariableContext = getParentOrEmptyVariableContext(variableContext);
for (CoreInstance keyValue : keyValues) {
CoreInstance classifier = sourceClassifier;
// Find Property and newInstanceCurrent
ListIterable<? extends CoreInstance> keys = Instance.getValueForMetaPropertyToManyResolved(Instance.getValueForMetaPropertyToOneResolved(keyValue, M3Properties.key, processorSupport), M3Properties.values, processorSupport);
String finalPropertyName = keys.getLast().getName();
CoreInstance property = null;
CoreInstance newInstanceCurrent = newInstance;
CoreInstance instanceCurrent = instance;
int size = keys.size() - 1;
MutableMap<CoreInstance, MutableMap> treeNode = propertyTree;
for (CoreInstance key : keys) {
property = processorSupport.class_findPropertyUsingGeneralization(classifier, key.getName());
if (property == null) {
throw new PureExecutionException(Instance.getValueForMetaPropertyToOneResolved(keyValue, M3Properties.key, processorSupport).getSourceInformation(), "The property '" + key.getName() + "' can't be found in the type '" + classifier.getName() + "' or in its hierarchy.");
}
treeNode = treeNode.getIfAbsentPut(property, Maps.mutable.empty());
classifier = Instance.getValueForMetaPropertyToOneResolved(property, M3Properties.genericType, M3Properties.rawType, processorSupport);
if (size > 0) {
if (Multiplicity.isToOne(Instance.getValueForMetaPropertyToOneResolved(property, M3Properties.multiplicity, processorSupport), false)) {
instanceCurrent = Instance.getValueForMetaPropertyToOneResolved(instanceCurrent, property, processorSupport);
CoreInstance res = Instance.getValueForMetaPropertyToOneResolved(newInstanceCurrent, property, processorSupport);
if (res == null) {
res = this.repository.newEphemeralAnonymousCoreInstance(null, classifier);
Instance.addValueToProperty(newInstanceCurrent, key.getName(), res, processorSupport);
}
newInstanceCurrent = res;
} else {
throw new RuntimeException("Not supported yet!");
}
}
size--;
}
// Maybe add the existing ones
CoreInstance addValue = Instance.getValueForMetaPropertyToOneResolved(keyValue, M3Properties.add, processorSupport);
boolean add = (addValue != null) && PrimitiveUtilities.getBooleanValue(addValue);
if (add) {
ListIterable<? extends CoreInstance> existingOnes = Instance.getValueForMetaPropertyToManyResolved(instanceCurrent, property, processorSupport);
for (CoreInstance existing : existingOnes) {
Instance.addValueToProperty(newInstanceCurrent, finalPropertyName, existing, processorSupport);
addedValues.add(existing);
}
}
// Add the requested ones
CoreInstance propertyGenericType = GenericType.resolvePropertyReturnType(Instance.extractGenericTypeFromInstance(instanceCurrent, processorSupport), property, processorSupport);
CoreInstance expression = Instance.getValueForMetaPropertyToOneResolved(keyValue, M3Properties.expression, processorSupport);
Executor executor = FunctionExecutionInterpreted.findValueSpecificationExecutor(expression, functionExpressionToUseInStack, processorSupport, this.functionExecution);
CoreInstance instanceValResult = executor.execute(expression, resolvedTypeParameters, resolvedMultiplicityParameters, functionExpressionToUseInStack, evaluationVariableContext, profiler, instantiationContext, executionSupport, this.functionExecution, processorSupport);
ListIterable<? extends CoreInstance> values = Instance.getValueForMetaPropertyToManyResolved(instanceValResult, M3Properties.values, processorSupport);
New.validateRangeUsingMultiplicity(instance, keyValue, property, values, processorSupport);
if (values.isEmpty()) {
if (newInstanceCurrent.isValueDefinedForKey(finalPropertyName)) {
if (!add) {
Instance.removeProperty(newInstanceCurrent, finalPropertyName, processorSupport);
Instance.addPropertyWithEmptyList(newInstanceCurrent, finalPropertyName, processorSupport);
}
}
} else {
New.validateTypeFromGenericType(propertyGenericType, Instance.getValueForMetaPropertyToOneResolved(instanceValResult, M3Properties.genericType, processorSupport), expression, processorSupport);
for (CoreInstance value : values) {
Instance.addValueToProperty(newInstanceCurrent, finalPropertyName, value, processorSupport);
addedValues.add(value);
}
}
}
this.copy(instance, newInstance, sourceClassifier, addedValues, functionExpressionToUseInStack.getSourceInformation(), processorSupport, instantiationContext, propertyTree);
if (addedValues.isEmpty()) {
newInstance.setSourceInformation(instance.getSourceInformation());
} else {
newInstance.setSourceInformation(functionExpressionToUseInStack.getSourceInformation());
}
CoreInstance value = ValueSpecificationBootstrap.wrapValueSpecification(newInstance, ValueSpecification.isExecutable(params.get(0), processorSupport), processorSupport);
instantiationContext.popAndExecuteProcedures(value);
if (instantiationContext.isEmpty()) {
instantiationContext.runValidations();
instantiationContext.reset();
}
return DefaultConstraintHandler.handleConstraints(sourceClassifier, value, functionExpressionToUseInStack.getSourceInformation(), this.functionExecution, resolvedTypeParameters, resolvedMultiplicityParameters, variableContext, functionExpressionToUseInStack, profiler, instantiationContext, executionSupport);
}
Aggregations