Skip to content

Commit

Permalink
[GR-32296] Backport of "Add tests for vctrs and tibble".
Browse files Browse the repository at this point in the history
PullRequest: fastr/2634
  • Loading branch information
Pavel Marek committed Jun 25, 2021
2 parents e0d2ce8 + 97f29e0 commit 8e83c03
Show file tree
Hide file tree
Showing 28 changed files with 1,047 additions and 161 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# 21.2.0
* Support for packages in 2021-02-01 CRAN snapshot:
* testthat 3.0.1 is partially supported.
* FastR does not support parallel tests run, i.e. run testthat only with `Sys.setenv(TESTTHAT_PARALLEL="false")`.
* tibble 3.0.6 , vctrs 0.3.6, and data.table 1.13.6 are mostly supported.
* Support for dplyr 1.0.3, ggplot 3.3.3, and knitr 1.31 is a work in progress.

Bug fixes:

* `read.dcf` does not ignore whitespaces in fields any more.
* `list.files` gives correct result in a subdirectory with the same prefix as its parent directory.
* Whitespaces in quantifiers in regular expressions are ignored.
* GNU-R does not comply with PCRE with this behavior.
* `sys.frame` displays frames for `NextMethod` correctly.
* `parent.frame` is able to get the frame that is no longer on the stack.
* Which is not recommended due to the documentation of `parent.frame`, but some packages do that nonetheless.

# 21.1.0

* Upgraded FastR to R 4.0.3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,19 +437,8 @@ public Object Rf_allocVector(int mode, long n) {
}

@Override
@TruffleBoundary
public Object Rf_allocArray(int mode, Object dimsObj) {
RIntVector dims = (RIntVector) dimsObj;
int n = 1;
int[] newDims = new int[dims.getLength()];
// TODO check long vector
for (int i = 0; i < newDims.length; i++) {
newDims[i] = dims.getDataAt(i);
n *= newDims[i];
}
RAbstractVector result = (RAbstractVector) Rf_allocVector(mode, n);
setDims(newDims, result);
return result;
throw implementedAsNode();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, 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
Expand All @@ -26,17 +26,20 @@
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.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.nodes.unary.CastStringNode;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
import com.oracle.truffle.r.runtime.data.RComplexVector;
import com.oracle.truffle.r.runtime.data.RDoubleVector;
import com.oracle.truffle.r.runtime.data.RStringVector;
import com.oracle.truffle.r.runtime.data.RSymbol;
import com.oracle.truffle.r.runtime.data.RTypes;
import com.oracle.truffle.r.runtime.data.VectorDataLibrary;
import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
import com.oracle.truffle.r.runtime.data.RComplexVector;
import com.oracle.truffle.r.runtime.data.RStringVector;

@TypeSystemReference(RTypes.class)
public abstract class AsCharNode extends FFIUpCallNode.Arg1 {
Expand All @@ -51,14 +54,21 @@ protected CharSXPWrapper asChar(CharSXPWrapper obj) {
}

@Specialization
protected CharSXPWrapper asChar(RStringVector obj, @Cached("createBinaryProfile()") ConditionProfile profile, @Cached("createBinaryProfile()") ConditionProfile naProfile,
@Cached("createBinaryProfile()") ConditionProfile isNativized,
@Cached("createBinaryProfile()") ConditionProfile wrapProfile) {
if (profile.profile(obj.getLength() == 0)) {
protected CharSXPWrapper asChar(RStringVector obj,
@Cached("createBinaryProfile()") ConditionProfile zeroLengthProfile,
@Cached("createBinaryProfile()") ConditionProfile naProfile,
@CachedLibrary(limit = "getTypedVectorDataLibraryCacheSize()") VectorDataLibrary dataLib) {
if (zeroLengthProfile.profile(obj.getLength() == 0)) {
return CharSXPWrapper_NA;
} else {
obj.wrapStrings(isNativized, wrapProfile);
CharSXPWrapper result = obj.getWrappedDataAt(0);
Object newCharSXPData = null;
try {
newCharSXPData = dataLib.materializeCharSXPStorage(obj.getData());
} catch (UnsupportedMessageException e) {
throw RInternalError.shouldNotReachHere(e);
}
obj.setData(newCharSXPData);
CharSXPWrapper result = dataLib.getCharSXPAt(obj.getData(), 0);
return naProfile.profile(RRuntime.isNA(result.getContents())) ? CharSXPWrapper_NA : result;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2021, 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 3 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 3 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
* 3 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.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RIntVector;
import com.oracle.truffle.r.runtime.data.VectorDataLibrary;
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
import com.oracle.truffle.r.runtime.data.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;

public abstract class RfAllocArrayNode extends FFIUpCallNode.Arg2 {
public static RfAllocArrayNode create() {
return RfAllocArrayNodeGen.create();
}

@Specialization(guards = "mode == type.code", limit = "getGenericDataLibraryCacheSize()")
protected static Object allocArrayCached(@SuppressWarnings("unused") int mode, RIntVector dims,
@Cached(value = "getType(mode)", allowUncached = true) SEXPTYPE type,
@CachedLibrary("dims.getData()") VectorDataLibrary dimsDataLib,
@Cached SetDimAttributeNode setDimNode) {
CompilerAsserts.compilationConstant(type);
return allocArray(dims, dimsDataLib, type, setDimNode);
}

@Specialization(replaces = "allocArrayCached")
@TruffleBoundary
protected static Object allocArrayUncached(int mode, RIntVector dims, @Cached SetDimAttributeNode setDimNode) {
return allocArray(dims, VectorDataLibrary.getFactory().getUncached(), getType(mode), setDimNode);
}

private static Object allocArray(RIntVector dims, VectorDataLibrary dimsDataLib, SEXPTYPE type, SetDimAttributeNode setDimNode) {
Object dimsData = dims.getData();
int dimsLen = dimsDataLib.getLength(dimsData);
int[] newDims = new int[dimsLen];
int totalLen = 1;
for (int i = 0; i < dimsLen; i++) {
int dimLen = dimsDataLib.getIntAt(dimsData, i);
newDims[i] = dimLen;
totalLen *= dimLen;
}
Object array = RDataFactory.createEmptyVectorFromSEXPType(type, totalLen);
if (!(array instanceof RAbstractContainer)) {
throw RInternalError.shouldNotReachHere("Type not implemented for Rf_allocArray");
} else {
setDimNode.setDimensions((RAbstractContainer) array, newDims);
return array;
}
}

protected static SEXPTYPE getType(int mode) {
return SEXPTYPE.mapInt(mode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@
*/
package com.oracle.truffle.r.ffi.impl.nodes;

import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.unimplemented;

import java.util.Arrays;

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
Expand All @@ -34,7 +30,6 @@
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RError.Message;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;

@GenerateUncached
Expand Down Expand Up @@ -69,33 +64,7 @@ protected static Object doIt(@SuppressWarnings("unused") int mode, long n,
}
}

private static Object allocate(@Cached(value = "getType(mode)", allowUncached = true) SEXPTYPE type, int ni) {
switch (type) {
case INTSXP:
return RDataFactory.createIntVector(new int[ni], RDataFactory.COMPLETE_VECTOR);
case REALSXP:
return RDataFactory.createDoubleVector(new double[ni], RDataFactory.COMPLETE_VECTOR);
case LGLSXP:
return RDataFactory.createLogicalVector(new byte[ni], RDataFactory.COMPLETE_VECTOR);
case STRSXP:
// fill list with empty strings
String[] data = new String[ni];
Arrays.fill(data, "");
return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
case CPLXSXP:
return RDataFactory.createComplexVector(new double[2 * ni], RDataFactory.COMPLETE_VECTOR);
case RAWSXP:
return RDataFactory.createRawVector(new byte[ni]);
case VECSXP:
return RDataFactory.createList(ni);
case LISTSXP:
case LANGSXP:
return RDataFactory.createPairList(ni, type);
case NILSXP:
return RNull.instance;
default:
CompilerDirectives.transferToInterpreter();
throw unimplemented("unexpected SEXPTYPE " + type);
}
private static Object allocate(SEXPTYPE type, int ni) {
return RDataFactory.createEmptyVectorFromSEXPType(type, ni);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@

import com.oracle.truffle.api.dsl.GenerateUncached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.data.CharSXPWrapper;
import com.oracle.truffle.r.runtime.data.RStringVector;
import com.oracle.truffle.r.runtime.data.VectorDataLibrary;
Expand All @@ -35,10 +37,17 @@ public static SetStringEltNode create() {
return SetStringEltNodeGen.create();
}

@Specialization(limit = "getTypedVectorDataLibraryCacheSize()")
@Specialization
Object doIt(RStringVector vector, long index, CharSXPWrapper element,
@CachedLibrary("vector.getData()") VectorDataLibrary dataLibrary) {
dataLibrary.setStringAt(vector.getData(), (int) index, element.getContents());
@CachedLibrary(limit = "getTypedVectorDataLibraryCacheSize()") VectorDataLibrary dataLibrary) {
Object newCharSXPData = null;
try {
newCharSXPData = dataLibrary.materializeCharSXPStorage(vector.getData());
} catch (UnsupportedMessageException e) {
throw RInternalError.shouldNotReachHere(e);
}
vector.setData(newCharSXPData);
dataLibrary.setCharSXPAt(vector.getData(), (int) index, element);
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, 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
Expand All @@ -22,11 +22,13 @@
*/
package com.oracle.truffle.r.ffi.impl.nodes;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.GenerateUncached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.data.RStringVector;
import com.oracle.truffle.r.runtime.data.VectorDataLibrary;

Expand All @@ -36,17 +38,21 @@ public static StringEltNode create() {
return StringEltNodeGen.create();
}

// TODO: Make just one specialization that handles both altrep and non-altrep via
// VectorDataLibrary
@Specialization(limit = "1")
Object doStringVector(RStringVector stringVector, long index,
@CachedLibrary("stringVector.getData()") VectorDataLibrary dataLibrary,
@Cached("createBinaryProfile()") ConditionProfile isAltrepProfile) {
if (isAltrepProfile.profile(stringVector.isAltRep())) {
return dataLibrary.getStringAt(stringVector, (int) index);
} else {
stringVector.wrapStrings();
return stringVector.getWrappedDataAt((int) index);
@CachedLibrary(limit = "getTypedVectorDataLibraryCacheSize()") VectorDataLibrary genericDataLib,
@CachedLibrary("stringVector.getData()") VectorDataLibrary stringVecDataLib) {
Object newCharSXPData = null;
try {
newCharSXPData = stringVecDataLib.materializeCharSXPStorage(stringVector.getData());
} catch (UnsupportedMessageException e) {
throw RInternalError.shouldNotReachHere(e);
}
stringVector.setData(newCharSXPData);
if (index > Integer.MAX_VALUE) {
CompilerDirectives.transferToInterpreter();
throw RError.error(RError.NO_CALLER, RError.Message.LONG_VECTORS_NOT_SUPPORTED);
}
return genericDataLib.getCharSXPAt(stringVector.getData(), (int) index);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodes;
import com.oracle.truffle.r.ffi.impl.nodes.RawGetRegionNode;
import com.oracle.truffle.r.ffi.impl.nodes.RealGetRegionNode;
import com.oracle.truffle.r.ffi.impl.nodes.RfAllocArrayNode;
import com.oracle.truffle.r.ffi.impl.nodes.RfAllocVectorNode;
import com.oracle.truffle.r.ffi.impl.nodes.RfEvalNode;
import com.oracle.truffle.r.ffi.impl.nodes.RfFindFun;
Expand Down Expand Up @@ -283,6 +284,7 @@ public interface StdUpCallsRFFI {
Object Rf_allocVector(int mode, long n);

@RFFIRunGC
@RFFIUpCallNode(value = RfAllocArrayNode.class, needsCallTarget = true)
Object Rf_allocArray(int mode, Object dimsObj);

@RFFIRunGC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,6 @@ public final class RFFIUpCallTargets {
public volatile RootCallTarget AsS4;

public volatile RootCallTarget Match5UpCallNode;

public volatile RootCallTarget RfAllocArrayNode;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021, 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
Expand Down Expand Up @@ -1121,34 +1121,8 @@ static int getDataLength(RStringVector vector, Object[] data) {
}
}

static String getData(RStringVector vector, Object data, int index) {
if (noStringNative.isValid() || data != null) {
Object localData = data;
if (localData instanceof String[]) {
return ((String[]) localData)[index];
}
assert data instanceof CharSXPWrapper[] : localData;
assert ((CharSXPWrapper[]) localData)[index] != null;
return ((CharSXPWrapper[]) localData)[index].getContents();
} else {
return getStringNativeMirrorData(vector.getNativeMirror(), index).getContents();
}
}

static void setData(RStringVector vector, Object data, int index, String value) {
assert data != null;
if (data instanceof String[]) {
assert !vector.isNativized();
((String[]) data)[index] = value;
} else {
assert data instanceof CharSXPWrapper[] : data;
CharSXPWrapper elem = CharSXPWrapper.create(value);
((CharSXPWrapper[]) data)[index] = elem;

if (!noStringNative.isValid() && vector.isNativized()) {
NativeDataAccess.setNativeMirrorStringData(vector.getNativeMirror(), index, elem);
}
}
static CharSXPWrapper getData(RStringVector vector, int index) {
return getStringNativeMirrorData(vector.getNativeMirror(), index);
}

static void setData(RStringVector vector, CharSXPWrapper[] data, int index, CharSXPWrapper value) {
Expand Down
Loading

0 comments on commit 8e83c03

Please sign in to comment.