From 56a0927ff359521abc69ac6aa3baa73c89ce0cd9 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 13 Jun 2017 18:51:41 +0200
Subject: [PATCH] let RError, RInternalError, ParseException and ExitException
 implement TruffleException

---
 .../truffle/r/runtime/ExitException.java      | 20 ++++++++++++++++++-
 .../com/oracle/truffle/r/runtime/RError.java  | 14 ++++++++++---
 .../truffle/r/runtime/RErrorHandling.java     | 13 ++++++------
 .../truffle/r/runtime/RInternalError.java     | 14 ++++++++++++-
 .../truffle/r/runtime/context/Engine.java     | 19 +++++++++++++++++-
 5 files changed, 68 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
index ba11798658..ad415a724c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
@@ -22,12 +22,15 @@
  */
 package com.oracle.truffle.r.runtime;
 
+import com.oracle.truffle.api.TruffleException;
+import com.oracle.truffle.api.nodes.Node;
+
 /**
  * This exception is thrown when a Polyglot R engine wants to exit, usually via the {@code quit}
  * builtin. It allows systems using multiple contexts via {@code .fastr.context.op} to handle exits
  * gracefully.
  */
-public class ExitException extends RuntimeException {
+public class ExitException extends RuntimeException implements TruffleException {
     private static final long serialVersionUID = 1L;
     private final int status;
 
@@ -38,4 +41,19 @@ public class ExitException extends RuntimeException {
     public int getStatus() {
         return status;
     }
+
+    @Override
+    public Node getLocation() {
+        return null;
+    }
+
+    @Override
+    public boolean isExit() {
+        return true;
+    }
+
+    @Override
+    public int getExitStatus() {
+        return status;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 16a847179a..615ab5006e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -16,6 +16,7 @@ import java.io.IOException;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.TruffleException;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
@@ -46,9 +47,10 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * Currently,there are no such cases.
  */
 @SuppressWarnings("serial")
-public final class RError extends RuntimeException {
+public final class RError extends RuntimeException implements TruffleException {
 
     private final String verboseStackTrace;
+    private final Node location;
 
     /**
      * This exception should be subclassed by subsystems that need to throw subsystem-specific
@@ -123,9 +125,10 @@ public final class RError extends RuntimeException {
     /**
      * TODO the string is not really needed as all output is performed prior to the throw.
      */
-    RError(String msg) {
+    RError(String msg, Node location) {
         super(msg);
-        verboseStackTrace = RInternalError.createVerboseStackTrace();
+        this.location = location;
+        this.verboseStackTrace = RInternalError.createVerboseStackTrace();
     }
 
     @Override
@@ -887,4 +890,9 @@ public final class RError extends RuntimeException {
             hasArgs = message.indexOf('%') >= 0;
         }
     }
+
+    @Override
+    public Node getLocation() {
+        return location;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index 6913a4f102..f3545d4004 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -18,6 +18,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -353,7 +354,7 @@ public class RErrorHandling {
                 if (isCallingEntry(entry)) {
                     Object h = entry.getDataAt(ENTRY_HANDLER);
                     if (h == RESTART_TOKEN) {
-                        errorcallDfltWithCall(fromCall(call), Message.GENERIC, msg);
+                        errorcallDfltWithCall(null, fromCall(call), Message.GENERIC, msg);
                     } else {
                         RFunction hf = (RFunction) h;
                         RContext.getEngine().evalFunction(hf, null, null, true, null, cond);
@@ -444,7 +445,7 @@ public class RErrorHandling {
 
     @TruffleBoundary
     public static void dfltStop(String msg, Object call) {
-        errorcallDfltWithCall(fromCall(call), Message.GENERIC, msg);
+        errorcallDfltWithCall(null, fromCall(call), Message.GENERIC, msg);
     }
 
     @TruffleBoundary
@@ -470,14 +471,14 @@ public class RErrorHandling {
     }
 
     static RError errorcallDflt(boolean showCall, RBaseNode callObj, Message msg, Object... objects) throws RError {
-        return errorcallDfltWithCall(showCall ? findCaller(callObj) : RNull.instance, msg, objects);
+        return errorcallDfltWithCall(callObj, showCall ? findCaller(callObj) : RNull.instance, msg, objects);
     }
 
     /**
      * The default error handler. This is where all the error message formatting is done and the
      * output.
      */
-    private static RError errorcallDfltWithCall(Object call, Message msg, Object... objects) throws RError {
+    private static RError errorcallDfltWithCall(Node location, Object call, Message msg, Object... objects) throws RError {
         String fmsg = formatMessage(msg, objects);
 
         String errorMessage = createErrorMessage(call, fmsg);
@@ -493,7 +494,7 @@ public class RErrorHandling {
                 errorHandlingState.warnings.clear();
                 Utils.writeStderr("Lost warning messages", true);
             }
-            throw new RError(errorMessage);
+            throw new RError(errorMessage, location);
         }
 
         Utils.writeStderr(errorMessage, true);
@@ -549,7 +550,7 @@ public class RErrorHandling {
                 throw RInternalError.shouldNotReachHere("cannot write .Traceback");
             }
         }
-        throw new RError(errorMessage);
+        throw new RError(errorMessage, location);
     }
 
     private static MaterializedFrame safeCurrentFrame() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java
index f1a38ffad7..2d2c4d93d7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java
@@ -36,13 +36,15 @@ import java.util.Date;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.TruffleException;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
  * This class is intended to be used for internal errors that do not correspond to R errors.
  */
-public final class RInternalError extends Error {
+public final class RInternalError extends Error implements TruffleException {
 
     private static final long serialVersionUID = 80698622974155216L;
 
@@ -198,4 +200,14 @@ public final class RInternalError extends Error {
             }
         }
     }
+
+    @Override
+    public Node getLocation() {
+        return null;
+    }
+
+    @Override
+    public boolean isInternalError() {
+        return true;
+    }
 }
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 1442f9e568..d593d92ec8 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
@@ -25,7 +25,9 @@ package com.oracle.truffle.r.runtime.context;
 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.MaterializedFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -42,7 +44,7 @@ public interface Engine {
 
     Source GET_CONTEXT = RSource.fromTextInternal("<<<get_context>>>", RSource.Internal.GET_CONTEXT);
 
-    class ParseException extends RuntimeException {
+    class ParseException extends RuntimeException implements TruffleException {
         private static final long serialVersionUID = 1L;
 
         private final Source source;
@@ -77,6 +79,16 @@ public interface Engine {
             }
             consoleHandler.println("Error: " + msg);
         }
+
+        @Override
+        public Node getLocation() {
+            return null;
+        }
+
+        @Override
+        public boolean isSyntaxError() {
+            return true;
+        }
     }
 
     final class IncompleteSourceException extends ParseException {
@@ -85,6 +97,11 @@ public interface Engine {
         public IncompleteSourceException(Throwable cause, Source source, String token, String substring, int line) {
             super(cause, source, token, substring, line);
         }
+
+        @Override
+        public boolean isIncompleteSource() {
+            return true;
+        }
     }
 
     /**
-- 
GitLab