From b58a5f458bf0b1ac2da2c8f09772feab9f7074bc Mon Sep 17 00:00:00 2001 From: Dmitry Bushev Date: Thu, 9 Feb 2023 14:49:39 +0300 Subject: [PATCH] Send method pointers of constructors (#5593) Closes #5043 Expression updates of constructors contain method pointers. --- .../test/instrument/RuntimeServerTest.scala | 85 ++++++++++++++++++- .../RuntimeVisualizationsTest.scala | 3 + .../instrument/IdExecutionService.java | 7 ++ .../atom/QualifiedAccessorNode.java | 5 ++ .../callable/atom/AtomConstructor.java | 8 +- .../runtime/callable/atom/BoxingAtom.java | 2 - 6 files changed, 101 insertions(+), 9 deletions(-) diff --git a/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala b/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala index ac2e99a85a7..ff5eb61142b 100644 --- a/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala +++ b/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala @@ -552,7 +552,7 @@ class RuntimeServerTest context.consumeOut shouldEqual List("1") } - it should "send method pointer updates" in { + it should "send method pointer updates of methods" in { val contextId = UUID.randomUUID() val requestId = UUID.randomUUID() val moduleName = "Enso_Test.Test.Main" @@ -621,7 +621,7 @@ class RuntimeServerTest Api.PushContextRequest( contextId, Api.StackItem.ExplicitCall( - Api.MethodPointer(moduleName, "Enso_Test.Test.Main", "main"), + Api.MethodPointer(moduleName, moduleName, "main"), None, Vector() ) @@ -646,7 +646,12 @@ class RuntimeServerTest ConstantsGen.INTEGER, Api.MethodPointer("Enso_Test.Test.Main", "Enso_Test.Test.Main", "bar") ), - TestMessages.update(contextId, idMainM, "Enso_Test.Test.A.AT"), + TestMessages.update( + contextId, + idMainM, + "Enso_Test.Test.A.AT", + Api.MethodPointer("Enso_Test.Test.A", "Enso_Test.Test.A.AT", "A") + ), TestMessages.update( contextId, idMainP, @@ -666,6 +671,80 @@ class RuntimeServerTest context.consumeOut shouldEqual List("79") } + it should "send method pointer updates of constructors" in { + val contextId = UUID.randomUUID() + val requestId = UUID.randomUUID() + val moduleName = "Enso_Test.Test.Main" + + val metadata = new Metadata + val idA = metadata.addItem(47, 3, "aa") + val idB = metadata.addItem(59, 6, "ab") + val idC = metadata.addItem(70, 7, "ac") + + val code = + """type T + | A + | B x + | C y z + | + |main = + | a = T.A + | b = T.B 42 + | T.C a b + |""".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 file + context.send( + Api.Request(Api.OpenFileNotification(mainFile, contents)) + ) + context.receiveNone shouldEqual None + + // push main + context.send( + Api.Request( + requestId, + Api.PushContextRequest( + contextId, + Api.StackItem.ExplicitCall( + Api.MethodPointer(moduleName, moduleName, "main"), + None, + Vector() + ) + ) + ) + ) + context.receiveN(5) should contain theSameElementsAs Seq( + Api.Response(requestId, Api.PushContextResponse(contextId)), + TestMessages.update( + contextId, + idA, + "Enso_Test.Test.Main.T", + Api.MethodPointer("Enso_Test.Test.Main", "Enso_Test.Test.Main.T", "A") + ), + TestMessages.update( + contextId, + idB, + "Enso_Test.Test.Main.T", + Api.MethodPointer("Enso_Test.Test.Main", "Enso_Test.Test.Main.T", "B") + ), + TestMessages.update( + contextId, + idC, + "Enso_Test.Test.Main.T", + Api.MethodPointer("Enso_Test.Test.Main", "Enso_Test.Test.Main.T", "C") + ), + context.executionComplete(contextId) + ) + } + it should "send updates from last line" in { val contextId = UUID.randomUUID() val requestId = UUID.randomUUID() 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 c3f5703da01..8f7b5713dae 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 @@ -3059,6 +3059,9 @@ class RuntimeVisualizationsTest s"$moduleName.Newtype", payload = Api.ExpressionUpdate.Payload.Value( Some(Api.ExpressionUpdate.Payload.Value.Warnings(1, Some("'x'"))) + ), + methodPointer = Some( + Api.MethodPointer(moduleName, s"$moduleName.Newtype", "Mk_Newtype") ) ), context.executionComplete(contextId) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/instrument/IdExecutionService.java b/engine/runtime/src/main/java/org/enso/interpreter/instrument/IdExecutionService.java index 9bc68856569..b0416bfe138 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/instrument/IdExecutionService.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/instrument/IdExecutionService.java @@ -15,7 +15,9 @@ import org.enso.interpreter.instrument.profiling.ProfilingInfo; import org.enso.interpreter.node.EnsoRootNode; import org.enso.interpreter.node.MethodRootNode; import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode; +import org.enso.interpreter.node.expression.atom.QualifiedAccessorNode; import org.enso.interpreter.runtime.Module; +import org.enso.interpreter.runtime.callable.atom.AtomConstructor; import org.enso.logger.masking.MaskedString; import org.enso.pkg.QualifiedName; @@ -214,6 +216,11 @@ public interface IdExecutionService { moduleName = methodNode.getModuleScope().getModule().getName(); typeName = methodNode.getType().getQualifiedName(); functionName = methodNode.getMethodName(); + } else if (rootNode instanceof QualifiedAccessorNode qualifiedAccessor) { + AtomConstructor atomConstructor = qualifiedAccessor.getAtomConstructor(); + moduleName = atomConstructor.getDefinitionScope().getModule().getName(); + typeName = atomConstructor.getType().getQualifiedName(); + functionName = atomConstructor.getDisplayName(); } else if (rootNode instanceof EnsoRootNode ensoRootNode) { moduleName = ensoRootNode.getModuleScope().getModule().getName(); typeName = null; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/atom/QualifiedAccessorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/atom/QualifiedAccessorNode.java index 8fbec7067e9..b3d89f135da 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/atom/QualifiedAccessorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/atom/QualifiedAccessorNode.java @@ -23,6 +23,11 @@ public class QualifiedAccessorNode extends RootNode { this.atomConstructor = atomConstructor; } + /** @return the atom constructor. */ + public AtomConstructor getAtomConstructor() { + return atomConstructor; + } + /** * Executes the node, returning the predefined constructor. * diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java index 3fdaf4f5ac3..61565bc3505 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java @@ -51,8 +51,8 @@ public final class AtomConstructor implements TruffleObject { /** * Creates a new Atom constructor for a given name. The constructor is not valid until {@link - * AtomConstructor#initializeFields(LocalScope, ExpressionNode[], ExpressionNode[], Annotation[], - * ArgumentDefinition...)} is called. + * AtomConstructor#initializeFields(EnsoLanguage, LocalScope, ExpressionNode[], ExpressionNode[], + * Annotation[], ArgumentDefinition...)} is called. * * @param name the name of the Atom constructor * @param definitionScope the scope in which this constructor was defined @@ -63,8 +63,8 @@ public final class AtomConstructor implements TruffleObject { /** * Creates a new Atom constructor for a given name. The constructor is not valid until {@link - * AtomConstructor#initializeFields(LocalScope, ExpressionNode[], ExpressionNode[], Annotation[], - * ArgumentDefinition...)} is called. + * AtomConstructor#initializeFields(EnsoLanguage, LocalScope, ExpressionNode[], ExpressionNode[], + * Annotation[], ArgumentDefinition...)} is called. * * @param name the name of the Atom constructor * @param definitionScope the scope in which this constructor was defined diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/BoxingAtom.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/BoxingAtom.java index 3bb4582218e..dfec4bca435 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/BoxingAtom.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/BoxingAtom.java @@ -1,9 +1,7 @@ package org.enso.interpreter.runtime.callable.atom; -import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; /** * A version of {@link org.enso.interpreter.runtime.callable.atom.Atom} that stores its fields in an