From 24424352f455f467df097d717a1bdaf202242316 Mon Sep 17 00:00:00 2001
From: Adam Welc <adam.welc@oracle.com>
Date: Mon, 13 Apr 2015 10:41:35 -0700
Subject: [PATCH] Break and next exceptions must be able to reach an outer
 loop.

---
 .../src/com/oracle/truffle/r/engine/REngine.java      | 11 +++++++++--
 .../com/oracle/truffle/r/test/ExpectedTestOutput.test |  3 +++
 .../truffle/r/test/library/base/TestSimpleLoop.java   |  1 +
 3 files changed, 13 insertions(+), 2 deletions(-)

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 4d997ccb0b..d4d9a7bb07 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
@@ -239,7 +239,11 @@ public final class REngine implements RContext.Engine {
         }
         try {
             RootCallTarget callTarget = doMakeCallTarget(node, "<repl wrapper>");
-            return runCall(callTarget, frame, printResult, true);
+            try {
+                return runCall(callTarget, frame, printResult, true);
+            } catch (BreakException | NextException cfe) {
+                throw RError.error(RError.Message.NO_LOOP_FOR_BREAK_NEXT);
+            }
         } catch (RError e) {
             // RError prints the correct result on the console
             return null;
@@ -419,7 +423,8 @@ public final class REngine implements RContext.Engine {
                 // condition handling can cause a "return" that needs to skip over this call
                 throw ex;
             } catch (BreakException | NextException cfe) {
-                throw RError.error(RError.Message.NO_LOOP_FOR_BREAK_NEXT);
+                // there can be an outer loop
+                throw cfe;
             }
             assert checkResult(result);
             if (printResult) {
@@ -432,6 +437,8 @@ public final class REngine implements RContext.Engine {
             throw e;
         } catch (ReturnException ex) {
             throw ex;
+        } catch (BreakException | NextException cfe) {
+            throw cfe;
         } catch (UnsupportedSpecializationException use) {
             throw use;
         } catch (DebugExitException | BrowserQuitException e) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index f27d2c6156..9c0076a173 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -21290,6 +21290,9 @@ list()
 #{ i <- 0L ; while(i < 3L) { i <- i + 1 ; if (i == 1) { next } ; if (i==3) { break } ; x <- i ; if (i==4) { x <- 10 } } ; x }
 [1] 2
 
+##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testLoopsBreakNext
+#{ x <- repeat tryCatch({break}, handler = function(e) NULL) }
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testLoopsErrors
 #{ break; }
 Error: no loop for break/next, jumping to top level
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
index 48d7e7640b..2b5666b8d6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
@@ -70,6 +70,7 @@ public class TestSimpleLoop extends TestBase {
         assertEval("{ for(i in 1:4) { if (i == 1) { next } ; if (i==3) { break } ; x <- i ; if (i==4) { x <- 10 } } ; x }");
         assertEval("{ i <- 0L ; while(i < 3L) { i <- i + 1 ; if (i == 1) { next } ; if (i==3) { break } ; x <- i ; if (i==4) { x <- 10 } } ; x }");
         assertEval("{ f <- function(s) { for(i in s) { if (i == 1) { next } ; if (i==3) { break } ; x <- i ; if (i==4) { x <- 10 } } ; x } ; f(2:1) ; f(c(1,2,3,4)) }");
+        assertEval("{ x <- repeat tryCatch({break}, handler = function(e) NULL) }");
     }
 
     @Test
-- 
GitLab