From 45aa09526bf625f8b1327eaf5327fa9d7ee185d5 Mon Sep 17 00:00:00 2001 From: Rafael Bey <24432403+rafaelbey@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:33:17 -0500 Subject: [PATCH] Introduce compiler api to get generic type of a Lambda (#3300) --- .../language/pure/compiler/Compiler.java | 23 ++++++++- .../language/pure/compiler/CompilerTest.java | 48 +++++++++++++++++++ .../protocol/vX_X_X/models/metamodel.pure | 11 +++++ .../protocol/vX_X_X/transfers/metamodel.pure | 35 ++++++++++---- .../pom.xml | 5 ++ .../compiler/test/TestRelationFunctions.java | 25 ++++++++++ 6 files changed, 136 insertions(+), 11 deletions(-) create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/test/java/org/finos/legend/engine/language/pure/compiler/CompilerTest.java diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/Compiler.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/Compiler.java index 0d7d00c5f5d..319daa902d7 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/Compiler.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/Compiler.java @@ -14,6 +14,7 @@ package org.finos.legend.engine.language.pure.compiler; +import java.io.IOException; import org.finos.legend.engine.language.pure.compiler.toPureGraph.CompileContext; import org.finos.legend.engine.language.pure.compiler.toPureGraph.HelperModelBuilder; import org.finos.legend.engine.language.pure.compiler.toPureGraph.HelperValueSpecificationBuilder; @@ -22,13 +23,18 @@ import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModelProcessParameter; import org.finos.legend.engine.language.pure.compiler.toPureGraph.RelationTypeHelper; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; +import org.finos.legend.engine.protocol.pure.v1.model.type.GenericType; import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; +import org.finos.legend.engine.shared.core.ObjectMapperFactory; import org.finos.legend.engine.shared.core.deployment.DeploymentMode; import org.finos.legend.engine.shared.core.operational.Assert; +import org.finos.legend.pure.generated.Root_meta_protocols_pure_vX_X_X_metamodel_type_GenericType; +import org.finos.legend.pure.generated.core_pure_protocol_protocol; +import org.finos.legend.pure.generated.core_pure_protocol_vX_X_X_transfers_metamodel; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relation.RelationType; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification; import org.finos.legend.pure.runtime.java.compiled.metadata.Metadata; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; public class Compiler { @@ -76,4 +82,19 @@ public static String getLambdaReturnType(Lambda lambda, PureModel pureModel) ValueSpecification valueSpecification = getLambdaRawType(lambda, pureModel); return HelperModelBuilder.getTypeFullPath(valueSpecification._genericType()._rawType(), pureModel.getExecutionSupport()); } + + public static GenericType getLambdaReturnGenericType(Lambda lambda, PureModel pureModel) + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType genericType = getLambdaRawType(lambda, pureModel)._genericType(); + Root_meta_protocols_pure_vX_X_X_metamodel_type_GenericType protocolGenericType = core_pure_protocol_vX_X_X_transfers_metamodel.Root_meta_protocols_pure_vX_X_X_transformation_fromPureGraph_domain_transformGenericType_GenericType_1__GenericType_1_(genericType, pureModel.getExecutionSupport()); + String json = core_pure_protocol_protocol.Root_meta_alloy_metadataServer_alloyToJSON_Any_1__String_1_(protocolGenericType, pureModel.getExecutionSupport()); + try + { + return ObjectMapperFactory.getNewStandardObjectMapperWithPureProtocolExtensionSupports().readValue(json, GenericType.class); + } + catch (IOException e) + { + throw new UnsupportedOperationException(e); + } + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/test/java/org/finos/legend/engine/language/pure/compiler/CompilerTest.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/test/java/org/finos/legend/engine/language/pure/compiler/CompilerTest.java new file mode 100644 index 00000000000..453b55faab5 --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/test/java/org/finos/legend/engine/language/pure/compiler/CompilerTest.java @@ -0,0 +1,48 @@ +// 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.engine.language.pure.compiler; + +import java.util.stream.Collectors; +import org.eclipse.collections.api.factory.Lists; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; +import org.finos.legend.engine.language.pure.grammar.from.PureGrammarParser; +import org.finos.legend.engine.protocol.pure.v1.model.type.GenericType; +import org.finos.legend.engine.protocol.pure.v1.model.type.PackageableType; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; +import org.junit.Assert; +import org.junit.Test; + +public class CompilerTest +{ + @Test + public void getLambdaReturnGenericTypeForPrimitive() + { + Lambda lambda = PureGrammarParser.newInstance().parseLambda("|1234"); + GenericType genericType = Compiler.getLambdaReturnGenericType(lambda, PureModel.getCorePureModel()); + Assert.assertTrue(genericType.rawType instanceof PackageableType); + Assert.assertEquals("Integer", ((PackageableType) genericType.rawType).fullPath); + } + + @Test + public void getLambdaReturnGenericTypeWithTypeArguments() + { + Lambda lambda = PureGrammarParser.newInstance().parseLambda("|pair(1, '2')"); + GenericType genericType = Compiler.getLambdaReturnGenericType(lambda, PureModel.getCorePureModel()); + Assert.assertTrue(genericType.rawType instanceof PackageableType); + Assert.assertEquals("meta::pure::functions::collection::Pair", ((PackageableType) genericType.rawType).fullPath); + Assert.assertEquals(Lists.mutable.with("Integer", "String"), genericType.typeArguments.stream().map(x -> ((PackageableType) x.rawType).fullPath).collect(Collectors.toList())); + } +} diff --git a/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/protocol/vX_X_X/models/metamodel.pure b/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/protocol/vX_X_X/models/metamodel.pure index 6e97fa4a4bb..1e81f9312ff 100644 --- a/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/protocol/vX_X_X/models/metamodel.pure +++ b/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/protocol/vX_X_X/models/metamodel.pure @@ -264,6 +264,17 @@ Class meta::protocols::pure::vX_X_X::metamodel::type::PackageableType extends me } +Class meta::protocols::pure::vX_X_X::metamodel::type::RelationType extends meta::protocols::pure::vX_X_X::metamodel::type::Type +{ + columns: meta::protocols::pure::vX_X_X::metamodel::type::Column[*]; +} + +Class meta::protocols::pure::vX_X_X::metamodel::type::Column +{ + name: String[1]; + type: String[1]; +} + Class meta::protocols::pure::vX_X_X::metamodel::type::GenericType { rawType : meta::protocols::pure::vX_X_X::metamodel::type::Type[1]; diff --git a/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/protocol/vX_X_X/transfers/metamodel.pure b/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/protocol/vX_X_X/transfers/metamodel.pure index e8c510fd641..b34bb74593b 100644 --- a/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/protocol/vX_X_X/transfers/metamodel.pure +++ b/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/protocol/vX_X_X/transfers/metamodel.pure @@ -140,16 +140,31 @@ function meta::protocols::pure::vX_X_X::transformation::fromPureGraph::domain::t function meta::protocols::pure::vX_X_X::transformation::fromPureGraph::domain::transformGenericType(genericType:GenericType[1]):meta::protocols::pure::vX_X_X::metamodel::type::GenericType[1] { - ^meta::protocols::pure::vX_X_X::metamodel::type::GenericType - ( - rawType = ^meta::protocols::pure::vX_X_X::metamodel::type::PackageableType - ( - _type='packageableType', - fullPath=$genericType.rawType->toOne()->elementToPath() - ), - typeArguments = $genericType.typeArguments->map(ta|$ta->transformGenericType()), - multiplicityArguments = $genericType.multiplicityArguments->map(ma|$ma->meta::protocols::pure::vX_X_X::transformation::fromPureGraph::domain::transformMultiplicity()) - ) + let rawType = $genericType.rawType->match([ + rel: meta::pure::metamodel::relation::RelationType[1] | ^meta::protocols::pure::vX_X_X::metamodel::type::RelationType + ( + _type='relationType', + columns=$rel.columns->map(c | + ^meta::protocols::pure::vX_X_X::metamodel::type::Column + ( + name = $c.name->toOne(), + type = $c.classifierGenericType.typeArguments->at(1).rawType->toOne()->elementToPath() + ) + ) + ), + type: Type[1] | ^meta::protocols::pure::vX_X_X::metamodel::type::PackageableType + ( + _type='packageableType', + fullPath=$genericType.rawType->toOne()->elementToPath() + ) + ]); + + ^meta::protocols::pure::vX_X_X::metamodel::type::GenericType + ( + rawType = $rawType, + typeArguments = $genericType.typeArguments->map(ta|$ta->transformGenericType()), + multiplicityArguments = $genericType.multiplicityArguments->map(ma|$ma->meta::protocols::pure::vX_X_X::transformation::fromPureGraph::domain::transformMultiplicity()) + ); } function <> meta::protocols::pure::vX_X_X::transformation::fromPureGraph::domain::transformProperty(property:Property[1], extensions:meta::pure::extension::Extension[*]):meta::protocols::pure::vX_X_X::metamodel::domain::Property[1] diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/pom.xml b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/pom.xml index a8e47d7591e..1525aa719d7 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/pom.xml +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/pom.xml @@ -280,6 +280,11 @@ legend-engine-pure-runtime-java-extension-compiled-functions-json test + + net.javacrumbs.json-unit + json-unit + test + \ No newline at end of file diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/test/java/org/finos/legend/engine/language/pure/compiler/test/TestRelationFunctions.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/test/java/org/finos/legend/engine/language/pure/compiler/test/TestRelationFunctions.java index 4f2d30da3b9..39f78f99997 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/test/java/org/finos/legend/engine/language/pure/compiler/test/TestRelationFunctions.java +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/test/java/org/finos/legend/engine/language/pure/compiler/test/TestRelationFunctions.java @@ -14,6 +14,15 @@ package org.finos.legend.engine.language.pure.compiler.test; +import net.javacrumbs.jsonunit.JsonAssert; +import org.eclipse.collections.api.tuple.Pair; +import org.finos.legend.engine.language.pure.compiler.Compiler; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; +import org.finos.legend.engine.language.pure.grammar.from.PureGrammarParser; +import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; +import org.finos.legend.engine.protocol.pure.v1.model.type.GenericType; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; +import org.finos.legend.engine.shared.core.ObjectMapperFactory; import org.junit.Test; public class TestRelationFunctions extends TestCompilationFromGrammar.TestCompilationFromGrammarTestSuite @@ -33,6 +42,22 @@ public void testFilter() ); } + @Test + public void lambdaRelationReturnType() throws Exception + { + Pair pureModelPair = test( + "###Relational\n" + + "Database a::A (Table tb(id Integer))\n" + ); + + Lambda lambda = PureGrammarParser.newInstance().parseLambda("|#>{a::A.tb}#->select()"); + GenericType genericType = Compiler.getLambdaReturnGenericType(lambda, pureModelPair.getTwo()); + String actualValue = ObjectMapperFactory.getNewStandardObjectMapperWithPureProtocolExtensionSupports().writeValueAsString(genericType); + JsonAssert.assertJsonEquals( + "{\"multiplicityArguments\":[],\"rawType\":{\"_type\":\"packageableType\",\"fullPath\":\"meta::pure::store::RelationStoreAccessor\"},\"typeArguments\":[{\"multiplicityArguments\":[],\"rawType\":{\"_type\":\"relationType\",\"columns\":[{\"name\":\"id\",\"type\":\"Integer\"}]},\"typeArguments\":[],\"typeVariableValues\":[]}],\"typeVariableValues\":[]}", + actualValue); + } + @Test public void testFilterError() {