diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java index a05fba7d0a78b52737beb2200532f51fb97e55e3..ef414d42b61e114ba26cc3a4c5960b2a0bf0aa56 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java @@ -66,9 +66,11 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RS4Object; +import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -316,6 +318,8 @@ public class GetFunctions { @Specialization protected RList mget(VirtualFrame frame, RAbstractStringVector xv, REnvironment envir, RAbstractStringVector mode, RList ifNotFound, boolean inherits, + @Cached("createBinaryProfile()") ConditionProfile argsAndValuesProfile, + @Cached("createBinaryProfile()") ConditionProfile missingProfile, @Cached("createBinaryProfile()") ConditionProfile inheritsProfile) { State state = checkArgs(xv, mode, ifNotFound); for (int i = 0; i < state.svLength; i++) { @@ -330,7 +334,7 @@ public class GetFunctions { while (env != REnvironment.emptyEnv()) { env = env.getParent(); if (env != REnvironment.emptyEnv()) { - r = helper.checkPromise(frame, env.get(x), x); + r = handleMissingAndVarargs(helper.checkPromise(frame, env.get(x), x), argsAndValuesProfile, missingProfile); if (r != null && RRuntime.checkType(r, modeType)) { break; } @@ -343,7 +347,7 @@ public class GetFunctions { state.data[i] = r; } } else { - Object r = helper.checkPromise(frame, envir.get(x), x); + Object r = handleMissingAndVarargs(helper.checkPromise(frame, envir.get(x), x), argsAndValuesProfile, missingProfile); if (r != null && RRuntime.checkType(r, modeType)) { state.data[i] = r; } else { @@ -356,9 +360,11 @@ public class GetFunctions { @Specialization protected RList mget(VirtualFrame frame, RAbstractStringVector xv, RS4Object s4Envir, RAbstractStringVector mode, RList ifNotFound, boolean inherits, + @Cached("createBinaryProfile()") ConditionProfile argsAndValuesProfile, + @Cached("createBinaryProfile()") ConditionProfile missingProfile, @Cached("createBinaryProfile()") ConditionProfile inheritsProfile, @Cached("new()") S4ToEnvNode s4ToEnv) { - return mget(frame, xv, (REnvironment) s4ToEnv.execute(s4Envir), mode, ifNotFound, inherits, inheritsProfile); + return mget(frame, xv, (REnvironment) s4ToEnv.execute(s4Envir), mode, ifNotFound, inherits, argsAndValuesProfile, missingProfile, inheritsProfile); } private void doIfNotFound(VirtualFrame frame, State state, int i, String x, RList ifNotFound) { @@ -380,5 +386,20 @@ public class GetFunctions { return callCache.execute(frame, ifnFunc, RCaller.create(frame, RCallerHelper.createFromArguments(ifnFunc, args)), callerFrame, new Object[]{x}, formals.getSignature(), ifnFunc.getEnclosingFrame(), null); } + + private static Object handleMissingAndVarargs(Object value, ConditionProfile argsAndValuesProfile, ConditionProfile missingProfile) { + if (argsAndValuesProfile.profile(value instanceof RArgsValuesAndNames)) { + if (((RArgsValuesAndNames) value).getLength() == 0) { + return RSymbol.MISSING; + } else { + // GNUR also puts raw promises in the list + return RDataFactory.createList(((RArgsValuesAndNames) value).getArguments()); + } + } + if (missingProfile.profile(value == RMissing.instance)) { + return RSymbol.MISSING; + } + return value; + } } } 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 c700f6b474620a0bc5151920c9259f33a5920e76..0b7f250943d118507e1047cb0cc5bbad0791eba8 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 @@ -36123,6 +36123,16 @@ list sys.call(1) +##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGetWithVarArgs# +#{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));func <- function(...) find_args(...);func(); } + ... +FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGetWithVarArgs# +#{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));func <- function(...) find_args(...);func(a=3); } + ... +TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# #min(c(1,NA,2), na.rm=NA) [1] 1 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java index e27d7728fc5c1f0ad654ae6a0d25cf668c7bb9a3..27f45c65f1dcf52a61f9af79cde406208c08008e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java @@ -34,4 +34,11 @@ public class TestBuiltin_mget extends TestBase { assertEval("{ x<-mget(\"_foo_\", ifnotfound=list(function(x) sys.call(0))); print(x[[1]][[1]]); print(x[[1]][[2]]) }"); assertEval("{ x<-mget(\"_foo_\", ifnotfound=list(function(x) sys.call(1))); list(x[[1]][[1]], x[[1]][[2]], x[[1]][[3]][[1]], x[[1]][[3]][[2]][[1]], x[[1]][[3]][[2]][[2]], x[[1]][[3]][[2]][[3]]) }"); } + + @Test + public void testMGetWithVarArgs() { + assertEval(template("{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));" + + "func <- function(...) find_args(...);" + + "%0; }", new String[]{"func()", "func(a=3)"})); + } }