diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/model.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/model.R index 5827c72a338b2b632e8f63746c9389a23316fe74..861b58860338027a5e7f74cd9a069e81e87df93d 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/model.R +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/model.R @@ -20,7 +20,7 @@ # The structure of the implementation somewhat reflects GnuR so that # it is easier to update this code, should the code in GnuR be changed. # -# Please run tests in modelTests.R when updating this file! +# Please run in GnuR the tests in modelTests.R when updating this file! # # ================================================================ @@ -35,9 +35,15 @@ isLanguage <- function(x) { is.null(x) || typeof(x) == "language" } +# as in Rf_isVector which works differently to is.vector +isVector <- function(x) { + typeof(x) %in% c("logical", "integer", "numeric", + "double", "complex", "character", "raw", "expression") +} + nrows <- function(x) { - plain <- unclass(x) # this is necessary because of 'AsIs' class: e.g. I(var+4) - if (is.factor(x) || is.vector(plain) || is.list(plain) || is.matrix(plain)) { + plain <- unclass(x) # this is necessary because of 'AsIs' class: e.g. I(var+4) + if (is.factor(x) || isVector(plain) || is.list(plain)) { dims <- dim(plain); if (is.null(dims)) { return(length(plain)) @@ -51,7 +57,7 @@ nrows <- function(x) { ncols <- function(x) { plain <- unclass(x) - if (is.factor(x) || is.vector(plain) || is.list(plain) || is.matrix(plain)) { + if (is.factor(x) || isVector(plain) || is.list(plain)) { dims <- dim(plain); if (is.null(dims)) { return(1L); @@ -88,7 +94,7 @@ isZeroOne <- function(x) { } MatchVar <- function(var1, var2) { - if (is.vector(var1) && is.vector(var2) && var1 == var2) { + if (isVector(var1) && isVector(var2) && var1 == var2) { return(TRUE) } else if (is.null(var1) && is.null(var2)) { return(TRUE) @@ -783,7 +789,7 @@ modelframe <- function(formula, rownames, variables, varnames, dots, dotnames, s data <- variables dataNames <- varnames } - + names(data) <- dataNames # Note, the following steps up to running na.action could be simplified to: diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java index fa01f31ea9879cd1422a07ccad89f66df1d9a40a..a27af4e3c7d1df84c2dba2f2573b1b3c7dd85b6e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2014, Purdue University - * Copyright (c) 2014, 2017, Oracle and/or its affiliates + * Copyright (c) 2014, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -343,9 +343,15 @@ public abstract class CallMatcherNode extends RBaseNode { RCaller parent = RArguments.getCall(frame).getParent(); String genFunctionName = functionName == null ? function.getName() : functionName; - RCaller caller = genFunctionName == null ? RCaller.createInvalid(frame, parent) - : RCaller.create(frame, RCallerHelper.createFromArguments(genFunctionName, - new RArgsValuesAndNames(reorderedArgs.getArguments(), ArgumentsSignature.empty(reorderedArgs.getLength())))); + + RCaller caller; + if (genFunctionName == null) { + caller = RCaller.createInvalid(frame, parent); + } else { + Supplier<RSyntaxElement> argsSupplier = RCallerHelper.createFromArguments(genFunctionName, new RArgsValuesAndNames(suppliedArguments, suppliedSignature)); + caller = RCaller.create(frame, parent, argsSupplier); + } + MaterializedFrame callerFrame = (dispatchArgs instanceof S3Args) ? ((S3Args) dispatchArgs).callEnv : null; try { return call.execute(frame, function, caller, callerFrame, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function.getEnclosingFrame(), dispatchArgs); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java index 4b1a0f0af8a824d2e17135a6688db029ba97ef4d..0962add7cd7196c5abd483388d58d0b323c10e46 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ public final class RCallerHelper { return createFromArgumentsInternal(function, arguments); } - public static Supplier<RSyntaxElement> createFromArgumentsInternal(final Object function, final RArgsValuesAndNames arguments) { + private static Supplier<RSyntaxElement> createFromArgumentsInternal(final Object function, final RArgsValuesAndNames arguments) { return new Supplier<RSyntaxElement>() { RSyntaxElement syntaxNode = null; 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 8ad6b28bbead4b239ae670cd2e29eabd6202b81f..ffc6478a1104f4acc3525214177a61cf5f5cad5d 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 @@ -39102,6 +39102,14 @@ cat(... = pairlist("abc", p = 3, lab = "b"), sep = ..1, fill = 13) #fn3 <- function(...) { (function(...) match.call(cat, call("cat", "abc", p=3,as.symbol("...")), expand.dots = TRUE))(...) }; fn3(sep=x,lab="b",fill=13) cat("abc", p = 3, lab = "b", sep = ..1, fill = 13) +##com.oracle.truffle.r.test.builtins.TestBuiltin_matchcall.testMatchCall# +#{ f <- function(a, ...) { UseMethod('f1', a) };f1.default <- function(a, b=2, c=3, d=4, e=5, ...) { match.call() };f(a=1); f(a=1, b=2); f(a=1, b=2, c=3);f(a=1, b=2, d=4);f(a=1, c=3, d=4, e=5) } +f1.default(a = 1, c = 3, d = 4, e = 5) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_matchcall.testMatchCall# +#{ f <- function(a, b, c, d, e) { UseMethod('f1', a) };f1.default <- function(a, b=2, c=3, d=4, e=5) { match.call() };f(a=1); f(a=1, b=2); f(a=1, b=2, c=3);f(a=1, b=2, d=4);f(a=1, c=3, d=4, e=5) } +f1.default(a = 1, c = 3, d = 4, e = 5) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_matchcall.testMatchCall# #{ f1<-function(...) { dots <- match.call(expand.dots = FALSE)$...; dots }; f2<-function(...) f1(...); f2("a") } [[1]] diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matchcall.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matchcall.java index 1b61c42d86967398bf3267c0815e8d8d0436dc9c..934b455fa4cee3e623ab424f58f4f1e20a94a625 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matchcall.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matchcall.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -78,6 +78,20 @@ public class TestBuiltin_matchcall extends TestBase { assertEval("{ foo<-function(...) match.call(expand.dots=F); bar<-function(x) x; y<-42; foo(bar(y), 7) }"); + assertEval("{ f <- function(a, ...) { UseMethod('f1', a) };" + + "f1.default <- function(a, b=2, c=3, d=4, e=5, ...) { match.call() };" + + // fill up signature cache + "f(a=1); f(a=1, b=2); f(a=1, b=2, c=3);f(a=1, b=2, d=4);" + + // this should be ok as well + "f(a=1, c=3, d=4, e=5) }"); + + assertEval("{ f <- function(a, b, c, d, e) { UseMethod('f1', a) };" + + "f1.default <- function(a, b=2, c=3, d=4, e=5) { match.call() };" + + // fill up signature cache + "f(a=1); f(a=1, b=2); f(a=1, b=2, c=3);f(a=1, b=2, d=4);" + + // this should be ok as well + "f(a=1, c=3, d=4, e=5) }"); + // TODO add tests that pass "definition" and "call" explicitly }