From a11bddcb742983f9ec5ea1bc2ecdb885031584a7 Mon Sep 17 00:00:00 2001 From: Hubert Plociniczak Date: Wed, 6 Dec 2023 10:03:06 +0100 Subject: [PATCH] Inline execution should support FQNs (#8454) * Test illustrating problems with FQNs Inline execution fails with `Compile error: The name `Standard` could not be found.`. * Ensure InlineContext carries Package Repos info Previously, there was no requirement that inline execution should allow for FQNs. This meant that the omission of Package Repository info went unnoticed. In order to be able to refer to `Standard.Visualization.Preprocessor` it has to be exported as well. --- .../Visualization/0.0.0-dev/src/Main.enso | 1 + .../enso/compiler/context/InlineContext.scala | 8 +- .../RuntimeVisualizationsTest.scala | 180 ++++++++++++++++++ .../node/expression/debug/EvalNode.java | 6 +- .../src/main/scala/org/enso/pkg/Package.scala | 4 + 5 files changed, 195 insertions(+), 4 deletions(-) diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Main.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Main.enso index a35c22bf67c..c4359fabb5a 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Main.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Main.enso @@ -7,4 +7,5 @@ import project.Preprocessor export project.Helpers export project.Id.Id +export project.Preprocessor from project.File_Upload export file_uploading diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/context/InlineContext.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/context/InlineContext.scala index bf15aaa806d..b09eb92b7e6 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/context/InlineContext.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/context/InlineContext.scala @@ -37,19 +37,23 @@ object InlineContext { * @param module the module defining the context * @param isInTailPosition whether or not the inline expression occurs in a * tail position + * @param compilerConfig the compiler configuration + * @param pkgRepo the compiler's package repository * @return the [[InlineContext]] instance corresponding to the arguments */ def fromJava( localScope: LocalScope, module: CompilerContext.Module, isInTailPosition: Option[Boolean], - compilerConfig: CompilerConfig + compilerConfig: CompilerConfig, + pkgRepo: Option[PackageRepository] ): InlineContext = { InlineContext( localScope = Option(localScope), module = ModuleContext(module, compilerConfig), isInTailPosition = isInTailPosition, - compilerConfig = compilerConfig + compilerConfig = compilerConfig, + pkgRepo = pkgRepo ) } diff --git a/engine/runtime-with-polyglot/src/test/scala/org/enso/interpreter/test/instrument/RuntimeVisualizationsTest.scala b/engine/runtime-with-polyglot/src/test/scala/org/enso/interpreter/test/instrument/RuntimeVisualizationsTest.scala index df9096dffc4..3f30657174b 100644 --- a/engine/runtime-with-polyglot/src/test/scala/org/enso/interpreter/test/instrument/RuntimeVisualizationsTest.scala +++ b/engine/runtime-with-polyglot/src/test/scala/org/enso/interpreter/test/instrument/RuntimeVisualizationsTest.scala @@ -3880,4 +3880,184 @@ class RuntimeVisualizationsTest } new String(data) shouldEqual "85" } + + it should "execute default visualization preprocessor" in { + val contextId = UUID.randomUUID() + val requestId = UUID.randomUUID() + val visualizationId = UUID.randomUUID() + val moduleName = "Enso_Test.Test.Main" + val metadata = new Metadata + + val idMain = metadata.addItem(60, 6) + + val code = + """import Standard.Visualization.Preprocessor + | + |main = + | fn = x -> x + | fn + |""".stripMargin.linesIterator.mkString("\n") + val contents = metadata.appendToCode(code) + val mainFile = context.writeMain(contents) + + // create context + context.send(Api.Request(requestId, Api.CreateContextRequest(contextId))) + context.receive shouldEqual Some( + Api.Response(requestId, Api.CreateContextResponse(contextId)) + ) + + // Open the new file + context.send( + Api.Request(requestId, Api.OpenFileRequest(mainFile, contents)) + ) + context.receive shouldEqual Some( + Api.Response(Some(requestId), Api.OpenFileResponse) + ) + + // push main + val item1 = Api.StackItem.ExplicitCall( + Api.MethodPointer(moduleName, moduleName, "main"), + None, + Vector() + ) + context.send( + Api.Request(requestId, Api.PushContextRequest(contextId, item1)) + ) + context.receiveNIgnorePendingExpressionUpdates( + 3 + ) should contain theSameElementsAs Seq( + Api.Response(requestId, Api.PushContextResponse(contextId)), + TestMessages.update( + contextId, + idMain, + ConstantsGen.FUNCTION + ), + context.executionComplete(contextId) + ) + + // execute expression + context.send( + Api.Request( + requestId, + Api.ExecuteExpression( + contextId, + visualizationId, + idMain, + "Preprocessor.default_preprocessor 85" + ) + ) + ) + val executeExpressionResponses = + context.receiveNIgnoreExpressionUpdates(3) + executeExpressionResponses should contain allOf ( + Api.Response(requestId, Api.VisualizationAttached()), + context.executionComplete(contextId) + ) + val Some(data) = executeExpressionResponses.collectFirst { + case Api.Response( + None, + Api.VisualizationUpdate( + Api.VisualizationContext( + `visualizationId`, + `contextId`, + `idMain` + ), + data + ) + ) => + data + } + new String(data) shouldEqual "85" + } + + it should "execute default visualization preprocessor with a FQN" in { + val contextId = UUID.randomUUID() + val requestId = UUID.randomUUID() + val visualizationId = UUID.randomUUID() + val moduleName = "Enso_Test.Test.Main" + val metadata = new Metadata + + val idMain = metadata.addItem(90, 6) + + val code = + """import Standard.Visualization + |import Standard.Visualization.Preprocessor + | + |main = + | fn = x -> x + | fn + |""".stripMargin.linesIterator.mkString("\n") + val contents = metadata.appendToCode(code) + val mainFile = context.writeMain(contents) + + // create context + context.send(Api.Request(requestId, Api.CreateContextRequest(contextId))) + context.receive shouldEqual Some( + Api.Response(requestId, Api.CreateContextResponse(contextId)) + ) + + // Open the new file + context.send( + Api.Request(requestId, Api.OpenFileRequest(mainFile, contents)) + ) + context.receive shouldEqual Some( + Api.Response(Some(requestId), Api.OpenFileResponse) + ) + + // push main + val item1 = Api.StackItem.ExplicitCall( + Api.MethodPointer(moduleName, moduleName, "main"), + None, + Vector() + ) + context.send( + Api.Request(requestId, Api.PushContextRequest(contextId, item1)) + ) + context.receiveNIgnorePendingExpressionUpdates( + 3 + ) should contain theSameElementsAs Seq( + Api.Response(requestId, Api.PushContextResponse(contextId)), + TestMessages.update( + contextId, + idMain, + ConstantsGen.FUNCTION + ), + context.executionComplete(contextId) + ) + + // execute expression + context.send( + Api.Request( + requestId, + Api.ExecuteExpression( + contextId, + visualizationId, + idMain, + "Standard.Visualization.Preprocessor.default_preprocessor 85" + ) + ) + ) + val executeExpressionResponses = + context.receiveNIgnoreExpressionUpdates(3) + executeExpressionResponses should contain allOf ( + Api.Response(requestId, Api.VisualizationAttached()), + context.executionComplete(contextId) + ) + val Some(data) = executeExpressionResponses.collectFirst { + case Api.Response( + None, + Api.VisualizationUpdate( + Api.VisualizationContext( + `visualizationId`, + `contextId`, + `idMain` + ), + data + ) + ) => + data + } + new String(data) shouldEqual "85" + } + } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/debug/EvalNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/debug/EvalNode.java index e0c036b62d1..2b73ee39398 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/debug/EvalNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/debug/EvalNode.java @@ -64,13 +64,15 @@ public abstract class EvalNode extends BaseNode { RootCallTarget parseExpression(LocalScope scope, ModuleScope moduleScope, String expression) { EnsoContext context = EnsoContext.get(this); LocalScope localScope = scope.createChild(); + var compiler = context.getCompiler(); InlineContext inlineContext = InlineContext.fromJava( localScope, moduleScope.getModule().asCompilerModule(), scala.Option.apply(getTailStatus() != TailStatus.NOT_TAIL), - context.getCompilerConfig()); - var compiler = context.getCompiler(); + context.getCompilerConfig(), + scala.Option.apply(compiler.packageRepository())); + var tuppleOption = compiler.runInline(expression, inlineContext); if (tuppleOption.isEmpty()) { throw new RuntimeException("Invalid code passed to `eval`: " + expression); diff --git a/lib/scala/pkg/src/main/scala/org/enso/pkg/Package.scala b/lib/scala/pkg/src/main/scala/org/enso/pkg/Package.scala index 1798b6cf8b8..44902213331 100644 --- a/lib/scala/pkg/src/main/scala/org/enso/pkg/Package.scala +++ b/lib/scala/pkg/src/main/scala/org/enso/pkg/Package.scala @@ -241,6 +241,10 @@ class Package[F]( .asScala .toList } + + override def toString: String = { + s"Package[$name]" + } } /** A class responsible for creating and parsing package structures.