Skip to content
Snippets Groups Projects
Commit f7800c24 authored by Mick Jordan's avatar Mick Jordan
Browse files

add RError support for (internal) non-reportable errors

parent eee6ed7c
Branches
No related tags found
No related merge requests found
......@@ -433,7 +433,7 @@ public abstract class ReadVariableNode extends RNode implements VisibilityContro
protected abstract String getSymbol();
@Specialization
public Object doObject(@SuppressWarnings("unused") VirtualFrame frame) {
public Object doObject(VirtualFrame frame) {
controlVisibility();
throw RError.error(frame, RError.Message.UNKNOWN_OBJECT, getSymbol());
}
......
......@@ -47,6 +47,7 @@ public abstract class S3DispatchNode extends DispatchNode {
}
Object func = targetFunction = null;
targetFunctionName = null;
boolean prevIgnoreError = RError.ignoreError(true);
try {
if (frame instanceof VirtualFrame) {
func = lookup.execute((VirtualFrame) frame);
......@@ -54,6 +55,9 @@ public abstract class S3DispatchNode extends DispatchNode {
func = lookup.execute(null, (MaterializedFrame) frame);
}
} catch (RError r) {
// in this context, this is not a reportable error
} finally {
RError.ignoreError(prevIgnoreError);
}
if (func != null && func instanceof RFunction) {
targetFunctionName = functionName;
......
......@@ -59,6 +59,37 @@ public final class RError extends RuntimeException {
return getMessage();
}
// use a ThreadLocal if multi-threaded evaluation
/**
* Are we (temporarily) ignore errors? Assumes single threaded.
*/
private static boolean ignoreError;
/**
* Support for the temporary suppression of the normal error catch machinery. After a call to
* {code ignoreError(true)}, the error will simply be thrown on the assumption that if will be
* caught by the caller and some alternative course of action chosen. This should always be used
* in a {@code try finally} block, e.g:
*
* <pre>
* boolean prev = RError.ignore(true);
* try {
* // do something that might throw an RError
* ...
* } finally {
* RError.ignore(prev);
* }
* </pre>
*
* @param ignore
* @return the previous setting
*/
public static boolean ignoreError(boolean ignore) {
boolean prev = ignoreError;
ignoreError = ignore;
return prev;
}
/**
* An error that cannot be caught by {@code options(error = expr)} as there is no
* {@link VirtualFrame} available. Ideally this should not be necessary.
......@@ -96,6 +127,11 @@ public final class RError extends RuntimeException {
} else {
rError = new RError(null, "Error: " + formatMessage(msg, args));
}
if (ignoreError) {
// do we really need to be in the interpreter in this case?
throw rError;
}
Object errorExpr = ROptions.getValue("error");
if (errorExpr != RNull.instance) {
if (frame == null) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment