Skip to content
Snippets Groups Projects
Commit 60ce69a0 authored by stepan's avatar stepan
Browse files

Fix S3 dispatches according to the first non-missing argument

parent 5ef96c5e
Branches
No related tags found
No related merge requests found
......@@ -48,6 +48,7 @@ import com.oracle.truffle.r.runtime.ReturnException;
import com.oracle.truffle.r.runtime.Utils;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RMissing;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RPromise;
......@@ -98,6 +99,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
@Child private PromiseCheckHelperNode promiseCheckHelper;
private final BranchProfile errorProfile = BranchProfile.create();
private final BranchProfile firstArgMissing = BranchProfile.create();
private final ConditionProfile argMissingProfile = ConditionProfile.createBinaryProfile();
private final ConditionProfile argsValueAndNamesProfile = ConditionProfile.createBinaryProfile();
......@@ -107,7 +109,6 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
@Specialization
protected Object execute(VirtualFrame frame, String generic, Object arg) {
Object dispatchedObject;
if (argMissingProfile.profile(arg == RMissing.instance)) {
// For S3Dispatch, we have to evaluate the the first argument
......@@ -116,7 +117,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
dispatchedObject = arg;
}
RStringVector type = classHierarchyNode.execute(dispatchedObject);
RStringVector type = dispatchedObject == null ? RDataFactory.createEmptyStringVector() : classHierarchyNode.execute(dispatchedObject);
MaterializedFrame callerFrame = getCallerFrame(frame);
MaterializedFrame genericDefFrame = RArguments.getEnclosingFrame(frame);
......@@ -128,7 +129,8 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
/**
* Get the first (logical) argument in the frame, and handle {@link RPromise}s and
* {@link RArgsValuesAndNames}.
* {@link RArgsValuesAndNames}. If there is no actual argument, returns null. If there are
* no formal arguments, throws the appropriate error.
*/
private Object getEnclosingArg(VirtualFrame frame, String generic) {
if (RArguments.getArgumentsLength(frame) == 0 || RArguments.getArgument(frame, 0) == null) {
......@@ -137,20 +139,37 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
}
Object enclosingArg = RArguments.getArgument(frame, 0);
if (argsValueAndNamesProfile.profile(enclosingArg instanceof RArgsValuesAndNames)) {
// The GnuR "1. argument" might be hidden inside a "..."! Unwrap for proper dispatch
RArgsValuesAndNames varArgs = (RArgsValuesAndNames) enclosingArg;
if (varArgs.isEmpty()) {
errorProfile.enter();
throw RError.error(this, RError.Message.UNKNOWN_FUNCTION_USE_METHOD, generic, RRuntime.toString(RNull.instance));
enclosingArg = getFirstVarArg((RArgsValuesAndNames) enclosingArg);
} else if (enclosingArg == RMissing.instance) {
firstArgMissing.enter();
enclosingArg = getFirstNonMissingArg(frame, 1);
if (enclosingArg == null) {
return null;
}
enclosingArg = varArgs.getArgument(0);
}
if (promiseCheckHelper == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
promiseCheckHelper = insert(new PromiseCheckHelperNode());
}
return promiseCheckHelper.checkEvaluate(frame, enclosingArg);
}
private Object getFirstNonMissingArg(VirtualFrame frame, int startIdx) {
for (int i = startIdx; i < RArguments.getArgumentsLength(frame); i++) {
Object arg = RArguments.getArgument(frame, i);
if (arg instanceof RArgsValuesAndNames) {
return getFirstVarArg((RArgsValuesAndNames) arg);
} else if (arg != RMissing.instance) {
return arg;
}
}
return null;
}
private Object getFirstVarArg(RArgsValuesAndNames varArgs) {
return varArgs.isEmpty() ? null : varArgs.getArgument(0);
}
}
@RBuiltin(name = "NextMethod", visibility = RVisibility.CUSTOM, kind = SUBSTITUTE, parameterNames = {"generic", "object", "..."})
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment