4747import com .oracle .truffle .r .runtime .data .RForeignDoubleWrapper ;
4848import com .oracle .truffle .r .runtime .data .RForeignIntWrapper ;
4949import com .oracle .truffle .r .runtime .data .RForeignStringWrapper ;
50+ import com .oracle .truffle .r .runtime .data .RForeignWrapper ;
5051import com .oracle .truffle .r .runtime .data .RNull ;
5152import com .oracle .truffle .r .runtime .data .RStringVector ;
5253import com .oracle .truffle .r .runtime .data .RVector ;
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 })
8286public 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