Skip to content

Commit f3a0556

Browse files
committed
[GR-11533] Seamless way to create data frame from Java and other languages.
PullRequest: fastr/1711
2 parents c9e42a7 + 45bd4f3 commit f3a0556

File tree

37 files changed

+5520
-9468
lines changed

37 files changed

+5520
-9468
lines changed

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MathFunctionsNodes.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
3939
import com.oracle.truffle.r.runtime.data.nodes.GetReadonlyData;
4040
import com.oracle.truffle.r.runtime.ffi.interop.UnsafeAdapter;
41-
import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
41+
import com.oracle.truffle.r.runtime.interop.ConvertForeignObjectNode;
4242
import com.oracle.truffle.r.runtime.nmath.BesselFunctions;
4343
import com.oracle.truffle.r.runtime.nmath.Beta;
4444
import com.oracle.truffle.r.runtime.nmath.Choose;
@@ -695,7 +695,7 @@ abstract static class BesselExNode extends Node {
695695

696696
@Child private Node bIsPointerNode = Message.IS_POINTER.createNode();
697697
@Child private Node bAsPointerNode;
698-
@Child private ForeignArray2R bForeignArray2R;
698+
@Child private ConvertForeignObjectNode bConvertForeign;
699699

700700
public abstract double execute(BesselExCaller caller, Object b);
701701

@@ -717,11 +717,11 @@ protected double besselEx(BesselExCaller caller, Object b,
717717
throw RInternalError.shouldNotReachHere("IS_POINTER message returned true, AS_POINTER should not fail");
718718
}
719719
} else {
720-
if (bForeignArray2R == null) {
720+
if (bConvertForeign == null) {
721721
CompilerDirectives.transferToInterpreterAndInvalidate();
722-
bForeignArray2R = insert(ForeignArray2R.create());
722+
bConvertForeign = insert(ConvertForeignObjectNode.create());
723723
}
724-
bVec = (RAbstractDoubleVector) bForeignArray2R.convert(bTO);
724+
bVec = (RAbstractDoubleVector) bConvertForeign.convert(bTO);
725725
}
726726

727727
return caller.call(bReadonlyData.execute(bVec.materialize()));

com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
3838
import com.oracle.truffle.r.runtime.data.nodes.VectorAccess;
3939
import com.oracle.truffle.r.runtime.data.nodes.VectorAccess.SequentialIterator;
40-
import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
40+
import com.oracle.truffle.r.runtime.interop.ConvertForeignObjectNode;
4141
import com.oracle.truffle.r.runtime.nmath.MathFunctions;
4242
import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function2_1;
4343
import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function2_2;
@@ -214,8 +214,8 @@ public abstract static class RfRMultinomNode extends FFIUpCallNode.Arg4 {
214214
@Child private Node probAsPointerNode;
215215
@Child private Node rNIsPointerNode = Message.IS_POINTER.createNode();
216216
@Child private Node rNAsPointerNode;
217-
@Child private ForeignArray2R probForeignArray2R;
218-
@Child private ForeignArray2R rNForeignArray2R;
217+
@Child private ConvertForeignObjectNode probConvertForeign;
218+
@Child private ConvertForeignObjectNode rNConvertForeign;
219219
@Child private DoRMultinomNode doRMultinomNode = RandFunctionsNodesFactory.DoRMultinomNodeGen.create();
220220

221221
@Specialization
@@ -237,11 +237,11 @@ protected Object evaluate(int n, Object prob, int k, Object rN) {
237237
throw RInternalError.shouldNotReachHere("IS_POINTER message returned true, AS_POINTER should not fail");
238238
}
239239
} else {
240-
if (probForeignArray2R == null) {
240+
if (probConvertForeign == null) {
241241
CompilerDirectives.transferToInterpreterAndInvalidate();
242-
probForeignArray2R = insert(ForeignArray2R.create());
242+
probConvertForeign = insert(ConvertForeignObjectNode.create());
243243
}
244-
probVector = (RAbstractDoubleVector) probForeignArray2R.convert(probTO);
244+
probVector = (RAbstractDoubleVector) probConvertForeign.convert(probTO);
245245
}
246246

247247
RAbstractIntVector rNVector;
@@ -259,11 +259,11 @@ protected Object evaluate(int n, Object prob, int k, Object rN) {
259259
throw RInternalError.shouldNotReachHere("IS_POINTER message returned true, AS_POINTER should not fail");
260260
}
261261
} else {
262-
if (rNForeignArray2R == null) {
262+
if (rNConvertForeign == null) {
263263
CompilerDirectives.transferToInterpreterAndInvalidate();
264-
rNForeignArray2R = insert(ForeignArray2R.create());
264+
rNConvertForeign = insert(ConvertForeignObjectNode.create());
265265
}
266-
rNVector = (RAbstractIntVector) rNForeignArray2R.convert(probTO);
266+
rNVector = (RAbstractIntVector) rNConvertForeign.convert(probTO);
267267
}
268268

269269
doRMultinomNode.execute(n, probVector, k, rNVector);

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
7676
import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
7777
import com.oracle.truffle.r.runtime.env.REnvironment;
78-
import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
78+
import com.oracle.truffle.r.runtime.interop.ConvertForeignObjectNode;
7979
import com.oracle.truffle.r.runtime.nodes.RBaseNode;
8080

8181
@ImportStatic(RRuntime.class)
@@ -153,9 +153,13 @@ protected Object asVector(Object x, String mode,
153153
@Cached("fromMode(cachedMode)") RType type,
154154
@Cached("createCast(type)") CastNode cast,
155155
@Cached("create(type)") DropAttributesNode drop,
156-
@Cached("create()") ForeignArray2R foreignArray2R) {
156+
@Cached("create()") ConvertForeignObjectNode convertForeign) {
157157
if (RRuntime.isForeignObject(x)) {
158-
Object o = foreignArray2R.convert((TruffleObject) x);
158+
if (type == RType.List) {
159+
// already returns list, no need to cast
160+
return convertForeign.convertToList((TruffleObject) x, true, true);
161+
}
162+
Object o = convertForeign.convert((TruffleObject) x, true, true);
159163
if (!RRuntime.isForeignObject(o)) {
160164
return cast == null ? o : cast.doCast(o);
161165
}

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ public BasePackage() {
486486
add(FastRInterop.JavaIsInstance.class, FastRInteropFactory.JavaIsInstanceNodeGen::create);
487487
add(FastRInterop.JavaAsTruffleObject.class, FastRInteropFactory.JavaAsTruffleObjectNodeGen::create);
488488
add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create);
489-
add(FastRInterop.FromForeignArray.class, FastRInteropFactory.FromForeignArrayNodeGen::create);
489+
add(FastRInterop.AsVector.class, FastRInteropFactory.AsVectorNodeGen::create);
490490
add(FastRInterop.ToByte.class, FastRInteropFactory.ToByteNodeGen::create);
491491
add(FastRInterop.ToChar.class, FastRInteropFactory.ToCharNodeGen::create);
492492
add(FastRInterop.ToFloat.class, FastRInteropFactory.ToFloatNodeGen::create);

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java

Lines changed: 6 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,40 @@
2222
*/
2323
package com.oracle.truffle.r.nodes.builtin.base;
2424

25-
import com.oracle.truffle.api.CompilerDirectives;
2625
import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
2726
import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
2827
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
2928

3029
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
31-
import com.oracle.truffle.api.TruffleLanguage;
3230
import com.oracle.truffle.api.dsl.Cached;
3331
import com.oracle.truffle.api.dsl.Fallback;
3432
import com.oracle.truffle.api.dsl.ImportStatic;
3533
import com.oracle.truffle.api.dsl.Specialization;
36-
import com.oracle.truffle.api.interop.ForeignAccess;
37-
import com.oracle.truffle.api.interop.InteropException;
38-
import com.oracle.truffle.api.interop.Message;
3934
import com.oracle.truffle.api.interop.TruffleObject;
40-
import com.oracle.truffle.api.interop.UnknownIdentifierException;
41-
import com.oracle.truffle.api.interop.UnsupportedMessageException;
42-
import com.oracle.truffle.api.nodes.Node;
4335
import com.oracle.truffle.api.profiles.ConditionProfile;
4436
import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
4537
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
46-
import com.oracle.truffle.r.runtime.RInternalError;
4738
import com.oracle.truffle.r.runtime.RRuntime;
4839
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
49-
import com.oracle.truffle.r.runtime.context.RContext;
50-
import com.oracle.truffle.r.runtime.data.RDataFactory;
5140
import com.oracle.truffle.r.runtime.data.RNull;
5241
import com.oracle.truffle.r.runtime.data.RStringVector;
5342
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
5443
import com.oracle.truffle.r.runtime.env.REnvironment;
44+
import com.oracle.truffle.r.runtime.interop.GetForeignKeysNode;
5545

56-
@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
46+
@ImportStatic(RRuntime.class)
5747
@RBuiltin(name = "names", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
5848
public abstract class Names extends RBuiltinNode.Arg1 {
5949

6050
private final ConditionProfile hasNames = ConditionProfile.createBinaryProfile();
61-
@Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
62-
@Child private Node executeNode;
6351

6452
static {
6553
Casts.noCasts(Names.class);
6654
}
6755

6856
@Specialization
69-
protected Object getNames(RAbstractContainer container) {
57+
protected Object getNames(RAbstractContainer container,
58+
@Cached("create()") GetNamesAttributeNode getNames) {
7059
RStringVector names = getNames.getNames(container);
7160
if (hasNames.profile(names != null)) {
7261
return names;
@@ -83,54 +72,8 @@ protected Object getNames(REnvironment env) {
8372

8473
@Specialization(guards = "isForeignObject(obj)")
8574
protected Object getNames(TruffleObject obj,
86-
@Cached("GET_SIZE.createNode()") Node getSizeNode,
87-
@Cached("KEYS.createNode()") Node keysNode,
88-
@Cached("READ.createNode()") Node readNode) {
89-
90-
try {
91-
String[] names;
92-
try {
93-
names = readKeys(keysNode, obj, getSizeNode, readNode);
94-
} catch (UnsupportedMessageException e) {
95-
// because it is a java function, java.util.Map (has special handling too) ... ?
96-
return RNull.instance;
97-
}
98-
String[] staticNames = new String[0];
99-
RContext context = RContext.getInstance();
100-
TruffleLanguage.Env env = context.getEnv();
101-
if (env.isHostObject(obj) && !(env.asHostObject(obj) instanceof Class)) {
102-
if (executeNode == null) {
103-
CompilerDirectives.transferToInterpreterAndInvalidate();
104-
executeNode = insert(Message.EXECUTE.createNode());
105-
}
106-
try {
107-
TruffleObject clazzStatic = context.toJavaStatic(obj, readNode, executeNode);
108-
staticNames = readKeys(keysNode, clazzStatic, getSizeNode, readNode);
109-
} catch (UnknownIdentifierException | NoSuchFieldError | UnsupportedMessageException e) {
110-
}
111-
}
112-
if (names.length == 0 && staticNames.length == 0) {
113-
return RNull.instance;
114-
}
115-
String[] result = new String[names.length + staticNames.length];
116-
System.arraycopy(names, 0, result, 0, names.length);
117-
System.arraycopy(staticNames, 0, result, names.length, staticNames.length);
118-
return RDataFactory.createStringVector(result, true);
119-
} catch (InteropException e) {
120-
throw RInternalError.shouldNotReachHere(e);
121-
}
122-
}
123-
124-
private static String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode)
125-
throws UnknownIdentifierException, InteropException, UnsupportedMessageException {
126-
TruffleObject keys = ForeignAccess.sendKeys(keysNode, obj);
127-
int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys);
128-
String[] names = new String[size];
129-
for (int i = 0; i < size; i++) {
130-
Object value = ForeignAccess.sendRead(readNode, keys, i);
131-
names[i] = (String) value;
132-
}
133-
return names;
75+
@Cached("create()") GetForeignKeysNode foreignKeys) {
76+
return foreignKeys.execute(obj, true);
13477
}
13578

13679
@Fallback
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# This code is free software; you can redistribute it and/or modify it
5+
# under the terms of the GNU General Public License version 3 only, as
6+
# published by the Free Software Foundation.
7+
#
8+
# This code is distributed in the hope that it will be useful, but WITHOUT
9+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
# version 3 for more details (a copy is included in the LICENSE file that
12+
# accompanied this code).
13+
#
14+
# You should have received a copy of the GNU General Public License version
15+
# 3 along with this work; if not, write to the Free Software Foundation,
16+
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
#
18+
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
# or visit www.oracle.com if you need additional information or have any
20+
# questions.
21+
22+
as.matrix.polyglot.value <- function(x, ...) {
23+
v <- .fastr.interop.asVector(x, recursive=TRUE, dropDimensions=FALSE)
24+
return(as.matrix(v), ...)
25+
}
26+
27+
as.array.polyglot.value <- function(x, ...) {
28+
v <- .fastr.interop.asVector(x, recursive=TRUE, dropDimensions=FALSE)
29+
return(as.array(v), ...)
30+
}
31+
32+
as.data.frame.polyglot.value <- function(x, row.names = NULL, optional = FALSE, ..., nm = paste(deparse(substitute(x),
33+
width.cutoff = 500L), collapse = " ")) {
34+
v <- .fastr.interop.asVector(x, recursive=TRUE, dropDimensions=FALSE)
35+
if (!optional && !is.null(v) && is.atomic(v)) {
36+
v <- list(v)
37+
names(v) <- nm
38+
}
39+
as.data.frame(v, row.names=row.names, optional=optional, ...)
40+
}

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
6565
import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
6666
import com.oracle.truffle.r.runtime.interop.Foreign2R;
67-
import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
67+
import com.oracle.truffle.r.runtime.interop.ConvertForeignObjectNode;
6868

6969
@ImportStatic({Message.class, RRuntime.class})
7070
@RBuiltin(name = "unlist", kind = INTERNAL, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE)
@@ -83,9 +83,9 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
8383
@Child private RecursiveLength recursiveLengthNode;
8484
@Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
8585
@Child private Node hasSizeNode;
86-
@Child private ForeignArray2R foreignArray2RNode;
86+
@Child private ConvertForeignObjectNode convertForeignNode;
8787

88-
@ImportStatic({Message.class, RRuntime.class, ForeignArray2R.class})
88+
@ImportStatic({Message.class, RRuntime.class, ConvertForeignObjectNode.class})
8989
@TypeSystemReference(RTypes.class)
9090
protected abstract static class UnlistLength extends Node {
9191

@@ -110,7 +110,7 @@ protected int getLength(Object operand) {
110110
}
111111
}
112112

113-
@ImportStatic({Message.class, RRuntime.class, ForeignArray2R.class})
113+
@ImportStatic({Message.class, RRuntime.class, ConvertForeignObjectNode.class})
114114
@TypeSystemReference(RTypes.class)
115115
protected abstract static class RecursiveLength extends Node {
116116

@@ -292,12 +292,12 @@ protected Object unlistPairList(RPairList list, boolean recursive, boolean useNa
292292
@Specialization(guards = {"isForeignArray(obj)"})
293293
protected Object unlistForeignArray(VirtualFrame frame, TruffleObject obj, boolean recursive, boolean useNames,
294294
@SuppressWarnings("unused") @Cached("HAS_SIZE.createNode()") Node hasSize,
295-
@Cached("create()") ForeignArray2R foreignArray2R) {
296-
return unlistForeign(frame, obj, recursive, useNames, foreignArray2R);
295+
@Cached("create()") ConvertForeignObjectNode convertForeign) {
296+
return unlistForeign(frame, obj, recursive, useNames, convertForeign);
297297
}
298298

299-
private Object unlistForeign(VirtualFrame frame, TruffleObject obj, boolean recursive, boolean useNames, ForeignArray2R foreignArray2R) {
300-
Object result = foreignArray2R.convert(obj, recursive);
299+
private Object unlistForeign(VirtualFrame frame, TruffleObject obj, boolean recursive, boolean useNames, ConvertForeignObjectNode convertForeign) {
300+
Object result = convertForeign.convert(obj, recursive);
301301
if (result instanceof RAbstractListVector) {
302302
result = execute(frame, result, recursive, useNames);
303303
}
@@ -316,7 +316,7 @@ protected Object unlist(Object o, Object recursive, Object useNames) {
316316
}
317317

318318
protected boolean isForeignArray(Object obj) {
319-
return ForeignArray2R.isForeignArray(obj, getHasSizeNode());
319+
return ConvertForeignObjectNode.isForeignArray(obj, getHasSizeNode());
320320
}
321321

322322
/**
@@ -329,12 +329,12 @@ private RAbstractVector foreignToVector(TruffleObject obj, boolean recursive) {
329329
return (RAbstractVector) getForeignArray2RNode().convert(obj, recursive);
330330
}
331331

332-
private ForeignArray2R getForeignArray2RNode() {
333-
if (foreignArray2RNode == null) {
332+
private ConvertForeignObjectNode getForeignArray2RNode() {
333+
if (convertForeignNode == null) {
334334
CompilerDirectives.transferToInterpreterAndInvalidate();
335-
foreignArray2RNode = insert(ForeignArray2R.create());
335+
convertForeignNode = insert(ConvertForeignObjectNode.create());
336336
}
337-
return foreignArray2RNode;
337+
return convertForeignNode;
338338
}
339339

340340
private Node getHasSizeNode() {

0 commit comments

Comments
 (0)