diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java index c36cc56519..80de875fe7 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/DebuggingEnsoTest.java @@ -317,6 +317,41 @@ public class DebuggingEnsoTest { } } + @Test + public void testEvaluateExpressionInDebugBreakpoint() { + Value fooFunc = + createEnsoMethod( + """ + + import Standard.Base.Runtime.Debug + + foo x = + a = 6 + b = 7 + Debug.breakpoint + """, + "foo"); + + int[] res = {0}; + try (DebuggerSession session = + debugger.startSession( + (SuspendedEvent event) -> { + switch (event.getSourceSection().getCharacters().toString().strip()) { + case "Debug.breakpoint" -> { + DebugStackFrame stackFrame = event.getTopStackFrame(); + DebugValue evaluatedValue = stackFrame.eval("a * b"); + assertTrue(evaluatedValue.isNumber()); + assertEquals(42, res[0] = evaluatedValue.asInt()); + } + } + event.getSession().suspendNextExecution(); + })) { + session.suspendNextExecution(); + fooFunc.execute(0); + } + assertEquals("Really suspended at 42", 42, res[0]); + } + @Test public void testRewriteLocalVariable() { Value fooFunc = diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/debug/DebugBreakpointNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/debug/DebugBreakpointNode.java index 890602364c..4f5f309e41 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/debug/DebugBreakpointNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/debug/DebugBreakpointNode.java @@ -8,6 +8,8 @@ import com.oracle.truffle.api.instrumentation.InstrumentableNode; import com.oracle.truffle.api.instrumentation.ProbeNode; import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.runtime.EnsoContext; import org.enso.interpreter.runtime.callable.CallerInfo; @@ -20,6 +22,13 @@ import org.enso.interpreter.runtime.state.State; autoRegister = false) @GenerateWrapper public abstract class DebugBreakpointNode extends Node implements InstrumentableNode { + private static final SourceSection DEBUG_SECTION; + + static { + var src = Source.newBuilder("enso", "Debug.breakpoint", "Debug.enso").build(); + DEBUG_SECTION = src.createUnavailableSection(); + } + /** * Creates a new instance of this node. * @@ -29,13 +38,18 @@ public abstract class DebugBreakpointNode extends Node implements Instrumentable return DebugBreakpointNodeGen.create(); } + @Override + public final SourceSection getSourceSection() { + return DEBUG_SECTION; + } + /** * Tells Truffle this node is instrumentable. * * @return {@code true} – this node is always instrumentable. */ @Override - public boolean isInstrumentable() { + public final boolean isInstrumentable() { return true; } @@ -55,7 +69,7 @@ public abstract class DebugBreakpointNode extends Node implements Instrumentable * @return {@code true} if the tag is {@link DebuggerTags.AlwaysHalt}, {@code false} otherwise */ @Override - public boolean hasTag(Class tag) { + public final boolean hasTag(Class tag) { return tag == DebuggerTags.AlwaysHalt.class; } @@ -66,7 +80,7 @@ public abstract class DebugBreakpointNode extends Node implements Instrumentable * @return the wrapper instance wrapping both this and the probe node */ @Override - public WrapperNode createWrapper(ProbeNode probeNode) { + public final WrapperNode createWrapper(ProbeNode probeNode) { return new DebugBreakpointNodeWrapper(this, probeNode); } }