diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java index a439a0b7db36dcd248ecc5f690dbac5da2861088..d0d48097d59d96b28d8e3770e37f6f31bb0d5131 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java @@ -92,6 +92,7 @@ import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument; import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode; import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; @@ -222,21 +223,27 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { @Override @TruffleBoundary - public Object fromList(RList list, RLanguage.RepType repType) { + public Object createLanguageFromList(RList list, RLanguage.RepType repType) { int length = list.getLength(); if (length == 0) { return RNull.instance; } else if (repType == RLanguage.RepType.CALL) { RStringVector formals = list.getNames(); - RSyntaxNode[] arguments = new RSyntaxNode[length - 1]; - String[] sigNames = new String[arguments.length]; + + List<RCodeBuilder.Argument<RSyntaxNode>> argList = new ArrayList<>(length - 1); for (int i = 1; i < length; i++) { - arguments[i - 1] = (RSyntaxNode) unwrapToRNode(list.getDataAtAsObject(i)); String formal = formals == null ? null : formals.getDataAt(i); - sigNames[i - 1] = formal != null && formal.length() > 0 ? formal : null; + RSyntaxNode syntaxArg = (RSyntaxNode) unwrapToRNode(list.getDataAtAsObject(i)); + if (formal != null) { + argList.add(RCodeBuilder.argument(RSourceSectionNode.LAZY_DEPARSE, formal, syntaxArg)); + } else { + argList.add(RCodeBuilder.argument(syntaxArg)); + } } + RNode fn = unwrapToRNode(list.getDataAtAsObject(0)); - RLanguage result = RDataFactory.createLanguage(RASTUtils.createCall(fn, false, ArgumentsSignature.get(sigNames), arguments).asRNode()); + RSyntaxNode call = RContext.getASTBuilder().call(RSourceSectionNode.LAZY_DEPARSE, fn.asRSyntaxNode(), argList); + RLanguage result = RDataFactory.createLanguage(call.asRNode()); if (formals != null && formals.getLength() > 0 && formals.getDataAt(0).length() > 0) { result.setCallLHSName(formals.getDataAt(0)); } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java index 0fd2bf80d7febf8ed9d5b24c8dccc5a01cad255f..b459887c3e7b27730c2d4f2fb85fe16ba16a8d8b 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java @@ -136,7 +136,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { private final Map<String, Object> nameSymbolCache = new ConcurrentHashMap<>(); private static RuntimeException implementedAsNode() { - throw RInternalError.shouldNotReachHere("upcall function is implemented via a node"); + // TODO: Exception handling over native boundaries is currently missing. Once this works, + // remove the following two lines. + System.err.println("upcall function is implemented via a node"); + System.exit(1); + + return RInternalError.shouldNotReachHere("upcall function is implemented via a node"); } // Checkstyle: stop method name check @@ -217,6 +222,13 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { return 0; } + @Override + public Object R_getClassDef(String clazz) { + String name = "getClassDef"; + RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name)); + return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz); + } + @Override public Object R_do_MAKE_CLASS(String clazz) { String name = "getClass"; @@ -1678,4 +1690,15 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { private static RFFIContext getContext() { return RContext.getInstance().getStateRFFI(); } + + @Override + public Object Rf_match(Object itables, Object ix, int nmatch) { + throw implementedAsNode(); + } + + @Override + public Object Rf_NonNullStringMatch(Object s, Object t) { + throw implementedAsNode(); + } + } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MatchNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MatchNodes.java new file mode 100644 index 0000000000000000000000000000000000000000..fbd8025aaec2505b46256817a7c5437290878dfc --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MatchNodes.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.ffi.impl.nodes; + +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RTypes; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; + +public final class MatchNodes { + + @TypeSystemReference(RTypes.class) + public abstract static class MatchNode extends FFIUpCallNode.Arg3 { + + @SuppressWarnings("unused") + @Specialization + Object match(Object itables, Object ix, int nmatch) { + throw RInternalError.unimplemented("Rf_match"); + } + + public static MatchNode create() { + return MatchNodesFactory.MatchNodeGen.create(); + } + } + + @TypeSystemReference(RTypes.class) + public abstract static class NonNullStringMatchNode extends FFIUpCallNode.Arg2 { + + @Specialization(guards = {"s.getLength() == 1", "t.getLength() == 1"}) + Object matchSingle(RAbstractStringVector s, RAbstractStringVector t) { + if (s.getDataAt(0) == RRuntime.STRING_NA || t.getDataAt(0) == RRuntime.STRING_NA) { + return RRuntime.LOGICAL_FALSE; + } + return RRuntime.asLogical(s.getDataAt(0).equals(t.getDataAt(0))); + } + + @Fallback + @SuppressWarnings("unused") + Object match(Object s, Object t) { + throw RInternalError.unimplemented("Rf_NonNullStringMatch"); + } + + public static NonNullStringMatchNode create() { + return MatchNodesFactory.NonNullStringMatchNodeGen.create(); + } + } + +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java index 6d7d2f2c571aa8bfcf848a11ae41e5e9bf295a12..515524a94b9a9918eb060ebca0e589d53b01d1ad 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java @@ -113,7 +113,7 @@ public final class MiscNodes { } @TypeSystemReference(RTypes.class) - abstract static class RDoSlotNode extends FFIUpCallNode.Arg2 { + public abstract static class RDoSlotNode extends FFIUpCallNode.Arg2 { @Child private AccessSlotNode accessSlotNode; @@ -137,7 +137,7 @@ public final class MiscNodes { } @TypeSystemReference(RTypes.class) - abstract static class RDoSlotAssignNode extends FFIUpCallNode.Arg3 { + public abstract static class RDoSlotAssignNode extends FFIUpCallNode.Arg3 { @Child private UpdateSlotNode updateSlotNode; @@ -150,6 +150,11 @@ public final class MiscNodes { return updateSlotNode.executeUpdate(o, name, value); } + @Specialization + Object doSlotAssign(Object o, RSymbol name, Object value) { + return updateSlotNode.executeUpdate(o, name.getName(), value); + } + @Fallback Object doSlot(@SuppressWarnings("unused") Object o, Object name, @SuppressWarnings("unused") Object value) { throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name()); @@ -161,7 +166,7 @@ public final class MiscNodes { } @TypeSystemReference(RTypes.class) - abstract static class RDoNewObjectNode extends FFIUpCallNode.Arg1 { + public abstract static class RDoNewObjectNode extends FFIUpCallNode.Arg1 { @Child private NewObject newObjectNode; @@ -180,7 +185,7 @@ public final class MiscNodes { } @TypeSystemReference(RTypes.class) - abstract static class NamesGetsNode extends FFIUpCallNode.Arg2 { + public abstract static class NamesGetsNode extends FFIUpCallNode.Arg2 { @Child private SetNamesAttributeNode setNamesNode; @@ -193,6 +198,10 @@ public final class MiscNodes { setNamesNode.execute(vec, val); return vec; } + + public static NamesGetsNode create() { + return MiscNodesFactory.NamesGetsNodeGen.create(); + } } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java index f168c1caeda218a4a7589d1e2a6edc979faa8fb8..a626970a7e77ca884c63f9dc0580fc8b6ef2d303 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java @@ -24,13 +24,16 @@ package com.oracle.truffle.r.ffi.impl.nodes; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.nmath.MathFunctions; +import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function3_1; +import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function3_2; import com.oracle.truffle.r.runtime.nmath.RandomFunctions; import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction2_Double; import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider; +import com.oracle.truffle.r.runtime.nmath.distr.Unif; public final class RandFunctionsNodes { - public abstract static class RandFunction3_2Node extends FFIUpCallNode.Arg5 { + abstract static class RandFunction3_2Node extends FFIUpCallNode.Arg5 { private final MathFunctions.Function3_2 inner; protected RandFunction3_2Node(MathFunctions.Function3_2 inner) { @@ -43,7 +46,7 @@ public final class RandFunctionsNodes { } } - public abstract static class RandFunction3_1Node extends FFIUpCallNode.Arg4 { + abstract static class RandFunction3_1Node extends FFIUpCallNode.Arg4 { private final MathFunctions.Function3_1 inner; protected RandFunction3_1Node(MathFunctions.Function3_1 inner) { @@ -56,7 +59,7 @@ public final class RandFunctionsNodes { } } - public abstract static class RandFunction2Node extends FFIUpCallNode.Arg2 { + abstract static class RandFunction2Node extends FFIUpCallNode.Arg2 { @Child private RandomFunctions.RandFunction2_Double inner; protected RandFunction2Node(RandFunction2_Double inner) { @@ -69,4 +72,51 @@ public final class RandFunctionsNodes { } } + public abstract static class RunifNode extends RandFunction2Node { + + protected RunifNode(RandFunction2_Double inner) { + super(inner); + } + + public static RunifNode create() { + return RandFunctionsNodesFactory.RunifNodeGen.create(new Unif.Runif()); + } + + } + + public abstract static class DunifNode extends RandFunction3_1Node { + + protected DunifNode(Function3_1 inner) { + super(inner); + } + + public static DunifNode create() { + return RandFunctionsNodesFactory.DunifNodeGen.create(new Unif.DUnif()); + } + + } + + public abstract static class QunifNode extends RandFunction3_2Node { + + protected QunifNode(Function3_2 inner) { + super(inner); + } + + public static QunifNode create() { + return RandFunctionsNodesFactory.QunifNodeGen.create(new Unif.QUnif()); + } + + } + + public abstract static class PunifNode extends RandFunction3_2Node { + + protected PunifNode(Function3_2 inner) { + super(inner); + } + + public static PunifNode create() { + return RandFunctionsNodesFactory.PunifNodeGen.create(new Unif.PUnif()); + } + + } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java index 4b7965ab318ddf4b53548d9d3036c4aaf72c2f52..d6dff9a1df3609c3548429a12a3b9e81b03ca595 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java @@ -36,7 +36,10 @@ import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CADRNode; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CARNode; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CDDRNode; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CDRNode; +import com.oracle.truffle.r.ffi.impl.nodes.MatchNodes; +import com.oracle.truffle.r.ffi.impl.nodes.MiscNodes; import com.oracle.truffle.r.ffi.impl.nodes.MiscNodes.LENGTHNode; +import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodes; import com.oracle.truffle.r.ffi.processor.RFFICstring; import com.oracle.truffle.r.ffi.processor.RFFIRunGC; import com.oracle.truffle.r.ffi.processor.RFFIUpCallNode; @@ -93,8 +96,11 @@ public interface StdUpCallsRFFI { int /* void */ Rf_defineVar(Object symbolArg, Object value, Object envArg); + Object R_getClassDef(@RFFICstring String clazz); + Object R_do_MAKE_CLASS(@RFFICstring String clazz); + @RFFIUpCallNode(MiscNodes.RDoNewObjectNode.class) Object R_do_new_object(Object classDef); /** @@ -315,8 +321,10 @@ public interface StdUpCallsRFFI { boolean isSeekable(Object x); + @RFFIUpCallNode(MiscNodes.RDoSlotNode.class) Object R_do_slot(Object o, Object name); + @RFFIUpCallNode(MiscNodes.RDoSlotAssignNode.class) Object R_do_slot_assign(Object o, Object name, Object value); Object R_MethodsNamespace(); @@ -325,14 +333,19 @@ public interface StdUpCallsRFFI { int FASTR_getConnectionChar(Object obj); + @RFFIUpCallNode(RandFunctionsNodes.DunifNode.class) double Rf_dunif(double a, double b, double c, int d); + @RFFIUpCallNode(RandFunctionsNodes.QunifNode.class) double Rf_qunif(double a, double b, double c, int d, int e); + @RFFIUpCallNode(RandFunctionsNodes.PunifNode.class) double Rf_punif(double a, double b, double c, int d, int e); + @RFFIUpCallNode(RandFunctionsNodes.RunifNode.class) double Rf_runif(double a, double b); + @RFFIUpCallNode(MiscNodes.NamesGetsNode.class) Object Rf_namesgets(Object vec, Object val); @RFFIUpCallNode(CopyMostAttrib.class) @@ -343,4 +356,10 @@ public interface StdUpCallsRFFI { @RFFIUpCallNode(CADDRNode.class) Object Rf_asCharacterFactor(Object x); + + @RFFIUpCallNode(MatchNodes.MatchNode.class) + Object Rf_match(Object itables, Object ix, int nmatch); + + @RFFIUpCallNode(MatchNodes.NonNullStringMatchNode.class) + Object Rf_NonNullStringMatch(Object s, Object t); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/PPSum.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/PPSum.java new file mode 100644 index 0000000000000000000000000000000000000000..6fd2053b204f3a7d2ec7b1df29a72e0ae1c5c74c --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/PPSum.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.library.stats; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.library.stats.PPSumFactory.IntgrtVecNodeGen; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; + +public abstract class PPSum { + + /** + * Implementation of function 'intgrt_vec'. + */ + public abstract static class IntgrtVecNode extends RExternalBuiltinNode.Arg3 { + + private final ValueProfile profileArgX = ValueProfile.createClassProfile(); + private final ValueProfile profileArgXi = ValueProfile.createClassProfile(); + + static { + Casts casts = new Casts(IntgrtVecNode.class); + casts.arg(0).asDoubleVector(); + casts.arg(1).asDoubleVector(); + casts.arg(2).asIntegerVector().findFirst(); + } + + @Specialization + protected RAbstractDoubleVector doIntegrateVector(RAbstractDoubleVector x, RAbstractDoubleVector xi, int lag) { + RAbstractDoubleVector profiledX = profileArgX.profile(x); + RAbstractDoubleVector profiledXi = profileArgXi.profile(xi); + + int n = profiledX.getLength(); + int nResult = n + lag; + + RDoubleVector result = (RDoubleVector) profiledXi.copyResized(nResult, false); + + double[] store = result.getInternalStore(); + for (int i = 0; i < n; i++) { + store[i + lag] = profiledX.getDataAt(i) + store[i]; + } + return result; + } + + public static IntgrtVecNode create() { + return IntgrtVecNodeGen.create(); + } + } + +} 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 37640f855ba9e0ec96d6831e6d6abb188f944f2c..2175ac8d653c38340f7b99f3a51baa4a5b5bf1b8 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 @@ -582,14 +582,16 @@ termsform <- function (x.in, specials, data, keep.order, allowDotAsName) { varlist <<- list() ExtractVars(x) vars <- quote(list()) - vars[2:(length(varlist) + 1L)] <- varlist + if(length(varlist)) { + vars[2:(length(varlist) + 1L)] <- varlist + } attr(x, "variables") <- vars # Note: GnuR uses bitvector of integers and variable nwords to denote its size, we do not need that nvar <<- length(varlist) formula <- EncodeVars(x) - # EncodeVars may have stretched varlist becuase it is a global variable (to reflect GnuR's implementation) + # EncodeVars may have stretched varlist because it is a global variable (to reflect GnuR's implementation) nvar <<- length(varlist) # Step 2a: Compute variable names @@ -611,24 +613,28 @@ termsform <- function (x.in, specials, data, keep.order, allowDotAsName) { # Step 3: Reorder the model terms by BitCount, otherwise # preserving their order. - sCounts <- vapply(formula, BitCount, 0L) - bitmax <- max(sCounts) - - if (keep.order) { - ord <- sCounts; - } else { - pattern <- formula # save original formula - callIdx <- 1L - ord <- integer(nterm) - for (i in 0:bitmax) { - for (n in 1:nterm) { - if (sCounts[[n]] == i) { - formula[[callIdx]] <- pattern[[n]] - ord[[callIdx]] <- i - callIdx <- callIdx + 1L + if(nterm) { + sCounts <- vapply(formula, BitCount, 0L) + bitmax <- max(sCounts) + + if (keep.order) { + ord <- sCounts; + } else { + pattern <- formula # save original formula + callIdx <- 1L + ord <- integer(nterm) + for (i in 0:bitmax) { + for (n in 1:nterm) { + if (sCounts[[n]] == i) { + formula[[callIdx]] <- pattern[[n]] + ord[[callIdx]] <- i + callIdx <- callIdx + 1L + } + } } } - } + } else { + ord <- integer() } # Step 4: Compute the factor pattern for the model. @@ -996,7 +1002,7 @@ modelmatrix <- function(formula, modelframe) { # If there is no intercept we look through the factor pattern # matrix and adjust the code for the first factor found so that # it will be coded by dummy variables rather than contrasts. - if (!intercept) { + if (!intercept && nterms > 0L) { # Note/TODO: in GnuR response is retrieved using asLogical, # but here it is used as an index, is this intended? done <- FALSE @@ -1034,7 +1040,7 @@ modelmatrix <- function(formula, modelframe) { # By convention, an rhs term identical to the response generates nothing # in the model matrix (but interactions involving the response do). rhs_response = -1; - if (response > 0) { + if (response > 0 && nterms > 0L) { for (j in 1:nterms) { if (factors[response, j] != 0L && sum(factors[,j] > 0L) == 1L) { rhs_response = j @@ -1052,36 +1058,38 @@ modelmatrix <- function(formula, modelframe) { if (intercept) { dnc <- 1 } - for (j in 1:nterms) { - if (j == rhs_response) { - warning("the response appeared on the right-hand side and was dropped") - count[[j]] <- 0L - } - - dk <- 1L - for (i in 1:nvar) { - factors_ij <- factors[i,j] - if (factors_ij == 0L) { - next + if(nterms > 0L) { + for (j in 1:nterms) { + if (j == rhs_response) { + warning("the response appeared on the right-hand side and was dropped") + count[[j]] <- 0L } - if (nlevs[[i]] != 0L) { - if (factors_ij == 1L) { - dk <- dk * ncols(contr1[[i]]) - } else if (factors_ij == 2L) { - dk <- dk * ncols(contr2[[i]]) + dk <- 1L + for (i in 1:nvar) { + factors_ij <- factors[i,j] + if (factors_ij == 0L) { + next + } + + if (nlevs[[i]] != 0L) { + if (factors_ij == 1L) { + dk <- dk * ncols(contr1[[i]]) + } else if (factors_ij == 2L) { + dk <- dk * ncols(contr2[[i]]) + } + } else { + dk <- dk * columns[[i]] } - } else { - dk <- dk * columns[[i]] } - } - - if (typeof(dk) == "double") { - error(paste0("term ", j, " would require ", dk, " columns")) - } - count[[j]] <- dk - dnc <- dnc + dk - } + + if (typeof(dk) == "double") { + error(paste0("term ", j, " would require ", dk, " columns")) + } + count[[j]] <- dk + dnc <- dnc + dk + } + } # Record which columns of the design matrix are associated with which model terms assign <- integer(dnc) @@ -1090,15 +1098,17 @@ modelmatrix <- function(formula, modelframe) { assign[[k]] <- 0L k <- k + 1 } - for (j in 1:nterms) { - if (count[[j]] <= 0L) { - warning(paste0("problem with term ", j, " in model.matrix: no columns are assigned")) + if(nterms > 0L) { + for (j in 1:nterms) { + if (count[[j]] <= 0L) { + warning(paste0("problem with term ", j, " in model.matrix: no columns are assigned")) + } + + # idx.seq covers columns that are associated with term 'j' + idx.seq <- seq(k, length.out = count[[j]]) + assign[idx.seq] <- j + k <- k + count[[j]] } - - # idx.seq covers columns that are associated with term 'j' - idx.seq <- seq(k, length.out = count[[j]]) - assign[idx.seq] <- j - k <- k + count[[j]] } # Create column labels for the matrix columns. @@ -1122,58 +1132,60 @@ modelmatrix <- function(formula, modelframe) { # append them together with ':', this gives us 'x', 'q', 'x:q'. Plus # some special handling that makes it less straightforward - for (j in 1:nterms) { - if (j == rhs_response) { - next - } - for (kk in 1:count[j]) { - first <- TRUE - indx <- kk - 1 # zero base like in GnuR C code - buffer <- "" - for (i in 1:nvar) { - ll <- factors[i,j] - if (ll != 0L) { - var_i <- variable[[i]] - if (!first) { - buffer <- paste0(buffer, ":") - } - first <- FALSE - if (is.factor(var_i) || is.logical(var_i)) { - if (ll == 1) { - x = ColumnNames(contr1[[i]]) - ll <- ncols(contr1[[i]]) - } else { - x = ColumnNames(contr2[[i]]) - ll <- ncols(contr2[[i]]) - } - buffer <- paste0(buffer, vnames[[i]]) - if (is.null(x)) { - buffer <- paste0(buffer, indx %% ll + 1) - } else { - buffer <- paste0(buffer, x[[indx %% ll + 1]]) + if(nterms > 0L) { + for (j in 1:nterms) { + if (j == rhs_response) { + next + } + for (kk in 1:count[j]) { + first <- TRUE + indx <- kk - 1 # zero base like in GnuR C code + buffer <- "" + for (i in 1:nvar) { + ll <- factors[i,j] + if (ll != 0L) { + var_i <- variable[[i]] + if (!first) { + buffer <- paste0(buffer, ":") } - } else if (is.complex(var_i)) { - error("complex variables are not currently allowed in model matrices"); - } else if (is.numeric(var_i)) { - x = ColumnNames(var_i) - ll = ncols(var_i) - buffer = paste0(buffer, vnames[[i]]) - if (ll > 1L) { + first <- FALSE + if (is.factor(var_i) || is.logical(var_i)) { + if (ll == 1) { + x = ColumnNames(contr1[[i]]) + ll <- ncols(contr1[[i]]) + } else { + x = ColumnNames(contr2[[i]]) + ll <- ncols(contr2[[i]]) + } + buffer <- paste0(buffer, vnames[[i]]) if (is.null(x)) { buffer <- paste0(buffer, indx %% ll + 1) } else { buffer <- paste0(buffer, x[[indx %% ll + 1]]) } + } else if (is.complex(var_i)) { + error("complex variables are not currently allowed in model matrices"); + } else if (is.numeric(var_i)) { + x = ColumnNames(var_i) + ll = ncols(var_i) + buffer = paste0(buffer, vnames[[i]]) + if (ll > 1L) { + if (is.null(x)) { + buffer <- paste0(buffer, indx %% ll + 1) + } else { + buffer <- paste0(buffer, x[[indx %% ll + 1]]) + } + } + } else { + error(paste0("variables of type '", typeof(var_i), "' are not allowed in model matrices")) } - } else { - error(paste0("variables of type '", typeof(var_i), "' are not allowed in model matrices")) + indx <- indx %/% ll; } - indx <- indx %/% ll; } + + xnames[[k]] <- buffer + k <- k + 1 } - - xnames[[k]] <- buffer - k <- k + 1 } } @@ -1202,54 +1214,56 @@ modelmatrix <- function(formula, modelframe) { jnext <- as.integer(intercept) + 1 jstart <- jnext contrast <- NULL - for (k in 1:nterms) { - if (k == rhs_response) { next } - # for each term we go through the rows in corresponding column in 'factor' - for (i in 1:nvar) { - if (columns[[i]] == 0L) { next } # num of cols == 0 - var_i <- variable[[i]] - factor_ik <- factors[i,k] - - # if factor for this variable is != 0 we do some action with it, resulting - # into putting new columns into the result 'x'. This moves jnext by the - # number of new columns, jstart tells us the first column that was copied - # within this innermost loop - if (factor_ik == 0L) { next } - if (factor_ik == 1L) { - contrast <- contr1[[i]] - } else { - contrast <- contr2[[i]] - } - - # is this the first non-zero factor in this factor column? - if (jnext == jstart) { - if (nlevs[[i]] > 0L) { - for (j in 1:ncols(contrast)) { - x[,jstart + j - 1] = get.col(contrast,j)[var_i] - } - jnext = jnext + ncols(contrast) + if(nterms > 0L) { + for (k in 1:nterms) { + if (k == rhs_response) { next } + # for each term we go through the rows in corresponding column in 'factor' + for (i in 1:nvar) { + if (columns[[i]] == 0L) { next } # num of cols == 0 + var_i <- variable[[i]] + factor_ik <- factors[i,k] + + # if factor for this variable is != 0 we do some action with it, resulting + # into putting new columns into the result 'x'. This moves jnext by the + # number of new columns, jstart tells us the first column that was copied + # within this innermost loop + if (factor_ik == 0L) { next } + if (factor_ik == 1L) { + contrast <- contr1[[i]] } else { - # first variable in this term is simply copied, note that it can - # be a matrix or a vector, this assignment handles both: - # vector is treated as a single column matrix - x[, seq(jstart, length.out = ncols(var_i))] <- var_i - jnext = jnext + ncols(var_i) + contrast <- contr2[[i]] } - } else { - if (nlevs[[i]] > 0L) { - cont.var = matrix(0L, nrows(var_i), ncols(contrast)) - for (j in 1:ncols(contrast)) { - cont.var[,j] = get.col(contrast,j)[var_i] - } - x <- addvar(x, jstart, jnext - jstart, cont.var) - jnext <- jnext + (jnext - jstart) * (ncols(contrast) - 1); + + # is this the first non-zero factor in this factor column? + if (jnext == jstart) { + if (nlevs[[i]] > 0L) { + for (j in 1:ncols(contrast)) { + x[,jstart + j - 1] = get.col(contrast,j)[var_i] + } + jnext = jnext + ncols(contrast) + } else { + # first variable in this term is simply copied, note that it can + # be a matrix or a vector, this assignment handles both: + # vector is treated as a single column matrix + x[, seq(jstart, length.out = ncols(var_i))] <- var_i + jnext = jnext + ncols(var_i) + } } else { - x <- addvar(x, jstart, jnext - jstart, var_i) - jnext <- jnext + (jnext - jstart) * (ncols(var_i) - 1); + if (nlevs[[i]] > 0L) { + cont.var = matrix(0L, nrows(var_i), ncols(contrast)) + for (j in 1:ncols(contrast)) { + cont.var[,j] = get.col(contrast,j)[var_i] + } + x <- addvar(x, jstart, jnext - jstart, cont.var) + jnext <- jnext + (jnext - jstart) * (ncols(contrast) - 1); + } else { + x <- addvar(x, jstart, jnext - jstart, var_i) + jnext <- jnext + (jnext - jstart) * (ncols(var_i) - 1); + } } } + jstart <- jnext } - jstart <- jnext } dimnames(x) <- list(row.names(modelframe), xnames) diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h index 3d29cb9f88548f2536114d3b2b9e893a6499d498..e48fc20e3ce43ba1249164d1c78ab328bd6df01d 100644 --- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h +++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h @@ -275,6 +275,8 @@ typedef double (*call_Rf_qunif)(double a, double b, double c, int d, int e); typedef double (*call_Rf_dunif)(double a, double b, double c, int d); typedef double (*call_Rf_punif)(double a, double b, double c, int d, int e); typedef double (*call_Rf_runif)(double x, double y); +typedef SEXP (*call_Rf_match)(SEXP itable, SEXP ix, int nmatch); +typedef Rboolean (*call_Rf_NonNullStringMatch)(SEXP s, SEXP t); typedef SEXP (*call_getvar)(); diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h index e028d1c383ec401a6d1307c87ad3aa41b295b6c0..a86b1d5693b84d22db836eb98851b7078a19216d 100644 --- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h +++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h @@ -67,103 +67,106 @@ #define R_do_new_object_x 62 #define R_do_slot_x 63 #define R_do_slot_assign_x 64 -#define R_getContextCall_x 65 -#define R_getContextEnv_x 66 -#define R_getContextFun_x 67 -#define R_getContextSrcRef_x 68 -#define R_getGlobalFunctionContext_x 69 -#define R_getParentFunctionContext_x 70 -#define R_insideBrowser_x 71 -#define R_isEqual_x 72 -#define R_isGlobal_x 73 -#define R_lsInternal3_x 74 -#define R_new_custom_connection_x 75 -#define R_tryEval_x 76 -#define Rf_GetOption1_x 77 -#define Rf_PairToVectorList_x 78 -#define Rf_ScalarDouble_x 79 -#define Rf_ScalarInteger_x 80 -#define Rf_ScalarLogical_x 81 -#define Rf_ScalarString_x 82 -#define Rf_VectorToPairList_x 83 -#define Rf_allocArray_x 84 -#define Rf_allocMatrix_x 85 -#define Rf_allocVector_x 86 -#define Rf_any_duplicated_x 87 -#define Rf_asChar_x 88 -#define Rf_asCharacterFactor_x 89 -#define Rf_asInteger_x 90 -#define Rf_asLogical_x 91 -#define Rf_asReal_x 92 -#define Rf_classgets_x 93 -#define Rf_coerceVector_x 94 -#define Rf_cons_x 95 -#define Rf_copyListMatrix_x 96 -#define Rf_copyMatrix_x 97 -#define Rf_copyMostAttrib_x 98 -#define Rf_defineVar_x 99 -#define Rf_dunif_x 100 -#define Rf_duplicate_x 101 -#define Rf_error_x 102 -#define Rf_errorcall_x 103 -#define Rf_eval_x 104 -#define Rf_findFun_x 105 -#define Rf_findVar_x 106 -#define Rf_findVarInFrame_x 107 -#define Rf_findVarInFrame3_x 108 -#define Rf_getAttrib_x 109 -#define Rf_gsetVar_x 110 -#define Rf_inherits_x 111 -#define Rf_install_x 112 -#define Rf_installChar_x 113 -#define Rf_isNull_x 114 -#define Rf_isString_x 115 -#define Rf_lengthgets_x 116 -#define Rf_mkCharLenCE_x 117 -#define Rf_namesgets_x 118 -#define Rf_ncols_x 119 -#define Rf_nrows_x 120 -#define Rf_protect_x 121 -#define Rf_punif_x 122 -#define Rf_qunif_x 123 -#define Rf_runif_x 124 -#define Rf_setAttrib_x 125 -#define Rf_str2type_x 126 -#define Rf_unprotect_x 127 -#define Rf_unprotect_ptr_x 128 -#define Rf_warning_x 129 -#define Rf_warningcall_x 130 -#define Rprintf_x 131 -#define SETCADR_x 132 -#define SETCAR_x 133 -#define SETCDR_x 134 -#define SET_NAMED_FASTR_x 135 -#define SET_RDEBUG_x 136 -#define SET_RSTEP_x 137 -#define SET_S4_OBJECT_x 138 -#define SET_STRING_ELT_x 139 -#define SET_SYMVALUE_x 140 -#define SET_TAG_x 141 -#define SET_TYPEOF_FASTR_x 142 -#define SET_VECTOR_ELT_x 143 -#define STRING_ELT_x 144 -#define SYMVALUE_x 145 -#define TAG_x 146 -#define TYPEOF_x 147 -#define UNSET_S4_OBJECT_x 148 -#define VECTOR_ELT_x 149 -#define forceSymbols_x 150 -#define getCCallable_x 151 -#define getConnectionClassString_x 152 -#define getOpenModeString_x 153 -#define getSummaryDescription_x 154 -#define isSeekable_x 155 -#define registerCCallable_x 156 -#define registerRoutines_x 157 -#define setDotSymbolValues_x 158 -#define unif_rand_x 159 -#define useDynamicSymbols_x 160 +#define R_getClassDef_x 65 +#define R_getContextCall_x 66 +#define R_getContextEnv_x 67 +#define R_getContextFun_x 68 +#define R_getContextSrcRef_x 69 +#define R_getGlobalFunctionContext_x 70 +#define R_getParentFunctionContext_x 71 +#define R_insideBrowser_x 72 +#define R_isEqual_x 73 +#define R_isGlobal_x 74 +#define R_lsInternal3_x 75 +#define R_new_custom_connection_x 76 +#define R_tryEval_x 77 +#define Rf_GetOption1_x 78 +#define Rf_NonNullStringMatch_x 79 +#define Rf_PairToVectorList_x 80 +#define Rf_ScalarDouble_x 81 +#define Rf_ScalarInteger_x 82 +#define Rf_ScalarLogical_x 83 +#define Rf_ScalarString_x 84 +#define Rf_VectorToPairList_x 85 +#define Rf_allocArray_x 86 +#define Rf_allocMatrix_x 87 +#define Rf_allocVector_x 88 +#define Rf_any_duplicated_x 89 +#define Rf_asChar_x 90 +#define Rf_asCharacterFactor_x 91 +#define Rf_asInteger_x 92 +#define Rf_asLogical_x 93 +#define Rf_asReal_x 94 +#define Rf_classgets_x 95 +#define Rf_coerceVector_x 96 +#define Rf_cons_x 97 +#define Rf_copyListMatrix_x 98 +#define Rf_copyMatrix_x 99 +#define Rf_copyMostAttrib_x 100 +#define Rf_defineVar_x 101 +#define Rf_dunif_x 102 +#define Rf_duplicate_x 103 +#define Rf_error_x 104 +#define Rf_errorcall_x 105 +#define Rf_eval_x 106 +#define Rf_findFun_x 107 +#define Rf_findVar_x 108 +#define Rf_findVarInFrame_x 109 +#define Rf_findVarInFrame3_x 110 +#define Rf_getAttrib_x 111 +#define Rf_gsetVar_x 112 +#define Rf_inherits_x 113 +#define Rf_install_x 114 +#define Rf_installChar_x 115 +#define Rf_isNull_x 116 +#define Rf_isString_x 117 +#define Rf_lengthgets_x 118 +#define Rf_match_x 119 +#define Rf_mkCharLenCE_x 120 +#define Rf_namesgets_x 121 +#define Rf_ncols_x 122 +#define Rf_nrows_x 123 +#define Rf_protect_x 124 +#define Rf_punif_x 125 +#define Rf_qunif_x 126 +#define Rf_runif_x 127 +#define Rf_setAttrib_x 128 +#define Rf_str2type_x 129 +#define Rf_unprotect_x 130 +#define Rf_unprotect_ptr_x 131 +#define Rf_warning_x 132 +#define Rf_warningcall_x 133 +#define Rprintf_x 134 +#define SETCADR_x 135 +#define SETCAR_x 136 +#define SETCDR_x 137 +#define SET_NAMED_FASTR_x 138 +#define SET_RDEBUG_x 139 +#define SET_RSTEP_x 140 +#define SET_S4_OBJECT_x 141 +#define SET_STRING_ELT_x 142 +#define SET_SYMVALUE_x 143 +#define SET_TAG_x 144 +#define SET_TYPEOF_FASTR_x 145 +#define SET_VECTOR_ELT_x 146 +#define STRING_ELT_x 147 +#define SYMVALUE_x 148 +#define TAG_x 149 +#define TYPEOF_x 150 +#define UNSET_S4_OBJECT_x 151 +#define VECTOR_ELT_x 152 +#define forceSymbols_x 153 +#define getCCallable_x 154 +#define getConnectionClassString_x 155 +#define getOpenModeString_x 156 +#define getSummaryDescription_x 157 +#define isSeekable_x 158 +#define registerCCallable_x 159 +#define registerRoutines_x 160 +#define setDotSymbolValues_x 161 +#define unif_rand_x 162 +#define useDynamicSymbols_x 163 -#define UPCALLS_TABLE_SIZE 161 +#define UPCALLS_TABLE_SIZE 164 #endif // RFFI_UPCALLSINDEX_H diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h index 583fee9348251042d78bd2bcb00ff56c65674652..a02784c1a830733cbbc6fc698410e357676b13d5 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h @@ -1316,8 +1316,8 @@ SEXP R_do_MAKE_CLASS(const char *what) { } SEXP R_getClassDef (const char *what) { - TRACE0(); - return unimplemented("R_getClassDef"); + TRACE(TARGs, what); + return ((call_R_getClassDef) callbacks[R_getClassDef_x])(what); } SEXP R_do_new_object(SEXP class_def) { diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Utils.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/Utils.c index 6c0a8d482cb9556b55b8475a0cd61c8c016d41b7..7b3a17dfc2a2dbd3fccb08d5040d491df232d83e 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Utils.c +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Utils.c @@ -41,3 +41,10 @@ void Rf_onintr() { // TODO: implement interrupt handling, signal errors // ignored } + +Rboolean isOrdered(SEXP s) +{ + return (TYPEOF(s) == INTSXP + && inherits(s, "factor") + && inherits(s, "ordered")); +} diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/match.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/match.c new file mode 100644 index 0000000000000000000000000000000000000000..9a5d46d50c869f5e9fe00e6f214e34dc3a9c2387 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/match.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include "../truffle_nfi/rffiutils.h" +#include "rffi_upcalls.h" + +Rboolean Rf_NonNullStringMatch(SEXP s, SEXP t) +{ + return ((call_Rf_NonNullStringMatch) callbacks[Rf_NonNullStringMatch_x])(s, t); +} + diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/unique.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/unique.c new file mode 100644 index 0000000000000000000000000000000000000000..bfbe23c5f82fc85abce5a9e272bc5a7c9bbc93b2 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/unique.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +#include "../truffle_nfi/rffiutils.h" +#include "rffi_upcalls.h" + +SEXP Rf_matchE(SEXP itable, SEXP ix, int nmatch, SEXP env) +{ + unimplemented("Rf_matchE"); +} + +/* used from other code, not here: */ +SEXP Rf_match(SEXP itable, SEXP ix, int nmatch) +{ + return ((call_Rf_match) callbacks[Rf_match_x])(itable, ix, nmatch); +} + diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c index 4f2042988b31bef3a8ac79452ddd45ca2e7cfaf6..9aa78ee7998c9dcc0cd21c9f8b39bcb9b7a9fee8 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c @@ -88,3 +88,9 @@ SEXP Rf_allocS4Object() { return NULL; } +SEXP do_address(SEXP call, SEXP op, SEXP args, SEXP rho) +{ + checkArity(op, args); + return R_MakeExternalPtr((void *) CAR(args), R_NilValue, R_NilValue); +} + diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source index 81b5c5d06cc0b8290c264b408abb32cc0986e8f2..a2720097dccb441015beb4f75766b9908ad46f5a 100644 --- a/com.oracle.truffle.r.native/version.source +++ b/com.oracle.truffle.r.native/version.source @@ -1 +1 @@ -37 +39 diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java index 33b9f53eb2bcc6da41a102539f92b1e8d6ca6f2e..33364751766bc9dd9cd61da732615d77464bd0bb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java @@ -36,6 +36,7 @@ import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.RASTUtils; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; @@ -79,6 +80,7 @@ import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -435,11 +437,14 @@ public abstract class Bind extends RBaseNode { @Specialization(guards = {"precedence != NO_PRECEDENCE", "args.length == 1"}) protected Object allOneElem(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, @Cached("create()") GetNamesAttributeNode getNamesNode) { + RAbstractVector vec = vectorProfile.profile(castVector(args[0])); - int[] rawDimensions = getVectorDimensions(vec); + int[] rawDimensions = null; + rawDimensions = getVectorDimensions(vec); if (GetDimAttributeNode.isMatrix(rawDimensions)) { return vec; } + // for cbind dimNamesA is names for the 1st dim and dimNamesB is names for 2nd dim; for // rbind the other way around Object dimNamesA = getNamesNode.getNames(vec); @@ -574,7 +579,7 @@ public abstract class Bind extends RBaseNode { @Specialization protected Object bind(VirtualFrame frame, int deparseLevel, RArgsValuesAndNames args) { - RFunction dispatchFunction = createDispatchFunction(frame, args.getArguments()); + RFunction dispatchFunction = createDispatchFunction(frame, args.getArguments(), deparseLevel); if (hasDispatchFunction.profile(dispatchFunction != null)) { if (dispatchCallNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -607,9 +612,20 @@ public abstract class Bind extends RBaseNode { return precedence; } - private RFunction createDispatchFunction(VirtualFrame frame, Object[] args) { + private RFunction createDispatchFunction(VirtualFrame frame, Object[] args, int deparseLevel) { + + // S4 dispatch is only considered if deparseLevel is non-negative + boolean tryS4 = deparseLevel >= 0; + + // indicating if any of the arguments is an S4 object + boolean anyS4 = false; + Result result = null; for (Object arg : args) { + if (tryS4 && !anyS4 && RRuntime.isS4Object(arg)) { + anyS4 = true; + } + RStringVector clazz = classHierarchy.execute(arg); if (hasClassProfile.profile(clazz != null)) { if (lookup == null) { @@ -630,7 +646,17 @@ public abstract class Bind extends RBaseNode { } } } - return result != null ? result.function : null; + + RFunction dispatchFunction = result != null ? result.function : null; + + // TODO class compatibility: record if S3 classes were compatible, if not, do S4 + // dispatch + // In this case, call function 'methods::cbind' or 'methods::rbind'. + if (dispatchFunction == null && anyS4) { + REnvironment methodsEnv = REnvironment.getRegisteredNamespace("methods"); + dispatchFunction = ReadVariableNode.lookupFunction(type.name(), methodsEnv.getFrame(), true, true); + } + return dispatchFunction; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java index 14cc631717cbcc5bcf1db61d9a08a405b3432d25..9c105a0af64c45af2c5b086f125805916f891f3a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java @@ -168,6 +168,7 @@ public class EnvFunctions { } @Specialization + @TruffleBoundary protected REnvironment asEnvironment(RList list, @Cached("new()") RList2EnvNode list2Env) { REnvironment env = RDataFactory.createNewEnv(null); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java index ea9010d63eb5986035bdaf2631fd9772d243f1c1..45aa94bc53f72db3833e6658748a32c94382e84e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java @@ -925,7 +925,14 @@ public class GrepFunctions { @TruffleBoundary private static Matcher getPatternMatcher(String pattern, String text, boolean ignoreCase) { - return Pattern.compile(pattern, ignoreCase ? Pattern.CASE_INSENSITIVE : 0).matcher(text); + String actualPattern = pattern; + + // If a pattern starts with a '*', GnuR virtually prepends an empty string literal to + // the star. This won't match anything, so just remove '*' from the pattern. + if (pattern.length() > 0 && pattern.charAt(0) == '*') { + actualPattern = pattern.substring(1); + } + return Pattern.compile(actualPattern, ignoreCase ? Pattern.CASE_INSENSITIVE : 0).matcher(text); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java index 53a2fe0007ca4e46b1486dddb6a8a4aa6dd8fd86..286ed49c6b59006cfbce45ef2992eb83e971dd03 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode.isMatrix; +import static com.oracle.truffle.r.runtime.RDispatch.OPS_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -62,7 +63,7 @@ import com.oracle.truffle.r.runtime.data.nodes.GetReadonlyData; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; -@RBuiltin(name = "%*%", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE) +@RBuiltin(name = "%*%", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE, dispatch = OPS_GROUP_GENERIC) public abstract class MatMult extends RBuiltinNode.Arg2 { private static final int BLOCK_SIZE = 64; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java index c211bb753ea774dc4e87c6f5e7e69554bbd9067b..b4b9c2b17c39951b94199db27ce9e3f712a5dbaa 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java @@ -57,7 +57,7 @@ public abstract class IsElementFastPath extends RFastPathNode { return RRuntime.LOGICAL_FALSE; } - @Specialization(replaces = "iselementOneCachedString") + @Specialization(guards = "elIn.getLength() == 1", replaces = "iselementOneCachedString") protected Byte iselementOne(RAbstractStringVector elIn, RAbstractStringVector setIn, @Cached("create()") BranchProfile trueProfile, @Cached("create()") BranchProfile falseProfile) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java index 704efdd2428bf484eaa6f68d93543e322ce81b28..647e0140bbf6faecbe62e14a6d897253acc45e6b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java @@ -42,6 +42,7 @@ import com.oracle.truffle.r.library.stats.CompleteCases; import com.oracle.truffle.r.library.stats.CovcorNodeGen; import com.oracle.truffle.r.library.stats.CutreeNodeGen; import com.oracle.truffle.r.library.stats.DoubleCentreNodeGen; +import com.oracle.truffle.r.library.stats.PPSum; import com.oracle.truffle.r.library.stats.RMultinomNode; import com.oracle.truffle.r.library.stats.RandFunctionsNodes; import com.oracle.truffle.r.library.stats.RandFunctionsNodes.RandFunction1Node; @@ -84,6 +85,7 @@ import com.oracle.truffle.r.runtime.data.RExternalPtr; 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.nodes.MaterializeNode; import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; @@ -222,6 +224,7 @@ public class CallAndExternalFunctions { public abstract static class DotCall extends LookupAdapter { @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getCallRFFI().createInvokeCallNode(); + @Child MaterializeNode materializeNode = MaterializeNode.create(); static { Casts.noCasts(DotCall.class); @@ -232,6 +235,14 @@ public class CallAndExternalFunctions { return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY, RMissing.instance}; } + private Object[] materializeArgs(VirtualFrame frame, Object[] args) { + Object[] materializedArgs = new Object[args.length]; + for (int i = 0; i < args.length; i++) { + materializedArgs[i] = materializeNode.execute(frame, args[i]); + } + return materializedArgs; + } + @Override @TruffleBoundary public RExternalBuiltinNode lookupBuiltin(RList symbol) { @@ -570,6 +581,7 @@ public class CallAndExternalFunctions { case "ar2ma": case "Burg": case "intgrt_vec": + return PPSum.IntgrtVecNode.create(); case "pp_sum": case "Fexact": case "Fisher_sim": @@ -653,12 +665,12 @@ public class CallAndExternalFunctions { */ @SuppressWarnings("unused") @Specialization(limit = "2", guards = {"cached == symbol", "builtin == null"}) - protected Object callNamedFunction(RList symbol, RArgsValuesAndNames args, Object packageName, + protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName, @Cached("symbol") RList cached, @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin, @Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo, @Cached("extractSymbolInfo.execute(symbol)") NativeCallInfo nativeCallInfo) { - return callRFFINode.dispatch(nativeCallInfo, args.getArguments()); + return callRFFINode.dispatch(nativeCallInfo, materializeArgs(frame, args.getArguments())); } /** @@ -667,24 +679,24 @@ public class CallAndExternalFunctions { */ @SuppressWarnings("unused") @Specialization(replaces = {"callNamedFunction", "doExternal"}) - protected Object callNamedFunctionGeneric(RList symbol, RArgsValuesAndNames args, Object packageName, + protected Object callNamedFunctionGeneric(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName, @Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo) { RExternalBuiltinNode builtin = lookupBuiltin(symbol); if (builtin != null) { throw RInternalError.shouldNotReachHere("Cache for .Calls with FastR reimplementation (lookupBuiltin(...) != null) exceeded the limit"); } NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(symbol); - return callRFFINode.dispatch(nativeCallInfo, args.getArguments()); + return callRFFINode.dispatch(nativeCallInfo, materializeArgs(frame, args.getArguments())); } /** * {@code .NAME = string}, no package specified. */ @Specialization - protected Object callNamedFunction(String symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName, + protected Object callNamedFunction(VirtualFrame frame, String symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName, @Cached("createRegisteredNativeSymbol(CallNST)") DLL.RegisteredNativeSymbol rns, @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { - return callNamedFunctionWithPackage(symbol, args, null, rns, findSymbolNode); + return callNamedFunctionWithPackage(frame, symbol, args, null, rns, findSymbolNode); } /** @@ -692,19 +704,19 @@ public class CallAndExternalFunctions { * define that symbol. */ @Specialization - protected Object callNamedFunctionWithPackage(String symbol, RArgsValuesAndNames args, String packageName, + protected Object callNamedFunctionWithPackage(VirtualFrame frame, String symbol, RArgsValuesAndNames args, String packageName, @Cached("createRegisteredNativeSymbol(CallNST)") DLL.RegisteredNativeSymbol rns, @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "Call", packageName); } - return callRFFINode.dispatch(new NativeCallInfo(symbol, func, rns.getDllInfo()), args.getArguments()); + return callRFFINode.dispatch(new NativeCallInfo(symbol, func, rns.getDllInfo()), materializeArgs(frame, args.getArguments())); } @Specialization - protected Object callNamedFunctionWithPackage(RExternalPtr symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { - return callRFFINode.dispatch(new NativeCallInfo("", symbol.getAddr(), null), args.getArguments()); + protected Object callNamedFunctionWithPackage(VirtualFrame frame, RExternalPtr symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { + return callRFFINode.dispatch(new NativeCallInfo("", symbol.getAddr(), null), materializeArgs(frame, args.getArguments())); } @SuppressWarnings("unused") diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java index 7ce6f47b092713c0e5503f85b28e24f883381c98..f6e1fdd15a338630359f8e342e595a831ae2df34 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java @@ -274,7 +274,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { @TruffleBoundary private static Object materializeLanguage(RAbstractVector extractedVector) { - return RContext.getRRuntimeASTAccess().fromList((RList) extractedVector, RLanguage.RepType.CALL); + return RContext.getRRuntimeASTAccess().createLanguageFromList((RList) extractedVector, RLanguage.RepType.CALL); } private Object extract(int dimensionIndex, RAbstractStringVector vector, Object pos, PositionProfile profile) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java index 71a7e7c7183b7deb12ec8bcccd4e06d9167c3026..73b47fda388a25673352a3f2d033143354008629 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java @@ -318,7 +318,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { private Object wrapResult(RAbstractVector vector, RLanguage.RepType repType) { switch (vectorType) { case Language: - return RContext.getRRuntimeASTAccess().fromList((RList) vector, repType); + return RContext.getRRuntimeASTAccess().createLanguageFromList((RList) vector, repType); default: return vector; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java index f645d23f52d00e855f51b0d7c639e3258d8755b5..7e916de094572174a6c4088fa2f33f694366a7c2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java @@ -23,10 +23,12 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public abstract class CastToVectorNode extends CastNode { @@ -73,6 +75,12 @@ public abstract class CastToVectorNode extends CastNode { return vector; } + @Specialization + protected RAbstractVector cast(@SuppressWarnings("unused") RS4Object s4obj) { + // TODO implement according to function 'R_getS4DataSlot' in 'attrib.c' + throw error(RError.Message.CANNOT_COERCE_S4_TO_VECTOR); + } + public static CastToVectorNode create() { return CastToVectorNodeGen.create(false); } 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 dd4aaab8b46974711c0040fa695013a13b086015..a23208b85715f53cc7e1d68eb2e53fe2cab517f1 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 @@ -633,6 +633,7 @@ public final class RError extends RuntimeException implements TruffleException { POS_NOT_ALLOWED_WITH_NUMERIC("pos argument not allowed with a numeric value"), OBJ_CANNOT_BE_ATTRIBUTED("external object cannot be attributed"), CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR("no method for coercing this external object to a %s"), + CANNOT_COERCE_S4_TO_VECTOR("no method for coercing this S4 class to a vector"), // the following list is incomplete (but like GNU-R) INVALID_FORMAT_DOUBLE("invalid format '%s'; use format %%f, %%e, %%g or %%a for numeric objects"), INVALID_LOGICAL("'%s' must be TRUE or FALSE"), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java index 144cb8f2ac25ace0926f56dce84638b94b966c50..a1c5c0a19fb2ad08e6e77f39bb5e5444dedf544b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java @@ -945,4 +945,8 @@ public class RRuntime { private static boolean hasDims(RAbstractContainer xa) { return xa.hasDimensions(); } + + public static boolean isS4Object(Object o) { + return o instanceof RTypedValue && ((RTypedValue) o).isS4(); + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java index fe78327aeb55db9317feefacba162cdefeb53f8e..cda344489795bd1c53400e6741bf16cb43d66dfc 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java @@ -73,7 +73,7 @@ public interface RRuntimeASTAccess { * object whose rep is a {@code RCallNode} with the first list element as the function and the * remainder as the arguments, or a {@code RFunction} (as determined by repType). */ - Object fromList(RList list, RLanguage.RepType repType); + Object createLanguageFromList(RList list, RLanguage.RepType repType); /** * Get the "names" attribute for an {@link RLanguage} object, or {@code null} if none. diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java index 9c2e312f17d16967ac88b13b55f18ba26b0bc23e..de9ff2b821a97f48a5dc9189edde8caa77b27dd2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java @@ -193,19 +193,26 @@ public final class NativeDataAccess { RObject obj = (RObject) arg; NativeMirror mirror = (NativeMirror) obj.getNativeMirror(); if (mirror == null) { - obj.setNativeMirror(mirror = arg instanceof CustomNativeMirror ? new NativeMirror(((CustomNativeMirror) arg).getCustomMirrorAddress()) : new NativeMirror()); - // System.out.println(String.format("adding %16x = %s", mirror.id, - // obj.getClass().getSimpleName())); - nativeMirrors.put(mirror.id, new WeakReference<>(obj)); - if (TRACE_MIRROR_ALLOCATION_SITES) { - registerAllocationSite(arg, mirror); - } + mirror = putMirrorObject(arg, obj); } return mirror.id; } throw UnsupportedMessageException.raise(Message.AS_POINTER); } + @TruffleBoundary + private static NativeMirror putMirrorObject(Object arg, RObject obj) { + NativeMirror mirror; + obj.setNativeMirror(mirror = arg instanceof CustomNativeMirror ? new NativeMirror(((CustomNativeMirror) arg).getCustomMirrorAddress()) : new NativeMirror()); + // System.out.println(String.format("adding %16x = %s", mirror.id, + // obj.getClass().getSimpleName())); + nativeMirrors.put(mirror.id, new WeakReference<>(obj)); + if (TRACE_MIRROR_ALLOCATION_SITES) { + registerAllocationSite(arg, mirror); + } + return mirror; + } + @TruffleBoundary private static void registerAllocationSite(Object arg, NativeMirror mirror) { nativeMirrorInfo.put(mirror.id, new RuntimeException(arg.getClass().getSimpleName() + " " + arg)); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java index aa46ff8da7eb3ac5072177291084578551044f86..9595b1723d5c17dcc0d31deb33a7ee1db2fd77e5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java @@ -84,7 +84,7 @@ public final class RLanguage extends RSharingAttributeStorage implements RAbstra } else { l = (RList) o; } - return RContext.getRRuntimeASTAccess().fromList(l, type); + return RContext.getRRuntimeASTAccess().createLanguageFromList(l, type); } public RBaseNode getRep() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/MaterializeNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/MaterializeNode.java new file mode 100644 index 0000000000000000000000000000000000000000..67f641bca46d4247ce9de3b0bbe5433c9c90c7e9 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/nodes/MaterializeNode.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.runtime.data.nodes; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; + +public abstract class MaterializeNode extends Node { + + protected static final int LIMIT = 10; + + public abstract Object execute(VirtualFrame frame, Object arg); + + @Specialization(limit = "LIMIT", guards = {"vec.getClass() == cachedClass"}) + protected RAbstractContainer doAbstractContainerCached(RAbstractContainer vec, + @SuppressWarnings("unused") @Cached("vec.getClass()") Class<?> cachedClass) { + return vec.materialize(); + } + + @Specialization(replaces = "doAbstractContainerCached") + protected RAbstractContainer doAbstractContainer(RAbstractContainer vec) { + return vec.materialize(); + } + + @Fallback + protected Object doGeneric(Object o) { + return o; + } + + public static MaterializeNode create() { + return MaterializeNodeGen.create(); + } + +} 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 c2bfbac1b9ae02f97a2bd5912071e6303b647bfb..4d659845e40e4825ac4a691c081af846975cc15c 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 @@ -26029,6 +26029,14 @@ integer(0) #grep('))', '))') [1] 1 +##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep# +#grep('*', c('prefix.lsmc', 'arm'), value = TRUE) +[1] "prefix.lsmc" "arm" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep# +#grep('*.lsmc', c('prefix.lsmc', 'arm'), value = TRUE) +[1] "prefix.lsmc" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep# #grep('[(]', ')') integer(0) @@ -47152,6 +47160,10 @@ y2 2 4 y1 1 3 y2 2 4 +##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testGenericDispatch#Output.IgnoreErrorContext# +#{ setClass('fooo', slots = c(a='numeric')); obj <- new('fooo'); rbind(obj) } +Error in rbind2(..1) : no method for coercing this S4 class to a vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rbind.testGenericDispatch# #{ v <- 1; class(v) <- 'foo'; assign('rbind.foo', function(x) {'foo'}, envir=.__S3MethodsTable__.); result <- rbind(v) ; rm('rbind.foo', envir=.__S3MethodsTable__.); result;} [1] "foo" @@ -80242,6 +80254,41 @@ Error in get("x") : object 'x' not found #{ x <- function(){3} ; gg <- function() { assign("x", 4) ; g <- function() { if (FALSE) { x <- 2 } ; f <- function() { h <- function() { x() } ; h() } ; f() } ; g() } ; gg() } [1] 3 +##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement# +#{ is.element('b', c('a', 'b', 'b')) } +[1] TRUE + +##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement# +#{ is.element(c('a', 'b', 'b'), 'b') } +[1] FALSE TRUE TRUE + +##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement# +#{ is.element(c(1:10,rep(11,10)), 1) } + [1] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE +[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE + +##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement# +#{ is.element(c(1:10,rep(11,10)), 11) } + [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE +[13] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE + +##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement# +#{ is.element(c(1:10,rep(11,10)), c(1:10,rep(11,10))) } + [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE +[16] TRUE TRUE TRUE TRUE TRUE + +##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement# +#{ is.element(paste0('a', 1:10), 'a0') } + [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE + +##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement# +#{ is.element(paste0('a', 1:10), 'a1') } + [1] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE + +##com.oracle.truffle.r.test.library.base.TestIsElement.testIsElement# +#{ is.element(paste0('a', c(1:10, rep(11,2))), 'a11') } + [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE + ##com.oracle.truffle.r.test.library.base.TestPromiseOptimizations.testDeoptimization# #{ delayedAssign('x', c(1,2,3)); x/180; x } [1] 1 2 3 @@ -152299,6 +152346,10 @@ list(cyl, hp, mpg, disp, drat, wt, qsec, vs, am, gear, carb) 9 8 9 10 9 10 +##com.oracle.truffle.r.test.library.stats.TestFormulae.testModelFrame# +#{y<-0:9;z<-1:10;k<-2:11;w<-3:12;m<-4:13;u<-5:14;v<-6:15;; model.frame(terms.formula(~1)) } +data frame with 0 columns and 0 rows + ##com.oracle.truffle.r.test.library.stats.TestFormulae.testModelFrame# #{y<-0:9;z<-1:10;k<-2:11;w<-3:12;m<-4:13;u<-5:14;v<-6:15;; model.frame(terms.formula(~k+y+z)) } k y z @@ -152523,6 +152574,10 @@ list(cyl, hp, mpg, disp, drat, wt, qsec, vs, am, gear, carb) 9 8 c 10 9 c +##com.oracle.truffle.r.test.library.stats.TestFormulae.testModelFrame# +#{y<-0:9;z<-1:10;k<-2:11;w<-3:12;m<-4:13;u<-5:14;v<-6:15;k <- factor(rep(c('m', 'f'), 5));z <- factor(c(rep(c('a', 'b', 'c'), 3), 'c')); ; model.frame(terms.formula(~1)) } +data frame with 0 columns and 0 rows + ##com.oracle.truffle.r.test.library.stats.TestFormulae.testModelFrame# #{y<-0:9;z<-1:10;k<-2:11;w<-3:12;m<-4:13;u<-5:14;v<-6:15;k <- factor(rep(c('m', 'f'), 5));z <- factor(c(rep(c('a', 'b', 'c'), 3), 'c')); ; model.frame(terms.formula(~k+y+z)) } k y z @@ -152777,6 +152832,11 @@ attr(,"assign") attr(,"assign") [1] 0 1 +##com.oracle.truffle.r.test.library.stats.TestFormulae.testModelMatrix# +#{y<-0:9;z<-1:10;k<-2:11;w<-3:12;m<-4:13;u<-5:14;v<-6:15;; model.matrix(model.frame(terms.formula(~1))) } +Error in formula.data.frame(object, env = baseenv()) : + cannot create a formula from a zero-column data frame + ##com.oracle.truffle.r.test.library.stats.TestFormulae.testModelMatrix# #{y<-0:9;z<-1:10;k<-2:11;w<-3:12;m<-4:13;u<-5:14;v<-6:15;; model.matrix(model.frame(terms.formula(~k+y+z))) } (Intercept) k y z @@ -153107,6 +153167,11 @@ attr(,"contrasts")$z [1] "contr.treatment" +##com.oracle.truffle.r.test.library.stats.TestFormulae.testModelMatrix# +#{y<-0:9;z<-1:10;k<-2:11;w<-3:12;m<-4:13;u<-5:14;v<-6:15;k <- factor(rep(c('m', 'f'), 5));z <- factor(c(rep(c('a', 'b', 'c'), 3), 'c')); ; model.matrix(model.frame(terms.formula(~1))) } +Error in formula.data.frame(object, env = baseenv()) : + cannot create a formula from a zero-column data frame + ##com.oracle.truffle.r.test.library.stats.TestFormulae.testModelMatrix# #{y<-0:9;z<-1:10;k<-2:11;w<-3:12;m<-4:13;u<-5:14;v<-6:15;k <- factor(rep(c('m', 'f'), 5));z <- factor(c(rep(c('a', 'b', 'c'), 3), 'c')); ; model.matrix(model.frame(terms.formula(~k+y+z))) } (Intercept) km y zb zc @@ -153626,6 +153691,33 @@ $variables list(y, z) +##com.oracle.truffle.r.test.library.stats.TestFormulae.testTermsform# +#f <- terms.formula(~1); attrs <- attributes(f); envIdx <- which(names(attrs)=='.Environment'); print(attrs[envIdx]); attrs[sort(names(attrs[-envIdx]))] +$.Environment +<environment: R_GlobalEnv> + +$class +[1] "terms" "formula" + +$factors +integer(0) + +$intercept +[1] 1 + +$order +integer(0) + +$response +[1] 0 + +$term.labels +character(0) + +$variables +list() + + ##com.oracle.truffle.r.test.library.stats.TestFormulae.testTermsform# #f <- terms.formula(~k+y+z); attrs <- attributes(f); envIdx <- which(names(attrs)=='.Environment'); print(attrs[envIdx]); attrs[sort(names(attrs[-envIdx]))] $.Environment diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java index d5c5148e5700bf77b247ef7607dab95add6a7a71..36a3bd4f1f3d6cf5fd2defd05d41942532c389b4 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java @@ -107,6 +107,8 @@ public class TestBuiltin_grep extends TestBase { assertEval(Output.IgnoreErrorMessage, "grep('([)]', ')')"); assertEval(Output.IgnoreErrorMessage, "grep('([(]', ')')"); assertEval(Output.IgnoreErrorMessage, "grep('(()', ')')"); + assertEval("grep('*.lsmc', c('prefix.lsmc', 'arm'), value = TRUE)"); + assertEval("grep('*', c('prefix.lsmc', 'arm'), value = TRUE)"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java index 558032e94439942a684f70b658f4e5392f6cc237..ccf9cc0a6af505c946cd22616e20791a9619997e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rbind.java @@ -111,6 +111,9 @@ public class TestBuiltin_rbind extends TestBase { assertEval("{ v1 <- 1; class(v1) <- 'foo1'; rbind.foo1 <- function(...) 'foo1'; v2 <- 2; class(v2) <- 'foo2'; rbind.foo2 <- function(...) 'foo2'; rbind(v1, v2) }"); assertEval("{ v1 <- 1; class(v1) <- 'foo1'; rbind.foo1 <- function(...) 'foo1'; v2 <- 2; class(v2) <- 'foo2'; rbind(v1, v2) }"); assertEval("{ v1 <- 1; class(v1) <- 'foo1'; v2 <- 2; class(v2) <- 'foo2'; rbind.foo2 <- function(...) 'foo2'; rbind(v1, v2) }"); + + // S4 + assertEval(Output.IgnoreErrorContext, "{ setClass('fooo', slots = c(a='numeric')); obj <- new('fooo'); rbind(obj) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestIsElement.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestIsElement.java new file mode 100644 index 0000000000000000000000000000000000000000..ec27ac1989d18ed27bcb3aa637022e37904f87e4 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestIsElement.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.library.base; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestIsElement extends TestBase { + + @Test + public void testIsElement() { + assertEval("{ is.element(c('a', 'b', 'b'), 'b') }"); + assertEval("{ is.element('b', c('a', 'b', 'b')) }"); + assertEval("{ is.element(paste0('a', 1:10), 'a1') }"); + assertEval("{ is.element(paste0('a', 1:10), 'a0') }"); + assertEval("{ is.element(paste0('a', c(1:10, rep(11,2))), 'a11') }"); + assertEval("{ is.element(c(1:10,rep(11,10)), 1) }"); + assertEval("{ is.element(c(1:10,rep(11,10)), 11) }"); + assertEval("{ is.element(c(1:10,rep(11,10)), c(1:10,rep(11,10))) }"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestFormulae.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestFormulae.java index c2d7be4e0b73e889737f4a424536c3a14a7ba03e..76faa10ddb6f317796b42ff353e03a8aee98c84d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestFormulae.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestFormulae.java @@ -60,7 +60,7 @@ public class TestFormulae extends TestBase { "y~z", "y~1+z", "y~0+z", "y~-1+z", "y~z*k", "y~z*k+w*m", "u~z*k+w*m", "y~z:k", "y~z^2", "y~(z+k)^2", "y~z*((m+w)^3)", "y~(z+k)*(w+u)", "y~w%in%v", "y~w/k", "y~(1 + w/k)", - "~k+y+z" + "~k+y+z", "~1" }; /**