Skip to content

Commit 24e71c6

Browse files
committed
[GR-11533] Seamless way to create data frame from Java and other languages - second round.
PullRequest: fastr/1728
2 parents a0b7a47 + cb0845f commit 24e71c6

File tree

7 files changed

+1704
-916
lines changed

7 files changed

+1704
-916
lines changed

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RForeignWrapper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import com.oracle.truffle.r.runtime.RInternalError;
3333
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
3434
import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
35-
import com.oracle.truffle.r.runtime.interop.CopyForeignArrayNode;
35+
import com.oracle.truffle.r.runtime.interop.ForeignArrayToVectorNode;
3636

3737
public abstract class RForeignWrapper implements RAbstractVector {
3838

@@ -42,7 +42,7 @@ public abstract class RForeignWrapper implements RAbstractVector {
4242
protected static final Node UNBOX = Message.UNBOX.createNode();
4343
protected static final Node READ = Message.READ.createNode();
4444

45-
private static final CopyForeignArrayNode COPY_ARRAY = CopyForeignArrayNode.create();
45+
private static final ForeignArrayToVectorNode COPY_ARRAY = ForeignArrayToVectorNode.create();
4646

4747
protected final TruffleObject delegate;
4848

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ConvertForeignObjectNode.java

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.oracle.truffle.r.runtime.data.RForeignDoubleWrapper;
4848
import com.oracle.truffle.r.runtime.data.RForeignIntWrapper;
4949
import com.oracle.truffle.r.runtime.data.RForeignStringWrapper;
50+
import com.oracle.truffle.r.runtime.data.RForeignWrapper;
5051
import com.oracle.truffle.r.runtime.data.RNull;
5152
import com.oracle.truffle.r.runtime.data.RStringVector;
5253
import com.oracle.truffle.r.runtime.data.RVector;
@@ -77,6 +78,9 @@
7778
* <b>dropDimensions</b> parameter, either honored by the conversion or a flat vector/list is
7879
* returned.
7980
* </p>
81+
*
82+
* <b>Note</b> currently are {@link RForeignWrapper}-s used only in case of homogenous 1-dimensional
83+
* arrays resulting to a logical, double, integer or character vector.
8084
*/
8185
@ImportStatic({Message.class, RRuntime.class, RType.class})
8286
public abstract class ConvertForeignObjectNode extends RBaseNode {
@@ -86,12 +90,14 @@ public abstract class ConvertForeignObjectNode extends RBaseNode {
8690
@Child protected Foreign2R foreign2RNode;
8791
@Child protected Node keyInfoNode;
8892
@Child private ConvertForeignObjectNode recurseNode;
93+
@Child private ForeignArrayToListNode arrayToList;
94+
@Child private ForeignArrayToVectorNode arrayToVector;
8995

9096
public static ConvertForeignObjectNode create() {
9197
return ConvertForeignObjectNodeGen.create();
9298
}
9399

94-
protected abstract Object execute(Object obj, boolean recursive, boolean dropDimensions, RType type);
100+
protected abstract Object execute(Object obj, boolean recursive, boolean dropDimensions, boolean toList);
95101

96102
/**
97103
* Converts the provided foreign array to a vector or list.
@@ -147,7 +153,7 @@ public Object convert(TruffleObject truffleObject, boolean recursive) {
147153
*
148154
*/
149155
public Object convert(TruffleObject truffleObject, boolean recursive, boolean dropDimensions) {
150-
return execute(truffleObject, recursive, dropDimensions, RType.Any);
156+
return execute(truffleObject, recursive, dropDimensions, false);
151157
}
152158

153159
/**
@@ -168,7 +174,7 @@ public Object convert(TruffleObject truffleObject, boolean recursive, boolean dr
168174
* @return a list if obj is a foreign array, otherwise obj
169175
*/
170176
public Object convertToList(TruffleObject truffleObject, boolean recursive, boolean dropDimensions) {
171-
return execute(truffleObject, recursive, dropDimensions, RType.List);
177+
return execute(truffleObject, recursive, dropDimensions, true);
172178
}
173179

174180
/**
@@ -223,7 +229,7 @@ static RAbstractVector asAbstractVector(Object[] elements, int[] dims, RType typ
223229
};
224230
byte[] byteArray = new byte[size];
225231
if (dims != null) {
226-
return createVector(dims, byteArray, wba, (complete) -> RDataFactory.createLogicalVector(byteArray, complete, dropDimensions ? null : dims));
232+
return createByColVector(dims, byteArray, wba, (complete) -> RDataFactory.createLogicalVector(byteArray, complete, dropDimensions ? null : dims));
227233
} else {
228234
return createFlatVector(size, byteArray, wba, (complete) -> RDataFactory.createLogicalVector(byteArray, complete));
229235
}
@@ -235,7 +241,7 @@ static RAbstractVector asAbstractVector(Object[] elements, int[] dims, RType typ
235241
};
236242
double[] doubleArray = new double[size];
237243
if (dims != null) {
238-
return createVector(dims, doubleArray, wda, (complete) -> RDataFactory.createDoubleVector(doubleArray, complete, dropDimensions ? null : dims));
244+
return createByColVector(dims, doubleArray, wda, (complete) -> RDataFactory.createDoubleVector(doubleArray, complete, dropDimensions ? null : dims));
239245
} else {
240246
return createFlatVector(size, doubleArray, wda, (complete) -> RDataFactory.createDoubleVector(doubleArray, complete));
241247
}
@@ -247,7 +253,7 @@ static RAbstractVector asAbstractVector(Object[] elements, int[] dims, RType typ
247253
};
248254
int[] intArray = new int[size];
249255
if (dims != null) {
250-
return createVector(dims, intArray, wia, (complete) -> RDataFactory.createIntVector(intArray, complete, dropDimensions ? null : dims));
256+
return createByColVector(dims, intArray, wia, (complete) -> RDataFactory.createIntVector(intArray, complete, dropDimensions ? null : dims));
251257
} else {
252258
return createFlatVector(size, intArray, wia, (complete) -> RDataFactory.createIntVector(intArray, complete));
253259
}
@@ -259,19 +265,18 @@ static RAbstractVector asAbstractVector(Object[] elements, int[] dims, RType typ
259265
};
260266
String[] stringArray = new String[size];
261267
if (dims != null) {
262-
return createVector(dims, stringArray, wsa, (complete) -> RDataFactory.createStringVector(stringArray, complete, dropDimensions ? null : dims));
268+
return createByColVector(dims, stringArray, wsa, (complete) -> RDataFactory.createStringVector(stringArray, complete, dropDimensions ? null : dims));
263269
} else {
264270
return createFlatVector(size, stringArray, wsa, (complete) -> RDataFactory.createStringVector(stringArray, complete));
265271
}
266272
case List:
267273
case Null:
268-
// return createList(elements, null, dropDimensions ? null : dims, size);
269274
if (dims != null) {
270275
WriteArray<Object[]> wa = (array, resultIdx, sourceIdx, complete) -> {
271276
array[resultIdx] = elements[sourceIdx];
272277
};
273278
Object[] array = new Object[size];
274-
return createVector(dims, array, wa, (complete) -> RDataFactory.createList(array, dropDimensions ? null : dims));
279+
return createByColVector(dims, array, wa, (complete) -> RDataFactory.createList(array, dropDimensions ? null : dims));
275280
} else {
276281
return RDataFactory.createList(elements);
277282
}
@@ -293,7 +298,11 @@ private static <A> RAbstractVector createFlatVector(int length, A resultArray, W
293298
return createResult.apply(complete[0]);
294299
}
295300

296-
private static <A> RAbstractVector createVector(int[] dims, A resultArray, WriteArray<A> writeResultArray, Function<Boolean, RVector<?>> createResult) {
301+
/**
302+
* Creates a vector where the elements are positioned 'by collumn' according to the provided
303+
* dimensions, no matter if dim attribute is set or not.
304+
*/
305+
private static <A> RAbstractVector createByColVector(int[] dims, A resultArray, WriteArray<A> writeResultArray, Function<Boolean, RVector<?>> createResult) {
297306
boolean[] complete = new boolean[]{true};
298307
assert dims.length > 1;
299308
populateResultArray(dims, new int[dims.length], 0, new int[]{0}, resultArray, writeResultArray, complete);
@@ -337,70 +346,70 @@ private static int getResultIdx(int[] cor, int[] dims) {
337346
return idx;
338347
}
339348

340-
@Specialization(guards = {"isForeignArray(truffleObject)", "type != List"})
341-
protected Object convertArray(TruffleObject truffleObject, boolean recursive, boolean dropDimensions, @SuppressWarnings("unused") RType type,
342-
@Cached("create()") InspectForeignArrayNode inspectTruffleObject,
343-
@Cached("create()") CopyForeignArrayNode copyArray) {
349+
@Specialization(guards = {"isForeignArray(truffleObject)", "!toList"})
350+
protected Object convertArray(TruffleObject truffleObject, boolean recursive, boolean dropDimensions, @SuppressWarnings("unused") boolean toList,
351+
@Cached("create()") InspectForeignArrayNode inspectTruffleObject) {
344352
ArrayInfo arrayInfo = new ArrayInfo();
345-
inspectTruffleObject.execute(truffleObject, recursive, arrayInfo, 0);
353+
inspectTruffleObject.execute(truffleObject, recursive, arrayInfo, 0, true);
346354

347355
RType inspectedType = arrayInfo.getType();
348356
switch (inspectedType) {
349357
case Logical:
350358
if (arrayInfo.isOneDim()) {
351359
return new RForeignBooleanWrapper(truffleObject);
352360
} else {
353-
return copyArray.toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), dropDimensions);
361+
if (arrayInfo.isRectMultiDim()) {
362+
return getArrayToVectorNode().toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), dropDimensions);
363+
} else {
364+
throw error(RError.Message.GENERIC, "A non rectangular array cannot be converted to a vector, only to a list.");
365+
}
354366
}
355367
case Double:
356368
if (arrayInfo.isOneDim()) {
357369
return new RForeignDoubleWrapper(truffleObject);
358370
} else {
359-
return copyArray.toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), dropDimensions);
371+
if (arrayInfo.isRectMultiDim()) {
372+
return getArrayToVectorNode().toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), dropDimensions);
373+
} else {
374+
throw error(RError.Message.GENERIC, "A non rectangular array cannot be converted to a vector, only to a list.");
375+
}
360376
}
361377
case Integer:
362378
if (arrayInfo.isOneDim()) {
363379
return new RForeignIntWrapper(truffleObject);
364380
} else {
365-
return copyArray.toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), dropDimensions);
381+
if (arrayInfo.isRectMultiDim()) {
382+
return getArrayToVectorNode().toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), dropDimensions);
383+
} else {
384+
throw error(RError.Message.GENERIC, "A non rectangular array cannot be converted to a vector, only to a list.");
385+
}
366386
}
367387
case Character:
368388
if (arrayInfo.isOneDim()) {
369389
return new RForeignStringWrapper(truffleObject);
370390
} else {
371-
return copyArray.toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), dropDimensions);
391+
if (arrayInfo.isRectMultiDim()) {
392+
return getArrayToVectorNode().toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), dropDimensions);
393+
} else {
394+
throw error(RError.Message.GENERIC, "A non rectangular array cannot be converted to a vector, only to a list.");
395+
}
372396
}
373397
case List:
374398
case Null:
375-
return copyArray.toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), false);
399+
return getArrayToListNode().toList(truffleObject, recursive);
376400
default:
377401
throw RInternalError.shouldNotReachHere("did not handle properly: " + inspectedType);
378402
}
379403
}
380404

381-
@Specialization(guards = {"isForeignArray(truffleObject)", "type == List"})
382-
protected Object convertArrayToList(TruffleObject truffleObject, boolean recursive, @SuppressWarnings("unused") boolean dropDimensions, @SuppressWarnings("unused") RType type,
383-
@Cached("create()") InspectForeignArrayNode inspectTruffleObject,
384-
@Cached("create()") CopyForeignArrayNode copyArray) {
385-
ArrayInfo arrayInfo = new ArrayInfo();
386-
inspectTruffleObject.execute(truffleObject, recursive, arrayInfo, 0);
387-
388-
RType inspectedType = arrayInfo.getType();
389-
if (inspectedType != RType.List) {
390-
// as if in as.list(atomicVector/Matrix) - e.g. as.list(matrix(1:4, c(2,2)))
391-
// => results in a flat list
392-
return copyArray.toVector(truffleObject, recursive, type, arrayInfo.getDims(), true);
393-
} else {
394-
// as if in as.list(heterogenous Matrix)
395-
// - e.g. l<-list(1,'a',2,3);dim(l)<-c(2,2);as.list(matrix(l,c(2,2)))
396-
// => keeps the lists dimensions
397-
return copyArray.toVector(truffleObject, recursive, arrayInfo.getType(), arrayInfo.getDims(), false);
398-
}
405+
@Specialization(guards = {"isForeignArray(truffleObject)", "toList"})
406+
protected Object convertArrayToList(TruffleObject truffleObject, boolean recursive, @SuppressWarnings("unused") boolean dropDimensions, @SuppressWarnings("unused") boolean toList) {
407+
return getArrayToListNode().toList(truffleObject, recursive);
399408
}
400409

401-
@Specialization(guards = {"isForeignObject(truffleObject)", "!isForeignArray(truffleObject)", "type == List"})
410+
@Specialization(guards = {"isForeignObject(truffleObject)", "!isForeignArray(truffleObject)", "toList"})
402411
@TruffleBoundary
403-
protected Object convertObjectToList(TruffleObject truffleObject, boolean recursive, boolean dropDimensions, @SuppressWarnings("unused") RType type,
412+
protected Object convertObjectToList(TruffleObject truffleObject, boolean recursive, boolean dropDimensions, @SuppressWarnings("unused") boolean toList,
404413
@Cached("create()") GetForeignKeysNode namesNode) {
405414
Object namesObj = namesNode.execute(truffleObject, false);
406415
if (namesObj == RNull.instance) {
@@ -417,7 +426,7 @@ protected Object convertObjectToList(TruffleObject truffleObject, boolean recurs
417426
Object o = ForeignAccess.sendRead(getReadNode(), truffleObject, name);
418427
o = getForeign2RNode().execute(o);
419428
if (isForeignArray(o, hasSizeNode)) {
420-
o = getRecurseNode().execute(o, recursive, dropDimensions, RType.Any);
429+
o = getRecurseNode().execute(o, recursive, dropDimensions, false);
421430
}
422431
elements.add(o);
423432
elementNames.add(name);
@@ -429,12 +438,16 @@ protected Object convertObjectToList(TruffleObject truffleObject, boolean recurs
429438
return RDataFactory.createList(elements.toArray(new Object[elements.size()]), RDataFactory.createStringVector(elementNames.toArray(new String[elementNames.size()]), true));
430439
}
431440

432-
@Specialization(guards = {"doNotConvert(obj, type)"})
441+
@Specialization(guards = {"doNotConvert(obj, toList)"})
433442
protected Object doObject(@SuppressWarnings("unused") Object obj, @SuppressWarnings("unused") boolean recursive, @SuppressWarnings("unused") boolean dropDimensions,
434-
@SuppressWarnings("unused") RType type) {
443+
@SuppressWarnings("unused") boolean toList) {
435444
return obj;
436445
}
437446

447+
protected boolean doNotConvert(Object obj, boolean toList) {
448+
return !RRuntime.isForeignObject(obj) || (!isForeignArray(obj) && !toList);
449+
}
450+
438451
protected boolean doNotConvert(Object obj, RType type) {
439452
return !RRuntime.isForeignObject(obj) || (!isForeignArray(obj) && type != RType.List);
440453
}
@@ -471,4 +484,20 @@ private Foreign2R getForeign2RNode() {
471484
return foreign2RNode;
472485
}
473486

487+
private ForeignArrayToListNode getArrayToListNode() {
488+
if (arrayToList == null) {
489+
CompilerDirectives.transferToInterpreterAndInvalidate();
490+
arrayToList = insert(ForeignArrayToListNodeGen.create());
491+
}
492+
return arrayToList;
493+
}
494+
495+
private ForeignArrayToVectorNode getArrayToVectorNode() {
496+
if (arrayToVector == null) {
497+
CompilerDirectives.transferToInterpreterAndInvalidate();
498+
arrayToVector = insert(ForeignArrayToVectorNodeGen.create());
499+
}
500+
return arrayToVector;
501+
}
502+
474503
}

0 commit comments

Comments
 (0)