Skip to content

Commit

Permalink
Fix Dynamic Eval with Default values (#861)
Browse files Browse the repository at this point in the history
* Fix Dynamic Eval with Default values

* Fix small issues
  • Loading branch information
pierredebelen authored Sep 12, 2024
1 parent fe60a53 commit 4663cec
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ Class meta::pure::functions::lang::tests::dynamicNew::D_D
name : String[1];
}


Class meta::pure::functions::lang::tests::dynamicNew::ClassWithDefault
{
name : String[1] = 'default_X_Y';
other : String[1];
optional : String[0..1];
}

function meta::pure::functions::lang::tests::dynamicNew::getterOverrideToMany(o:Any[1], property:Property<Nil,Any|*>[1]):Any[*]
{
[^D_D(name = $o->cast(@D_A).a + $o->getHiddenPayload()->cast(@String)->toOne()), ^D_D(name = $o->cast(@D_A).b->toOne() + $o->getHiddenPayload()->cast(@String)->toOne())]
Expand All @@ -57,6 +65,34 @@ function meta::pure::functions::lang::tests::dynamicNew::getterOverrideToOne(o:A
^D_D(name = $o->cast(@D_A).a + $o->getHiddenPayload()->cast(@String)->toOne());
}

function <<test.Test>> meta::pure::functions::lang::tests::dynamicNew::testDynamicNewWithDefault():Boolean[1]
{
assertEquals('default_X_Y', dynamicNew(ClassWithDefault, [^KeyValue(key='other',value='rrr')])->cast(@ClassWithDefault).name);

let x = [^KeyValue(key='other',value='rrr')];
assertEquals('default_X_Y', dynamicNew(ClassWithDefault, $x)->cast(@ClassWithDefault).name);

let c = ClassWithDefault;
assertEquals('default_X_Y', dynamicNew($c, [^KeyValue(key='other',value='rrr')])->cast(@ClassWithDefault).name);

let c_any = ClassWithDefault->cast(@Class<Any>);
assertEquals('default_X_Y', dynamicNew($c_any, [^KeyValue(key='other',value='rrr')])->cast(@ClassWithDefault).name);
}

function <<test.Test>> meta::pure::functions::lang::tests::dynamicNew::testDynamicNewWithDefaultAndSet():Boolean[1]
{
assertEquals('NewVal', dynamicNew(ClassWithDefault, [^KeyValue(key='other',value='rrr'), ^KeyValue(key='name',value='NewVal')])->cast(@ClassWithDefault).name);

let x = [^KeyValue(key='other',value='rrr'), ^KeyValue(key='name',value='NewVal')];
assertEquals('NewVal', dynamicNew(ClassWithDefault, $x)->cast(@ClassWithDefault).name);

let c = ClassWithDefault;
assertEquals('NewVal', dynamicNew($c, [^KeyValue(key='other',value='rrr'), ^KeyValue(key='name',value='NewVal')])->cast(@ClassWithDefault).name);

let c_any = ClassWithDefault->cast(@Class<Any>);
assertEquals('NewVal', dynamicNew($c_any, [^KeyValue(key='other',value='rrr'), ^KeyValue(key='name',value='NewVal')])->cast(@ClassWithDefault).name);
}

function <<test.Test>> meta::pure::functions::lang::tests::dynamicNew::testSimpleDynamicNew():Boolean[1]
{
let a = D_A;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,10 @@ public DynamicNew()
@Override
public ListIterable<String> transformParameterValues(ListIterable<? extends CoreInstance> parametersValues, CoreInstance topLevelElement, ProcessorSupport processorSupport, ProcessorContext processorContext)
{
ListIterable<String> defaultValues = transformDefaultValues(parametersValues.get(0), processorSupport, processorContext);

MutableList<String> transformedParams = Lists.mutable.ofInitialCapacity(parametersValues.size());
parametersValues.forEachWithIndex((parameterValue, index) ->
{
if (defaultValues.notEmpty() && index == 1)
{
ListIterable<? extends CoreInstance> values = Instance.getValueForMetaPropertyToManyResolved(parameterValue, M3Properties.values, processorSupport);
String type = TypeProcessor.typeToJavaObjectSingle(Instance.getValueForMetaPropertyToOneResolved(parameterValue, M3Properties.genericType, processorSupport), true, processorSupport);

MutableList<String> processedValues = values.collect(v -> ValueSpecificationProcessor.processValueSpecification(topLevelElement, v, processorContext), Lists.mutable.withAll(defaultValues));
transformedParams.add(processedValues.size() > 1 ? "Lists.mutable.<" + type + ">with(" + processedValues.makeString(",") + ")" : processedValues.makeString(","));
}
else
{
transformedParams.add(ValueSpecificationProcessor.processValueSpecification(topLevelElement, parameterValue, processorContext));
}
});

return transformedParams;
Expand Down Expand Up @@ -119,18 +106,4 @@ public String build(CoreInstance topLevelElement, CoreInstance functionExpressio
String newObjectStatement = newObject + "," + newOverrideInstance + "," + getterOverrides + ",es)";
return "Pure.handleValidation(false," + newObjectStatement + "," + SourceInfoProcessor.sourceInfoToString(functionExpression.getSourceInformation()) + ",es)";
}

private ListIterable<String> transformDefaultValues(CoreInstance instance, ProcessorSupport processorSupport, ProcessorContext processorContext)
{
CoreInstance genericType = Instance.getValueForMetaPropertyToOneResolved(instance, M3Properties.genericType, M3Properties.typeArguments, processorSupport);

return genericType != null ? InstantiationHelpers.manageDefaultValues(this::formatDefaultValueString,
Instance.getValueForMetaPropertyToOneResolved(genericType, M3Properties.rawType, processorSupport), true, processorContext).select(s -> !s.isEmpty())
: Lists.immutable.empty();
}

private String formatDefaultValueString(String name, String value)
{
return "new org.finos.legend.pure.generated.Root_meta_pure_functions_lang_KeyValue_Impl(\"Anonymous_NoCounter\")._key(\"" + name + "\")._value(" + value + ")";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,40 +127,6 @@ else if (!isNull && (Multiplicity.isLowerZero(expressionMultiplicity) || Multipl
}).makeString("");
}

public static ListIterable<String> manageDefaultValues(BiFunction<String, String, String> formatString, CoreInstance sourceClass, boolean doSingleWrap, ProcessorContext processorContext)
{
ProcessorSupport processorSupport = processorContext.getSupport();
ListIterable<? extends CoreInstance> properties = sourceClass.getValueForMetaPropertyToMany(M3Properties.properties);

return properties.collect(coreInstance ->
{
if (coreInstance.getValueForMetaPropertyToOne(M3Properties.defaultValue) == null)
{
return "";
}

boolean propertyIsToOne = Multiplicity.isToOne(Instance.getValueForMetaPropertyToOneResolved(coreInstance, M3Properties.multiplicity, processorSupport), false);
CoreInstance expression = Property.getDefaultValueExpression(Instance.getValueForMetaPropertyToOneResolved(coreInstance, M3Properties.defaultValue, processorSupport));
String value = ValueSpecificationProcessor.processValueSpecification(expression, processorContext);
if ("this".equals(value))
{
CoreInstance expressionRawType = Instance.getValueForMetaPropertyToOneResolved(Instance.getValueForMetaPropertyToOneResolved(expression, M3Properties.genericType, processorSupport), M3Properties.rawType, processorSupport);
value = PackageableElement.getSystemPathForPackageableElement(expressionRawType, "_") + processorContext.getClassImplSuffix() + "." + value;
}

CoreInstance expressionMultiplicity = Multiplicity.newMultiplicity(expression.getValueForMetaPropertyToMany(M3Properties.values).size(), processorSupport);

if ((doSingleWrap || !propertyIsToOne)
&& (Multiplicity.isLowerZero(expressionMultiplicity) || Multiplicity.isToOne(expressionMultiplicity)))
{
//wrap
value = "CompiledSupport.toPureCollection(" + value + ")";
}

return formatString.apply(coreInstance.getName(), value);
});
}

public static String manageId(ListIterable<? extends CoreInstance> parametersValues, ProcessorSupport processorSupport)
{
String id = Instance.getValueForMetaPropertyToOneResolved(parametersValues.get(1), M3Properties.values, processorSupport).getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.finos.legend.pure.runtime.java.compiled.generation.processors.natives.AbstractNative;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.type.FullJavaPaths;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.type.TypeProcessor;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.type._class.DefaultValue;

public class New extends AbstractNative
{
Expand Down Expand Up @@ -55,7 +56,7 @@ public String build(CoreInstance topLevelElement, CoreInstance functionExpressio
return "new " + JavaPackageAndImportBuilder.buildImplClassReferenceFromType(_class) + (addGenericType ? TypeProcessor.buildTypeArgumentsString(genericType, false, processorSupport) : "")
+ "(\"" + newId + "\")" + (addGenericType ? "._classifierGenericType("
+ InstantiationHelpers.buildGenericType(genericType, processorContext) + ")" : "") + (_Class.computeConstraintsInHierarchy(_class, processorSupport).isEmpty() ? "" : "._validate(false, " + SourceInfoProcessor.sourceInfoToString(functionExpression.getSourceInformation()) + ", es)")
+ InstantiationHelpers.manageDefaultValues(this::formatDefaultValueString, Instance.getValueForMetaPropertyToOneResolved(genericType, M3Properties.rawType, processorSupport), false, processorContext).makeString("");
+ DefaultValue.manageDefaultValues(this::formatDefaultValueString, Instance.getValueForMetaPropertyToOneResolved(genericType, M3Properties.rawType, processorSupport), false, processorContext).makeString("");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.finos.legend.pure.runtime.java.compiled.generation.processors.natives.AbstractNative;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.type.FullJavaPaths;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.type.TypeProcessor;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.type._class.DefaultValue;

public class NewWithKeyExpr extends AbstractNative
{
Expand All @@ -50,7 +51,7 @@ public String build(CoreInstance topLevelElement, CoreInstance functionExpressio
return "new " + JavaPackageAndImportBuilder.buildImplClassReferenceFromType(_class) + (addGenericType ? TypeProcessor.buildTypeArgumentsString(genericType, false, processorSupport) : "")
+ "(\"" + newId + "\")" + (addGenericType ? "._classifierGenericType("
+ InstantiationHelpers.buildGenericType(genericType, processorContext) + ")" : "")
+ InstantiationHelpers.manageDefaultValues(this::formatDefaultValueString, Instance.getValueForMetaPropertyToOneResolved(genericType, M3Properties.rawType, processorSupport), false, processorContext).makeString("")
+ DefaultValue.manageDefaultValues(this::formatDefaultValueString, Instance.getValueForMetaPropertyToOneResolved(genericType, M3Properties.rawType, processorSupport), false, processorContext).makeString("")
+ InstantiationHelpers.manageKeyValues(genericType, Instance.getValueForMetaPropertyToOneResolved(genericType, M3Properties.rawType, processorSupport), keyValues, processorContext)
+ (_Class.computeConstraintsInHierarchy(_class, processorSupport).isEmpty() ? "" : "._validate(false, " + SourceInfoProcessor.sourceInfoToString(functionExpression.getSourceInformation()) + ", es)");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@

package org.finos.legend.pure.runtime.java.compiled.generation.processors.support.coreinstance;

import org.eclipse.collections.api.RichIterable;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.api.tuple.Pair;
import org.finos.legend.pure.m3.execution.ExecutionSupport;
import org.finos.legend.pure.m4.coreinstance.AbstractCoreInstance;
import org.finos.legend.pure.m4.coreinstance.CoreInstance;
import org.finos.legend.pure.m4.coreinstance.compileState.CompileState;
Expand Down Expand Up @@ -100,4 +105,9 @@ public boolean equals(Object obj)
{
return this.pureEquals(obj);
}

public MutableList<? extends Pair<? extends String, ? extends RichIterable>> defaultValues(ExecutionSupport es)
{
return Lists.mutable.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import org.finos.legend.pure.runtime.java.compiled.generation.processors.type.TypeProcessor;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.valuespecification.ValueSpecificationProcessor;

import java.util.function.BiFunction;

public class ClassImplProcessor
{
//DO NOT ADD WIDE * IMPORTS TO THIS LIST IT IMPACTS COMPILE TIMES
Expand Down Expand Up @@ -95,6 +97,15 @@ public static StringJavaSource buildImplementation(String _package, String impor
String classNamePlusTypeParams = className + typeParamsString;
String interfaceNamePlusTypeParams = TypeProcessor.javaInterfaceForType(_class) + typeParamsString;

ListIterable<String> defaultValues = DefaultValue.manageDefaultValues(new BiFunction<String, String, String>()
{
@Override
public String apply(String name, String value)
{
return "org.eclipse.collections.impl.tuple.Tuples.pair(\"" + name + "\", " + value + ")";
}
}, _class, true, processorContext).select(s -> !s.isEmpty());

boolean isGetterOverride = M3Paths.GetterOverride.equals(PackageableElement.getUserPathForPackageableElement(_class)) ||
M3Paths.ConstraintsGetterOverride.equals(PackageableElement.getUserPathForPackageableElement(_class));

Expand Down Expand Up @@ -146,6 +157,12 @@ public static StringJavaSource buildImplementation(String _package, String impor
buildGetFullSystemPath() +
//Not supported on platform classes yet
(ClassProcessor.isPlatformClass(_class) ? "" : validate(_class, className, classGenericType, processorContext, processorSupport.class_getSimpleProperties(_class))) +
(defaultValues.isEmpty() ? "" :
" @Override\n" +
" public MutableList<? extends org.eclipse.collections.api.tuple.Pair<? extends String, ? extends RichIterable>> defaultValues(ExecutionSupport es)\n" +
" {\n" +
" return Lists.mutable.with(" + defaultValues.makeString(",") + ");\n" +
" }") +
"}");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2024 Goldman Sachs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.finos.legend.pure.runtime.java.compiled.generation.processors.type._class;

import org.eclipse.collections.api.list.ListIterable;
import org.finos.legend.pure.m3.navigation.Instance;
import org.finos.legend.pure.m3.navigation.M3Properties;
import org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement;
import org.finos.legend.pure.m3.navigation.ProcessorSupport;
import org.finos.legend.pure.m3.navigation.multiplicity.Multiplicity;
import org.finos.legend.pure.m3.navigation.property.Property;
import org.finos.legend.pure.m4.coreinstance.CoreInstance;
import org.finos.legend.pure.runtime.java.compiled.generation.ProcessorContext;
import org.finos.legend.pure.runtime.java.compiled.generation.processors.valuespecification.ValueSpecificationProcessor;

import java.util.function.BiFunction;

public class DefaultValue
{
public static ListIterable<String> manageDefaultValues(BiFunction<String, String, String> formatString, CoreInstance sourceClass, boolean doSingleWrap, ProcessorContext processorContext)
{
ProcessorSupport processorSupport = processorContext.getSupport();
ListIterable<? extends CoreInstance> properties = sourceClass.getValueForMetaPropertyToMany(M3Properties.properties);

return properties.collect(coreInstance ->
{
if (coreInstance.getValueForMetaPropertyToOne(M3Properties.defaultValue) == null)
{
return "";
}

boolean propertyIsToOne = Multiplicity.isToOne(Instance.getValueForMetaPropertyToOneResolved(coreInstance, M3Properties.multiplicity, processorSupport), false);
CoreInstance expression = Property.getDefaultValueExpression(Instance.getValueForMetaPropertyToOneResolved(coreInstance, M3Properties.defaultValue, processorSupport));
String value = ValueSpecificationProcessor.processValueSpecification(expression, processorContext);
if ("this".equals(value))
{
CoreInstance expressionRawType = Instance.getValueForMetaPropertyToOneResolved(Instance.getValueForMetaPropertyToOneResolved(expression, M3Properties.genericType, processorSupport), M3Properties.rawType, processorSupport);
value = PackageableElement.getSystemPathForPackageableElement(expressionRawType, "_") + processorContext.getClassImplSuffix() + "." + value;
}

CoreInstance expressionMultiplicity = Multiplicity.newMultiplicity(expression.getValueForMetaPropertyToMany(M3Properties.values).size(), processorSupport);

if ((doSingleWrap || !propertyIsToOne)
&& (Multiplicity.isLowerZero(expressionMultiplicity) || Multiplicity.isToOne(expressionMultiplicity)))
{
//wrap
value = "CompiledSupport.toPureCollection(" + value + ")";
}

return formatString.apply(coreInstance.getName(), value);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ private void validateClassLoaderForLegacyMethods(ClassLoader classLoader)
}
}

public Class<?> getIfAbsentPutImplForType(Type type)
{
TypeJavaInfo java = getJavaInfoForType(type);
return java.implClass;
}

public Class<?> getIfAbsentPutInterfaceForType(Type type)
{
TypeJavaInfo java = getJavaInfoForType(type);
Expand Down
Loading

0 comments on commit 4663cec

Please sign in to comment.