From 8fd909722530955a5e31d5ea97f3cd22df5fec35 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Tue, 16 May 2017 16:56:43 +0200
Subject: [PATCH] fastr interop - some basic builtins to create/convert java
 arrays

---
 .../r/nodes/builtin/base/BasePackage.java     |   4 +
 .../r/nodes/builtin/fastr/FastRInterop.java   |  26 +--
 .../r/runtime/data/RInteropScalar.java        |  26 +++
 .../r/test/library/fastr/TestJavaInterop.java | 160 ++++++++++++++++--
 4 files changed, 189 insertions(+), 27 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 3fda7060a4..eb9ccf0a2d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -375,6 +375,10 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRInterop.IsNull.class, FastRInteropFactory.IsNullNodeGen::create);
         add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create);
         add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
+        add(FastRInterop.IsJavaArray.class, FastRInteropFactory.IsJavaArrayNodeGen::create);
+        add(FastRInterop.NewJavaArray.class, FastRInteropFactory.NewJavaArrayNodeGen::create);
+        add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create);
+        add(FastRInterop.FromJavaArray.class, FastRInteropFactory.FromJavaArrayNodeGen::create);
         add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create);
         add(FastRInterop.ToByte.class, FastRInteropFactory.ToByteNodeGen::create);
         add(FastRInterop.ToChar.class, FastRInteropFactory.ToCharNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index fee1e92a29..0857f0b531 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -44,6 +44,7 @@ import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.ArityException;
 import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
@@ -63,10 +64,8 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
-import static com.oracle.truffle.r.runtime.RType.Array;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -87,6 +86,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import java.lang.reflect.Array;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -108,7 +108,7 @@ public class FastRInterop {
             try {
                 return RContext.getInstance().getEnv().parse(sourceObject);
             } catch (Throwable t) {
-                throw error(Message.GENERIC, "Error while parsing: " + t.getMessage());
+                throw error(RError.Message.GENERIC, "Error while parsing: " + t.getMessage());
             }
         }
 
@@ -153,9 +153,9 @@ public class FastRInterop {
                 Source sourceObject = sourceBuilder.build();
                 return RContext.getInstance().getEnv().parse(sourceObject);
             } catch (IOException e) {
-                throw error(Message.GENERIC, "Error reading file: " + e.getMessage());
+                throw error(RError.Message.GENERIC, "Error reading file: " + e.getMessage());
             } catch (Throwable t) {
-                throw error(Message.GENERIC, "Error while parsing: " + t.getMessage());
+                throw error(RError.Message.GENERIC, "Error while parsing: " + t.getMessage());
             }
         }
 
@@ -194,13 +194,13 @@ public class FastRInterop {
         @Specialization
         @TruffleBoundary
         protected Object exportSymbol(@SuppressWarnings("unused") String name, @SuppressWarnings("unused") RMissing value) {
-            throw error(Message.ARGUMENT_MISSING, "value");
+            throw error(RError.Message.ARGUMENT_MISSING, "value");
         }
 
         @Fallback
         @TruffleBoundary
         protected Object exportSymbol(@SuppressWarnings("unused") Object name, @SuppressWarnings("unused") Object value) {
-            throw error(Message.GENERIC, "only R language objects can be exported");
+            throw error(RError.Message.GENERIC, "only R language objects can be exported");
         }
     }
 
@@ -226,7 +226,7 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.hasSize", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class HasSize extends RBuiltinNode.Arg1 {
 
-        @Child private Node node = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode();
+        @Child private Node node = Message.HAS_SIZE.createNode();
 
         static {
             Casts.noCasts(HasSize.class);
@@ -241,7 +241,7 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.isNull", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class IsNull extends RBuiltinNode.Arg1 {
 
-        @Child private Node node = com.oracle.truffle.api.interop.Message.IS_NULL.createNode();
+        @Child private Node node = Message.IS_NULL.createNode();
 
         static {
             Casts.noCasts(IsNull.class);
@@ -256,7 +256,7 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.isExecutable", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class IsExecutable extends RBuiltinNode.Arg1 {
 
-        @Child private Node node = com.oracle.truffle.api.interop.Message.IS_EXECUTABLE.createNode();
+        @Child private Node node = Message.IS_EXECUTABLE.createNode();
 
         static {
             Casts.noCasts(IsExecutable.class);
@@ -434,7 +434,7 @@ public class FastRInterop {
             try {
                 return JavaInterop.asTruffleObject(Class.forName(clazz));
             } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) {
-                throw error(Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
             }
         }
     }
@@ -797,13 +797,13 @@ public class FastRInterop {
                 Object result = ForeignAccess.sendNew(sendNew, clazz, argValues);
                 return RRuntime.java2R(result);
             } catch (SecurityException | IllegalArgumentException | UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
-                throw error(Message.GENERIC, "error during Java object instantiation: " + e.getMessage());
+                throw error(RError.Message.GENERIC, "error during Java object instantiation: " + e.getMessage());
             }
         }
 
         @Fallback
         public Object interopNew(@SuppressWarnings("unused") Object clazz, @SuppressWarnings("unused") Object args) {
-            throw error(Message.GENERIC, "interop object needed as receiver of NEW message");
+            throw error(RError.Message.GENERIC, "interop object needed as receiver of NEW message");
         }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
index e2f4a3bc4f..ff5c016239 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
@@ -31,6 +31,8 @@ public abstract class RInteropScalar extends RScalar {
 
     public abstract Object getRValue();
 
+    public abstract Class<?> getJavaType();
+
     @ValueType
     public static final class RInteropByte extends RInteropScalar {
 
@@ -63,6 +65,11 @@ public abstract class RInteropScalar extends RScalar {
             CompilerAsserts.neverPartOfCompilation();
             return Byte.toString(value);
         }
+
+        @Override
+        public Class<?> getJavaType() {
+            return Byte.TYPE;
+        }
     }
 
     @ValueType
@@ -97,6 +104,11 @@ public abstract class RInteropScalar extends RScalar {
             CompilerAsserts.neverPartOfCompilation();
             return Character.toString(value);
         }
+
+        @Override
+        public Class<?> getJavaType() {
+            return Character.TYPE;
+        }
     }
 
     @ValueType
@@ -131,6 +143,11 @@ public abstract class RInteropScalar extends RScalar {
             CompilerAsserts.neverPartOfCompilation();
             return Float.toString(value);
         }
+
+        @Override
+        public Class<?> getJavaType() {
+            return Float.TYPE;
+        }
     }
 
     @ValueType
@@ -165,6 +182,11 @@ public abstract class RInteropScalar extends RScalar {
             CompilerAsserts.neverPartOfCompilation();
             return Long.toString(value);
         }
+
+        @Override
+        public Class<?> getJavaType() {
+            return Long.TYPE;
+        }
     }
 
     @ValueType
@@ -200,5 +222,9 @@ public abstract class RInteropScalar extends RScalar {
             return Short.toString(value);
         }
 
+        @Override
+        public Class<?> getJavaType() {
+            return Short.TYPE;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index 2a7bbe8986..05eda5ef59 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -112,6 +112,81 @@ public class TestJavaInterop extends TestBase {
         assertEvalFastR("v <- .fastr.interop.toChar('a'); v;", "'a'");
     }
 
+    @Test
+    public void testToArray() {
+        assertEvalFastR("a <- .fastr.java.toArray(1L); a;", getRValue(new int[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1L, 2L)); a;", getRValue(new int[]{1, 2}));
+        assertEvalFastR("a <- .fastr.java.toArray(1L,,T); a;", getRValue(new int[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1L, 2L),,T); a;", getRValue(new int[]{1, 2}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(1.1); a;", getRValue(new double[]{1.1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1.1, 1.2)); a;", getRValue(new double[]{1.1, 1.2}));
+        assertEvalFastR("a <- .fastr.java.toArray(1.1,,T); a;", getRValue(new double[]{1.1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1.1, 1.2),,T); a;", getRValue(new double[]{1.1, 1.2}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(T); a;", getRValue(new boolean[]{true}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(T, F)); a;", getRValue(new boolean[]{true, false}));
+        assertEvalFastR("a <- .fastr.java.toArray(T,,T); a;", getRValue(new boolean[]{true}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(T, F),,T); a;", getRValue(new boolean[]{true, false}));
+
+        assertEvalFastR("a <- .fastr.java.toArray('a'); a;", getRValue(new String[]{"a"}));
+        assertEvalFastR("a <- .fastr.java.toArray(c('a', 'b')); a;", getRValue(new String[]{"a", "b"}));
+        assertEvalFastR("a <- .fastr.java.toArray('a',,T); a;", getRValue(new String[]{"a"}));
+        assertEvalFastR("a <- .fastr.java.toArray(c('a', 'b'),,T); a;", getRValue(new String[]{"a", "b"}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a;", getRValue(new short[]{1, 2}));
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a;", getRValue(new short[]{1, 2}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a;", getRValue(new short[]{1, 2}));
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a;", getRValue(new short[]{1, 2}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a;", getRValue(new int[]{1, 2}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a;", getRValue(new double[]{1.123, 2.123}));
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a;", getRValue(new double[]{1}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(1L); .fastr.java.toArray(a);", getRValue(new int[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T);", getRValue(new int[]{1}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a);", getRValue(new short[]{1}));
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(to); .fastr.java.isArray(a)", "TRUE");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(c(to, to)); .fastr.java.isArray(a)", "TRUE");
+        
+        assertEvalFastR(Ignored.Unimplemented, "a <- .fastr.java.toArray(1L,,F); a;", getRValue(new int[]{1}));
+    }
+
+    @Test
+    public void testFromArray() {
+        testFromArray("fieldStaticBooleanArray", "logical");
+        testFromArray("fieldStaticByteArray", "integer");
+        testFromArray("fieldStaticCharArray", "character");
+        testFromArray("fieldStaticDoubleArray", "double");
+        testFromArray("fieldStaticFloatArray", "double");
+        testFromArray("fieldStaticIntArray", "integer");
+        testFromArray("fieldStaticLongArray", "double");
+        testFromArray("fieldStaticShortArray", "integer");
+        testFromArray("fieldStaticStringArray", "character");
+
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$objectArray); is.list(v)", "TRUE");
+        testFromArray("objectIntArray", "integer");
+        testFromArray("objectDoubleArray", "double");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$mixedTypesArray); is.list(v)", "TRUE");
+
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); is.list(v)", "TRUE");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[1]", "list(1)");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[2]", "list(NULL)");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[3]", "list(3)");
+    }
+
+    public void testFromArray(String field, String type) {
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$" + field + "); is.vector(v)", "TRUE");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$" + field + "); typeof(v)", getRValue(type));
+    }
+
     @Test
     public void testNew() {
         assertEvalFastR("tc <- .fastr.java.class('" + Boolean.class.getName() + "'); t <- .fastr.interop.new(tc, TRUE); t", "TRUE");
@@ -127,7 +202,7 @@ public class TestJavaInterop extends TestBase {
     }
 
     @Test
-    public void testCombine() {
+    public void testCombineInteropTypes() {
         assertEvalFastR("class(c(.fastr.interop.toByte(123)))", "'interopt.byte'");
         assertEvalFastR("class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234)))", "'list'");
         assertEvalFastR("class(c(.fastr.interop.toByte(123), 1))", "'list'");
@@ -177,7 +252,13 @@ public class TestJavaInterop extends TestBase {
 
     @Test
     public void testNonPrimitiveParameter() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", getRValue(true));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", "TRUE");
+    }
+    
+    @Test
+    public void testClassAsParameter() {
+        // needs to be implemented in truffle
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
     }
 
     private void getValueForAllTypesMethod(String method) {
@@ -190,7 +271,7 @@ public class TestJavaInterop extends TestBase {
         double d = Double.MAX_VALUE;
         float f = Float.MAX_VALUE;
         String s = "testString";
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + method + "(" + getRValue(bo, bt, c, sh, i, l, d, f, s) + ")",
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + method + "(" + getRValuesAsString(bo, bt, c, sh, i, l, d, f, s) + ")",
                         getRValue("" + bo + bt + c + sh + i + l + d + f + s));
     }
 
@@ -207,6 +288,21 @@ public class TestJavaInterop extends TestBase {
         // TODO add remaining isOverloaded(...) calls once this is fixed
     }
 
+    @Test
+    public void testArrayAccess() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1]]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1,2]", "2");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1,2]]", "2");
+
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]<-123; a[1]", "123");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]<-123; a[[1]]", "123");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1,2]<-1234; a[1,2]", "1234");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1,2]]<-1234; a[[1,2]]", "1234");
+    }
+
     private String getRValue(Object value) {
         if (value == null) {
             return "NULL";
@@ -214,6 +310,14 @@ public class TestJavaInterop extends TestBase {
         if (value instanceof Boolean) {
             return value.toString().toUpperCase();
         }
+        if (value instanceof Double) {
+            if (((Double) value) == (((Double) value).intValue())) {
+                return Integer.toString(((Double) value).intValue());
+            }
+        }
+        if (value instanceof String) {
+            return "\"" + value.toString() + "\"";
+        }
         if (value instanceof String) {
             return "\"" + value.toString() + "\"";
         }
@@ -222,22 +326,25 @@ public class TestJavaInterop extends TestBase {
         }
         if (value.getClass().isArray()) {
             StringBuilder sb = new StringBuilder();
-            int l = Array.getLength(value);
             sb.append("cat('[1] ");
-            for (int i = 0; i < l; i++) {
+            int lenght = Array.getLength(value);
+            for (int i = 0; i < lenght; i++) {
+                if (lenght > 1 && value.getClass().getComponentType() == Boolean.TYPE && (boolean) Array.get(value, i)) {
+                    // what the heck?
+                    sb.append(" ");
+                }
                 sb.append(getRValue(Array.get(value, i)));
-                if (i < l - 1) {
+                if (i < lenght - 1) {
                     sb.append(" ");
                 }
             }
             sb.append("\\nattr(,\"is.truffle.object\")\\n[1] TRUE\\n')");
             return sb.toString();
         }
-
         return value.toString();
     }
 
-    private String getRValue(Object... values) {
+    private String getRValuesAsString(Object... values) {
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < values.length; i++) {
             Object v = values[i];
@@ -298,12 +405,33 @@ public class TestJavaInterop extends TestBase {
         public static Double fieldStaticNaNObject = Double.NaN;
         public static double fieldStaticNaN = Double.NaN;
 
+        public static boolean[] fieldStaticBooleanArray = new boolean[]{true, false, true};
+        public static byte[] fieldStaticByteArray = new byte[]{1, 2, 3};
+        public static char[] fieldStaticCharArray = new char[]{'a', 'b', 'c'};
+        public static double[] fieldStaticDoubleArray = new double[]{1.1, 2.1, 3.1};
+        public static float[] fieldStaticFloatArray = new float[]{1.1f, 2.1f, 3.1f};
         public static int[] fieldStaticIntArray = new int[]{1, 2, 3};
+        public static long[] fieldStaticLongArray = new long[]{1, 2, 3};
+        public static short[] fieldStaticShortArray = new short[]{1, 2, 3};
         public static String[] fieldStaticStringArray = new String[]{"a", "b", "c"};
 
+        public boolean[] fieldBooleanArray = fieldStaticBooleanArray;
+        public byte[] fieldByteArray = fieldStaticByteArray;
+        public char[] fieldCharArray = fieldStaticCharArray;
+        public double[] fieldDoubleArray = fieldStaticDoubleArray;
+        public float[] fieldFloatArray = fieldStaticFloatArray;
         public int[] fieldIntArray = fieldStaticIntArray;
+        public long[] fieldLongArray = fieldStaticLongArray;
+        public short[] fieldShortArray = fieldStaticShortArray;
         public String[] fieldStringArray = fieldStaticStringArray;
 
+        public int[][] int2DimArray = new int[][]{new int[]{1, 2, 3}, new int[]{4, 5, 5}};
+        public Object[] objectArray = new Object[]{new Object(), new Object(), new Object()};
+        public Object[] objectIntArray = new Object[]{1, 2, 3};
+        public Object[] objectDoubleArray = new Object[]{1.1, 2.1, 3.1};
+        public Object[] mixedTypesArray = new Object[]{1, 2.1, 'a'};
+        public Integer[] hasNullIntArray = new Integer[]{1, null, 3};
+
         public static Object fieldStaticNullObject = null;
         public Object fieldNullObject = null;
 
@@ -322,9 +450,6 @@ public class TestJavaInterop extends TestBase {
             fieldStaticShort = sh;
             fieldStaticStringObject = st;
 
-            // fieldStaticIntArray = ia;
-            // fieldStaticStringArray = sta;
-
             fieldStaticBooleanObject = fieldStaticBoolean;
             fieldStaticByteObject = fieldStaticByte;
             fieldStaticCharObject = fieldStaticChar;
@@ -352,9 +477,6 @@ public class TestJavaInterop extends TestBase {
             this.fieldDoubleObject = fieldDouble;
             this.fieldFloatObject = fieldFloat;
             this.fieldStringObject = fieldStaticStringObject;
-
-            this.fieldIntArray = fieldStaticIntArray;
-            this.fieldStringArray = fieldStaticStringArray;
         }
 
         public static boolean methodStaticBoolean() {
@@ -517,6 +639,10 @@ public class TestJavaInterop extends TestBase {
             return null;
         }
 
+        public String classAsArg(Class<?> c) {
+            return c.getName();
+        }
+
         public String allTypesMethod(boolean bo, byte bt, char ch, short sh, int in, long lo, double db, float fl, String st) {
             return "" + bo + bt + ch + sh + in + lo + db + fl + st;
         }
@@ -605,4 +731,10 @@ public class TestJavaInterop extends TestBase {
             return String.class.getName();
         }
     }
+
+    public static class TestArrayClass {
+        public static TestArrayClass[] testArray = new TestArrayClass[]{new TestArrayClass(), new TestArrayClass(), new TestArrayClass()};
+
+    }
+
 }
-- 
GitLab