diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index e457130ddb3169388f5e5075f29e5a74eb486b01..021f8eb5d07c91455587591c432fa1296ce542f4 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -43,6 +43,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.api.nodes.ExecutableNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -338,6 +339,29 @@ final class REngine implements Engine, Engine.Timings { } } + @Override + public ExecutableNode parseToExecutableNode(Source source) throws ParseException { + List<RSyntaxNode> list = parseImpl(source); + RNode[] statements = new RNode[list.size()]; + for (int i = 0; i < statements.length; i++) { + statements[i] = list.get(i).asRNode(); + } + return new ExecutableNode(context.getLanguage()) { + @Child R2Foreign toForeignNode = R2Foreign.create(); + + @Override + public Object execute(VirtualFrame frame) { + if (statements.length == 0) { + return RNull.instance; + } + for (int i = 0; i < statements.length - 1; i++) { + statements[i].execute(frame); + } + return toForeignNode.execute(statements[statements.length - 1].execute(frame)); + } + }; + } + private static SourceSection createSourceSection(Source source, List<RSyntaxNode> statements) { // All statements come from the same "Source" if (statements.isEmpty()) { diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java index 55f25b4d20dc7807d9684c2ad7d79692e7921051..57e5be131a4c0ce57fc0d6cabdf1f8eed26daa09 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java @@ -32,6 +32,7 @@ import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.instrumentation.Instrumenter; import com.oracle.truffle.api.instrumentation.ProvidedTags; import com.oracle.truffle.api.instrumentation.StandardTags; +import com.oracle.truffle.api.nodes.ExecutableNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.engine.interop.RForeignAccessFactoryImpl; @@ -188,7 +189,23 @@ public final class TruffleRLanguageImpl extends TruffleRLanguage { protected CallTarget parse(ParsingRequest request) throws Exception { CompilerAsserts.neverPartOfCompilation(); try { - return RContext.getEngine().parseToCallTarget(request.getSource(), request.getFrame()); + return RContext.getEngine().parseToCallTarget(request.getSource(), null); + } catch (IncompleteSourceException e) { + throw e; + } catch (ParseException e) { + if (request.getSource().isInteractive()) { + throw e.throwAsRError(); + } else { + throw e; + } + } + } + + @Override + protected ExecutableNode parse(InlineParsingRequest request) throws Exception { + CompilerAsserts.neverPartOfCompilation(); + try { + return RContext.getEngine().parseToExecutableNode(request.getSource()); } catch (IncompleteSourceException e) { throw e; } catch (ParseException e) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java index 9e3592226f4a4f6c9ac04e2f9400b9661dd9da7b..b31e710df2030d6d11415e6dfa360c7c3839b3d3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java @@ -30,7 +30,9 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.TruffleException; +import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.nodes.ExecutableNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; @@ -178,6 +180,12 @@ public interface Engine { */ CallTarget parseToCallTarget(Source source, MaterializedFrame executionFrame) throws ParseException; + /** + * Returns ASTs representing given source. The node is meant to be inserted into existing AST + * and executed as part of it. + */ + ExecutableNode parseToExecutableNode(Source source) throws ParseException; + /** * Parse and evaluate {@code rscript} in {@code frame}. {@code printResult == true}, the result * of the evaluation is printed to the console. diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java index 7840f6cb87e8653eea17ecfa02d6e7bc35afd854..d28904a26b51259441dcfd8d6156945f61190fdf 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java @@ -168,16 +168,14 @@ public class FastRDebugTest { * Test is currently ignored because of missing functionality in Truffle. */ @Test - @Ignore public void testConditionalBreakpoint() throws Throwable { - final Source source = sourceFromText("main <- function() {\n" + + final Source source = sourceFromText("main <- function() { res <- 0;\n" + " for(i in seq(10)) {\n" + - " print(i)\n" + + " res <- res + i\n" + " }\n" + + " res\n" + "}\n", "test.r"); - context.eval(source); - run.addLast(() -> { assertNull(suspendedEvent); assertNotNull(debuggerSession); @@ -186,15 +184,17 @@ public class FastRDebugTest { debuggerSession.install(breakpoint); }); - assertLocation(3, "print(i)", "i", "5"); - continueExecution(); - // Init before eval: performWork(); - - final Source evalSrc = sourceFromText("main()\n", "test.r"); - context.eval(evalSrc); + context.eval(source); assertExecutedOK(); + + assertLocation(3, "res <- res + i", "i", "5"); + continueExecution(); + + final Source evalSrc = sourceFromText("main()\n", "test2.r"); + Value result = context.eval(evalSrc); + assertEquals("result is correct", 55, result.asInt()); } @Test diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index edde805aec17c42b90d0009e645381316e5417df..c9f01388703858f56bb6633a23e75f40a213026d 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -29,7 +29,7 @@ suite = { { "name" : "truffle", "subdir" : True, - "version" : "b29a94a6738f96c33be981681b69216a1664eb8a", + "version" : "e140680ae7ebc4329e5cd96889258a75b6987dfe", "urls" : [ {"url" : "https://github.com/graalvm/graal", "kind" : "git"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},