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 241fd56c01eca4051308d409096072619f128d9f..3fda7060a46f2c63769011664af3e5a4dc325c42 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
@@ -376,6 +376,11 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create);
         add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
         add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create);
+        add(FastRInterop.ToByte.class, FastRInteropFactory.ToByteNodeGen::create);
+        add(FastRInterop.ToChar.class, FastRInteropFactory.ToCharNodeGen::create);
+        add(FastRInterop.ToFloat.class, FastRInteropFactory.ToFloatNodeGen::create);
+        add(FastRInterop.ToLong.class, FastRInteropFactory.ToLongNodeGen::create);
+        add(FastRInterop.ToShort.class, FastRInteropFactory.ToShortNodeGen::create);
         add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::create);
         add(FastRPkgSource.class, FastRPkgSourceNodeGen::create);
         add(FastRStackTrace.class, FastRStackTraceNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
index 4104af4f437e3f09f890c93b2cee38ebf921876f..0bd88751d6643cdb10f595f18ad40e3a5b98507f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -75,7 +76,7 @@ final class ValuePrinters implements ValuePrinter<Object> {
         if (v == RNull.instance) {
             NullPrinter.INSTANCE.print(null, printCtx);
         } else {
-            // handle types that can appear via Truffle interop
+            // handle types that are meant for or can appear via Truffle interop
             Object x = v;
             if (x instanceof Boolean) {
                 x = RRuntime.asLogical((Boolean) x);
@@ -83,6 +84,8 @@ final class ValuePrinters implements ValuePrinter<Object> {
                 x = ((Number) x).doubleValue();
             } else if (x instanceof Character) {
                 x = ((Character) x).toString();
+            } else if (x instanceof RInteropScalar) {
+                x = ((RInteropScalar) x).getRValue();
             }
             // try to box a scalar primitive value to the respective vector
             x = printCtx.printerNode().boxPrimitive(x);
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 912beabdbf0da3918da1bdfbe295e03b7822cea5..fee1e92a2995cce386ff1356904eae268dafcb62 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
@@ -45,30 +45,50 @@ 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.TruffleObject;
+import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.interop.UnsupportedTypeException;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.Source.Builder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
+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;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort;
+import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+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.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 public class FastRInterop {
 
@@ -165,7 +185,7 @@ public class FastRInterop {
         @TruffleBoundary
         protected Object exportSymbol(String name, RTypedValue value) {
             if (name == null) {
-                throw error(RError.Message.INVALID_ARG_TYPE, "name");
+                throw error(RError.Message.INVALID_ARGUMENT, "name");
             }
             RContext.getInstance().getExportedSymbols().put(name, value);
             return RNull.instance;
@@ -228,7 +248,7 @@ public class FastRInterop {
         }
 
         @Specialization
-        public byte hasSize(TruffleObject obj) {
+        public byte isNull(TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendIsNull(node, obj));
         }
     }
@@ -243,11 +263,149 @@ public class FastRInterop {
         }
 
         @Specialization
-        public byte hasSize(TruffleObject obj) {
+        public byte isExecutable(TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendIsExecutable(node, obj));
         }
     }
 
+    @RBuiltin(name = ".fastr.interop.toByte", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    public abstract static class ToByte extends RBuiltinNode.Arg1 {
+
+        static {
+            castToJavaNumberType(new Casts(ToByte.class));
+        }
+
+        @Specialization
+        public RInteropByte toByte(int value) {
+            return RInteropByte.valueOf((byte) value);
+        }
+
+        @Specialization
+        public RInteropByte toByte(double value) {
+            return RInteropByte.valueOf((byte) value);
+        }
+
+        @Specialization
+        public RInteropByte toByte(RRaw value) {
+            return RInteropByte.valueOf(value.getValue());
+        }
+    }
+
+    @RBuiltin(name = ".fastr.interop.toChar", visibility = ON, kind = PRIMITIVE, parameterNames = {"value", "pos"}, behavior = COMPLEX)
+    public abstract static class ToChar extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts casts = new Casts(ToChar.class);
+            casts.arg("value").mustBe(integerValue().or(doubleValue().or(stringValue())), RError.Message.INVALID_ARGUMENT_OF_TYPE, "value", Predef.typeName()).asVector().mustBe(
+                            singleElement()).findFirst();
+            casts.arg("pos").allowMissing().mustBe(numericValue(), RError.Message.INVALID_ARGUMENT_OF_TYPE, "pos", Predef.typeName()).asIntegerVector().mustBe(singleElement()).findFirst();
+        }
+
+        @Specialization
+        public RInteropChar toChar(int value, @SuppressWarnings("unused") RMissing unused) {
+            return RInteropChar.valueOf((char) value);
+        }
+
+        @Specialization
+        public RInteropChar toChar(double value, @SuppressWarnings("unused") RMissing unused) {
+            return RInteropChar.valueOf((char) value);
+        }
+
+        @Specialization
+        public RInteropChar toChar(String value, @SuppressWarnings("unused") RMissing unused) {
+            return toChar(value, 0);
+        }
+
+        @Specialization
+        public RInteropChar toChar(int value, int pos) {
+            throw RError.error(this, RError.Message.POS_NOT_ALLOWED_WITH_NUMERIC);
+        }
+
+        @Specialization
+        public RInteropChar toChar(double value, int pos) {
+            throw RError.error(this, RError.Message.POS_NOT_ALLOWED_WITH_NUMERIC);
+        }
+
+        @Specialization
+        public RInteropChar toChar(String value, int pos) {
+            return RInteropChar.valueOf(value.charAt(pos));
+        }
+    }
+
+    @RBuiltin(name = ".fastr.interop.toFloat", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    public abstract static class ToFloat extends RBuiltinNode.Arg1 {
+
+        static {
+            castToJavaNumberType(new Casts(ToFloat.class));
+        }
+
+        @Specialization
+        public RInteropFloat toFloat(int value) {
+            return RInteropFloat.valueOf((float) value);
+        }
+
+        @Specialization
+        public RInteropFloat toFloat(double value) {
+            return RInteropFloat.valueOf((float) value);
+        }
+
+        @Specialization
+        public RInteropFloat toFloat(RRaw value) {
+            return RInteropFloat.valueOf(value.getValue());
+        }
+    }
+
+    @RBuiltin(name = ".fastr.interop.toLong", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    public abstract static class ToLong extends RBuiltinNode.Arg1 {
+
+        static {
+            castToJavaNumberType(new Casts(ToLong.class));
+        }
+
+        @Specialization
+        public RInteropLong toLong(int value) {
+            return RInteropLong.valueOf((long) value);
+        }
+
+        @Specialization
+        public RInteropLong toLong(double value) {
+            return RInteropLong.valueOf((long) value);
+        }
+
+        @Specialization
+        public RInteropLong toLong(RRaw value) {
+            return RInteropLong.valueOf(value.getValue());
+        }
+    }
+
+    @RBuiltin(name = ".fastr.interop.toShort", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    public abstract static class ToShort extends RBuiltinNode.Arg1 {
+
+        static {
+            castToJavaNumberType(new Casts(ToShort.class));
+        }
+
+        @Specialization
+        public RInteropShort toShort(double value) {
+            return RInteropShort.valueOf((short) value);
+        }
+
+        @Specialization
+        public RInteropShort toShort(int value) {
+            return RInteropShort.valueOf((short) value);
+        }
+
+        @Specialization
+        public RInteropShort toShort(RRaw value) {
+            return RInteropShort.valueOf(value.getValue());
+        }
+
+    }
+
+    private static void castToJavaNumberType(Casts casts) {
+        casts.arg("value").mustBe(integerValue().or(doubleValue().or(rawValue())), RError.Message.INVALID_ARGUMENT_OF_TYPE, "value", Predef.typeName()).asVector().mustBe(singleElement()).findFirst();
+    }
+
     @RBuiltin(name = ".fastr.interop.toBoolean", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class ToBoolean extends RBuiltinNode.Arg1 {
 
@@ -281,32 +439,349 @@ public class FastRInterop {
         }
     }
 
-    @ImportStatic({com.oracle.truffle.api.interop.Message.class, RRuntime.class})
-    @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
-    public abstract static class InteropNew extends RBuiltinNode.Arg2 {
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.java.isArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
+    public abstract static class IsJavaArray extends RBuiltinNode.Arg1 {
 
         static {
-            Casts.noCasts(InteropNew.class);
+            Casts.noCasts(IsJavaArray.class);
+        }
+
+        private final ConditionProfile isJavaProfile = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile();
+
+        @Specialization(guards = {"isForeignObject(obj)"})
+        @TruffleBoundary
+        public Object isArray(TruffleObject obj) {
+            // TODO does this return true only for java arrays, or also
+            // js arrays?
+            boolean result = isJavaProfile.profile(JavaInterop.isJavaObject(Object.class, obj)) && isArrayProfile.profile(JavaInterop.isArray(obj));
+            return RRuntime.java2R(result);
+        }
+
+        @Fallback
+        public Object isArray(Object obj) {
+            return RRuntime.java2R(false);
+        }
+    }
+
+    @RBuiltin(name = ".fastr.java.newArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "dim"}, behavior = COMPLEX)
+    public abstract static class NewJavaArray extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts casts = new Casts(NewJavaArray.class);
+            casts.arg("class").mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst();
+            casts.arg("dim").mustBe(integerValue(), RError.Message.INVALID_ARGUMENT_OF_TYPE, "dim", typeName()).asIntegerVector();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object newArray(String clazz, int length) {
+            try {
+                // TODO new via ForeignAccess
+                return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), length));
+            } catch (ClassNotFoundException e) {
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
         }
 
-        private static Object toJava(Object value) {
-            Object vector = RRuntime.asAbstractVector(value);
-            if (vector instanceof RAbstractAtomicVector && ((RAbstractAtomicVector) vector).getLength() == 1) {
-                if (vector instanceof RAbstractDoubleVector) {
-                    RAbstractDoubleVector v = (RAbstractDoubleVector) vector;
-                    return v.getDataAt(0);
-                } else if (vector instanceof RAbstractLogicalVector) {
-                    RAbstractLogicalVector v = (RAbstractLogicalVector) vector;
-                    return v.getDataAt(0) == RRuntime.LOGICAL_TRUE;
-                } else if (vector instanceof RAbstractRawVector) {
-                    RAbstractRawVector v = (RAbstractRawVector) vector;
-                    return v.getDataAt(0).getValue();
-                } else if (vector instanceof RAbstractStringVector) {
-                    RAbstractStringVector v = (RAbstractStringVector) vector;
-                    return v.getDataAt(0);
+        @Specialization
+        @TruffleBoundary
+        public Object newArray(String clazz, RAbstractIntVector dim) {
+            try {
+                int[] dima = new int[dim.getLength()];
+                // TODO new via ForeignAccess
+                return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), dima));
+            } catch (ClassNotFoundException e) {
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.java.toArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"x", "className", "flat"}, behavior = COMPLEX)
+    public abstract static class ToJavaArray extends RBuiltinNode.Arg3 {
+
+        static {
+            Casts casts = new Casts(ToJavaArray.class);
+            casts.arg("x").mustNotBeMissing();
+            casts.arg("className").allowMissing().mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst();
+            casts.arg("flat").mapMissing(Predef.constant(RRuntime.asLogical(true))).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(
+                            notLogicalNA()).map(Predef.toBoolean());
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractLogicalVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, boolean.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractLogicalVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractIntVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, int.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractIntVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractDoubleVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, double.class, (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractDoubleVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractStringVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, String.class, (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractStringVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, Object.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAtAsObject(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAtAsObject(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RInteropScalar ri, String className, boolean flat) {
+            RList list = RDataFactory.createList(new Object[]{ri});
+            return toArray(list, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(list.getDataAt(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RInteropScalar ri, RMissing className, boolean flat) {
+            RList list = RDataFactory.createList(new Object[]{ri});
+            return toArray(list, flat, ri.getJavaType(), (array, i) -> Array.set(array, i, RRuntime.r2Java(list.getDataAt(i))));
+        }
+
+        private Class<?> getClazz(String className) throws RError {
+            if (className.equals(Byte.TYPE.getName())) {
+                return Byte.TYPE;
+            }
+            if (className.equals(Boolean.TYPE.getName())) {
+                return Boolean.TYPE;
+            }
+            if (className.equals(Character.TYPE.getName())) {
+                return Character.TYPE;
+            }
+            if (className.equals(Double.TYPE.getName())) {
+                return Double.TYPE;
+            }
+            if (className.equals(Float.TYPE.getName())) {
+                return Float.TYPE;
+            }
+            if (className.equals(Integer.TYPE.getName())) {
+                return Integer.TYPE;
+            }
+            if (className.equals(Long.TYPE.getName())) {
+                return Long.TYPE;
+            }
+            if (className.equals(Short.TYPE.getName())) {
+                return Short.TYPE;
+            }
+            try {
+                return Class.forName(className);
+            } catch (ClassNotFoundException e) {
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
+        }
+
+        private int[] getDim(boolean flat, RAbstractVector vec) {
+            int[] dims;
+            if (flat) {
+                dims = new int[]{vec.getLength()};
+            } else {
+                dims = vec.getDimensions();
+                if (dims == null) {
+                    dims = new int[]{vec.getLength()};
                 }
             }
-            return value;
+            return dims;
+        }
+
+        private Object toArray(RAbstractVector vec, boolean flat, Class<?> clazz, VecElementToArray vecToArray) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+            int[] dims = getDim(flat, vec);
+            final Object array = Array.newInstance(clazz, dims);
+            for (int d = 0; d < dims.length; d++) {
+                int dim = dims[d];
+                // TODO works only for flat
+                for (int i = 0; i < dim; i++) {
+                    vecToArray.toArray(array, i);
+                }
+            }
+            return JavaInterop.asTruffleObject(array);
+        }
+
+        private interface VecElementToArray {
+            void toArray(Object array, Integer i);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(TruffleObject obj, @SuppressWarnings("unused") RMissing missing, @SuppressWarnings("unused") boolean flat,
+                        @Cached("WRITE.createNode()") Node write) {
+            if (JavaInterop.isJavaObject(Object.class, obj)) {
+                if (JavaInterop.isArray(obj)) {
+                    // TODO should return copy?
+                    return obj;
+                }
+                try {
+                    // TODO should create array with the same component type as the JavaObject
+                    TruffleObject array = JavaInterop.asTruffleObject(Array.newInstance(Object.class, 1));
+                    ForeignAccess.sendWrite(write, array, 0, obj);
+                    return array;
+                } catch (UnsupportedMessageException | UnknownIdentifierException e) {
+                    throw error(RError.Message.GENERIC, "error while creating array: " + e.getMessage());
+                } catch (UnsupportedTypeException ex) {
+                    Logger.getLogger(FastRInterop.class.getName()).log(Level.SEVERE, null, ex);
+                }
+            }
+            throw error(RError.Message.GENERIC, "can't create array from " + obj);
+        }
+
+        @Fallback
+        public Object toArray(Object o, @SuppressWarnings("unused") Object className, @SuppressWarnings("unused") Object flat) {
+            throw error(RError.Message.GENERIC, "unsupported type");
+        }
+
+    }
+
+    @RBuiltin(name = ".fastr.java.fromArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"array"}, behavior = COMPLEX)
+    public abstract static class FromJavaArray extends RBuiltinNode.Arg1 {
+        @Child Node getSize = Message.GET_SIZE.createNode();
+        @Child Node read;
+        @Child Node isNull;
+        @Child Node isBoxed;
+        @Child Node unbox;
+        static {
+            Casts casts = new Casts(FromJavaArray.class);
+            casts.arg("array").mustNotBeMissing();
+        }
+
+        protected boolean isJavaArray(TruffleObject obj) {
+            return JavaInterop.isJavaObject(Object.class, obj) && JavaInterop.isArray(obj);
+        }
+
+        @Specialization(guards = {"isJavaArray(obj)"})
+        @TruffleBoundary
+        public Object fromArray(TruffleObject obj) {
+            int size;
+            try {
+                size = (int) ForeignAccess.sendGetSize(getSize, obj);
+                if (size == 0) {
+                    return RDataFactory.createList();
+                }
+                Object[] elements = new Object[size];
+                boolean allBoolean = true;
+                boolean allInteger = true;
+                boolean allDouble = true;
+                boolean allString = true;
+                for (int i = 0; i < size; i++) {
+                    if (read == null) {
+                        read = insert(Message.READ.createNode());
+                    }
+                    Object element = ForeignAccess.sendRead(read, obj, i);
+                    if (element instanceof TruffleObject) {
+                        if (isNull == null) {
+                            isNull = insert(Message.IS_NULL.createNode());
+                        }
+                        if (ForeignAccess.sendIsNull(isNull, (TruffleObject) element)) {
+                            element = null;
+                        } else {
+                            if (isBoxed == null) {
+                                isBoxed = insert(Message.IS_BOXED.createNode());
+                            }
+                            if (ForeignAccess.sendIsBoxed(isBoxed, (TruffleObject) element)) {
+                                if (unbox == null) {
+                                    unbox = insert(Message.UNBOX.createNode());
+                                }
+                                element = ForeignAccess.sendIsBoxed(unbox, (TruffleObject) element);
+                            }
+                        }
+                    }
+                    allBoolean &= element instanceof Boolean;
+                    allInteger &= element instanceof Byte || element instanceof Integer || element instanceof Short;
+                    allDouble &= element instanceof Double || element instanceof Float || element instanceof Long;
+                    allString &= element instanceof Character || element instanceof String;
+
+                    elements[i] = RRuntime.java2R(element);
+                }
+                if (allBoolean) {
+                    byte[] ret = new byte[size];
+                    for (int i = 0; i < size; i++) {
+                        ret[i] = ((Number) elements[i]).byteValue();
+                    }
+                    return RDataFactory.createLogicalVector(ret, true);
+                }
+                if (allInteger) {
+                    int[] ret = new int[size];
+                    for (int i = 0; i < size; i++) {
+                        ret[i] = ((Number) elements[i]).intValue();
+                    }
+                    return RDataFactory.createIntVector(ret, true);
+                }
+                if (allDouble) {
+                    double[] ret = new double[size];
+                    for (int i = 0; i < size; i++) {
+                        ret[i] = ((Number) elements[i]).doubleValue();
+                    }
+                    return RDataFactory.createDoubleVector(ret, true);
+                }
+                if (allString) {
+                    String[] ret = new String[size];
+                    for (int i = 0; i < size; i++) {
+                        ret[i] = String.valueOf(elements[i]);
+                    }
+                    return RDataFactory.createStringVector(ret, true);
+                }
+                return RDataFactory.createList(elements);
+            } catch (UnsupportedMessageException | UnknownIdentifierException e) {
+                throw error(RError.Message.GENERIC, "error while converting array: " + e.getMessage());
+            }
+        }
+
+        @Fallback
+        public Object fromArray(@SuppressWarnings("unused") Object obj) {
+            throw error(RError.Message.GENERIC, "not a java array");
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
+    public abstract static class InteropNew extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts.noCasts(InteropNew.class);
         }
 
         @Specialization(limit = "99", guards = {"isForeignObject(clazz)", "length == args.getLength()"})
@@ -317,9 +792,10 @@ public class FastRInterop {
             try {
                 Object[] argValues = new Object[args.getLength()];
                 for (int i = 0; i < argValues.length; i++) {
-                    argValues[i] = toJava(args.getArgument(i));
+                    argValues[i] = RRuntime.r2Java(args.getArgument(i));
                 }
-                return ForeignAccess.sendNew(sendNew, clazz, argValues);
+                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());
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index 89b03586643b655e1b503474f80492140cb5b475..c3de2199322aa65b8a7d6d0c9beb35aafcc30503 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -23,14 +23,20 @@
 package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.KeyInfo;
 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;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
@@ -41,6 +47,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -48,6 +55,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
+@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
 public abstract class ExtractVectorNode extends Node {
 
     protected static final int CACHE_LIMIT = 5;
@@ -88,51 +96,89 @@ public abstract class ExtractVectorNode extends Node {
 
     protected abstract Object execute(VirtualFrame frame, Object vector, Object[] positions, Object exact, Object dropDimensions);
 
-    protected Node createForeignRead(Object[] positions) {
-        if (positions.length != 1) {
-            throw RError.error(this, RError.Message.GENERIC, "Invalid number positions for foreign access.");
-        }
-        return Message.READ.createNode();
-    }
-
     protected static boolean isForeignObject(TruffleObject object) {
         return RRuntime.isForeignObject(object);
     }
 
     protected static FirstStringNode createFirstString() {
-        return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot corce position to character for foreign access.");
+        return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot coerce position to character for foreign access.");
     }
 
     @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"})
     protected Object accessField(TruffleObject object, Object[] positions, @SuppressWarnings("unused") Object exact, @SuppressWarnings("unused") Object dropDimensions,
-                    @Cached("createForeignRead(positions)") Node foreignRead,
+                    @Cached("READ.createNode()") Node foreignRead,
+                    @Cached("KEY_INFO.createNode()") Node keyInfoNode,
                     @Cached("positions.length") @SuppressWarnings("unused") int cachedLength,
                     @Cached("create()") CastStringNode castNode,
                     @Cached("createFirstString()") FirstStringNode firstString,
-                    @Cached("createClassProfile()") ValueProfile positionProfile) {
-        Object position = positionProfile.profile(positions[0]);
+                    @Cached("createClassProfile()") ValueProfile positionProfile,
+                    @Cached("IS_NULL.createNode()") Node isNullNode,
+                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
+                    @Cached("UNBOX.createNode()") Node unboxNode) {
+        if (positions.length == 0) {
+            throw RError.error(this, RError.Message.GENERIC, "No positions for foreign access.");
+        }
+        positions = positionProfile.profile(positions);
         try {
-            if (position instanceof Integer) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((int) position) - 1});
-            } else if (position instanceof Double) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((double) position) - 1});
-            } else if (position instanceof String) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{position});
-            } else if (position instanceof RAbstractStringVector) {
-                String string = firstString.executeString(castNode.doCast(position));
-                return ForeignAccess.send(foreignRead, object, new Object[]{string});
-            } else if (position instanceof RAbstractDoubleVector) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1});
-            } else if (position instanceof RAbstractIntVector) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractIntVector) position).getDataAt(0) - 1});
-            } else {
-                throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+            try {
+                // TODO implicite unboxing ok? method calls seem to behave this way
+                Object result = object;
+                for (int i = 0; i < positions.length; i++) {
+                    result = send(positions[i], foreignRead, keyInfoNode, (TruffleObject) result, firstString, castNode);
+                    if (positions.length > 1 && i < positions.length - 1) {
+                        assert result instanceof TruffleObject;
+                    }
+                }
+                return unbox(result, isNullNode, isBoxedNode, unboxNode);
+            } catch (UnknownIdentifierException | NoSuchFieldError e) {
+                throw RError.interopError(RError.findParentRBase(this), e, object);
             }
         } catch (InteropException e) {
             throw RError.interopError(RError.findParentRBase(this), e, object);
         }
     }
 
+    private Object unbox(Object obj, Node isNullNode, Node isBoxedNode, Node unboxNode) throws UnsupportedMessageException {
+        if (RRuntime.isForeignObject(obj)) {
+            if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) obj)) {
+                return RNull.instance;
+            }
+            Boolean isBoxed = (Boolean) ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) obj);
+            if (isBoxed) {
+                return RRuntime.java2R(ForeignAccess.sendUnbox(unboxNode, (TruffleObject) obj));
+            }
+        }
+        return RRuntime.java2R(obj);
+    }
+
+    private Object send(Object position, Node foreignRead, Node keyInfoNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode) throws RError, InteropException {
+        if (position instanceof Integer) {
+            position = ((int) position) - 1;
+        } else if (position instanceof Double) {
+            position = ((double) position) - 1;
+        } else if (position instanceof RAbstractDoubleVector) {
+            position = ((RAbstractDoubleVector) position).getDataAt(0) - 1;
+        } else if (position instanceof RAbstractIntVector) {
+            position = ((RAbstractIntVector) position).getDataAt(0) - 1;
+        } else if (position instanceof RAbstractStringVector) {
+            position = firstString.executeString(castNode.doCast(position));
+        } else if (!(position instanceof String)) {
+            throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+        }
+
+        int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
+        if (KeyInfo.isReadable(info)) {
+            return ForeignAccess.sendRead(foreignRead, object, position);
+        } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
+            TruffleObject clazz = JavaInterop.toJavaClass(object);
+            info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position);
+            if (KeyInfo.isReadable(info)) {
+                return ForeignAccess.sendRead(foreignRead, clazz, position);
+            }
+        }
+        throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
+    }
+
     @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"})
     protected Object doExtractSameDimensions(VirtualFrame frame, RAbstractVector vector, Object[] positions, Object exact, Object dropDimensions,  //
                     @Cached("createRecursiveCache(vector, positions)") RecursiveExtractSubscriptNode cached) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
index d85926100c32e53a126f3b83df998b5248514e6a..5c4fa8b7749708527f3d6d0b2f23354e79fe3743 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
@@ -25,12 +25,15 @@ package com.oracle.truffle.r.nodes.access.vector;
 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.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.KeyInfo;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
@@ -38,8 +41,6 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.FirstStringNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RDouble;
-import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -49,6 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 /**
  * Syntax node for element writes.
  */
+@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
 public abstract class ReplaceVectorNode extends Node {
 
     protected static final int CACHE_LIMIT = 5;
@@ -97,40 +99,50 @@ public abstract class ReplaceVectorNode extends Node {
 
     @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"})
     protected Object accessField(TruffleObject object, Object[] positions, Object value,
-                    @Cached("createForeignWrite(positions)") Node foreignRead,
+                    @Cached("WRITE.createNode()") Node foreignWrite,
+                    @Cached("KEY_INFO.createNode()") Node keyInfo,
                     @SuppressWarnings("unused") @Cached("positions.length") int cachedLength,
                     @Cached("create()") CastStringNode castNode,
                     @Cached("createFirstString()") FirstStringNode firstString) {
-
-        Object writtenValue = value;
-        if (writtenValue instanceof RInteger) {
-            writtenValue = ((RInteger) writtenValue).getValue();
-        } else if (writtenValue instanceof RDouble) {
-            writtenValue = ((RDouble) writtenValue).getValue();
-        }
+        Object writtenValue = RRuntime.r2Java(value);
         Object position = positions[0];
         try {
-            if (position instanceof Integer) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((Integer) position) - 1, writtenValue});
-            } else if (position instanceof Double) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((Double) position) - 1, writtenValue});
-            } else if (position instanceof String) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{position, writtenValue});
-            } else if (position instanceof RAbstractStringVector) {
-                String string = firstString.executeString(castNode.doCast(position));
-                return ForeignAccess.send(foreignRead, object, new Object[]{string, writtenValue});
-            } else if (position instanceof RAbstractDoubleVector) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1, writtenValue});
-            } else if (position instanceof RAbstractIntVector) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractIntVector) position).getDataAt(0) - 1, writtenValue});
-            } else {
-                throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
-            }
+            return write(position, foreignWrite, keyInfo, object, writtenValue, firstString, castNode);
         } catch (InteropException e) {
             throw RError.interopError(RError.findParentRBase(this), e, object);
         }
     }
 
+    private Object write(Object position, Node foreignWrite, Node keyInfoNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode)
+                    throws InteropException, RError {
+        if (position instanceof Integer) {
+            position = ((Integer) position) - 1;
+        } else if (position instanceof Double) {
+            position = ((Double) position) - 1;
+        } else if (position instanceof RAbstractDoubleVector) {
+            position = ((RAbstractDoubleVector) position).getDataAt(0) - 1;
+        } else if (position instanceof RAbstractIntVector) {
+            position = ((RAbstractIntVector) position).getDataAt(0) - 1;
+        } else if (position instanceof RAbstractStringVector) {
+            String string = firstString.executeString(castNode.doCast(position));
+            position = string;
+        } else if (!(position instanceof String)) {
+            throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+        }
+
+        int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
+        if (KeyInfo.isWritable(info)) {
+            return ForeignAccess.sendWrite(foreignWrite, object, position, writtenValue);
+        } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
+            TruffleObject clazz = JavaInterop.toJavaClass(object);
+            info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position);
+            if (KeyInfo.isWritable(info)) {
+                return ForeignAccess.sendWrite(foreignWrite, clazz, position, writtenValue);
+            }
+        }
+        throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
+    }
+
     @Specialization(limit = "CACHE_LIMIT", guards = {"cached != null", "cached.isSupported(vector, positions)"})
     protected Object doRecursive(VirtualFrame frame, RAbstractListVector vector, Object[] positions, Object value,  //
                     @Cached("createRecursiveCache(vector, positions)") RecursiveReplaceSubscriptNode cached) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index fd54fa745ced5ad26aa9bd395633daf504cccdab..29c1453ada068b616d66acff9b7c3d097a92095e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -48,6 +48,7 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -148,6 +149,11 @@ public abstract class ClassHierarchyNode extends UnaryNode {
         return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Null) : null;
     }
 
+    @Specialization
+    protected RStringVector getClassHr(@SuppressWarnings("unused") RInteropScalar arg) {
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(arg.getRType()) : null;
+    }
+
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") REmpty arg) {
         return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Null) : null;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index a2bf334242b3b14374d164e4cd87b2b71089bc7a..7fa4270828d46489c5babae16b4f34a4715714db 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -40,9 +40,12 @@ import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
+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.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
@@ -90,6 +93,7 @@ import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -526,6 +530,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
 
         @Child private CallArgumentsNode arguments;
         @Child private Node foreignCall;
+        @Child private Node isNullCall;
         @CompilationFinal private int foreignCallArgCount;
 
         public ForeignCall(CallArgumentsNode arguments) {
@@ -540,15 +545,20 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                 foreignCallArgCount = argumentsArray.length;
             }
             try {
-                Object result = ForeignAccess.sendExecute(foreignCall, function, argumentsArray);
-                if (result instanceof Boolean) {
-                    // convert to R logical
-                    // TODO byte/short convert to int?
-                    result = RRuntime.asLogical((boolean) result);
+                Object result = ForeignAccess.sendExecute(foreignCall, function, RRuntime.r2Java(argumentsArray));
+                if (RRuntime.isForeignObject(result)) {
+                    if (isNullCall == null) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        isNullCall = insert(Message.IS_NULL.createNode());
+                    }
+                    if (ForeignAccess.sendIsNull(isNullCall, (TruffleObject) result)) {
+                        return RNull.instance;
+                    }
                 }
-                return result;
-            } catch (Throwable e) {
+                return RRuntime.java2R(result);
+            } catch (ArityException | UnsupportedMessageException | UnsupportedTypeException e) {
                 CompilerDirectives.transferToInterpreter();
+                RInternalError.reportError(e);
                 throw RError.interopError(RError.findParentRBase(this), e, function);
             }
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
index 5b442a98d5ac425061188d43edf3216253232f8f..2ea4c2b07e10e2b1091fda964087e9e2ba77f6cc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 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.interop.TruffleObject;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
@@ -37,6 +38,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -147,6 +149,16 @@ public abstract class CastListNode extends CastBaseNode {
         return RDataFactory.createList(new Object[]{s});
     }
 
+    @Specialization
+    protected RList doRInterop(RInteropScalar ri) {
+        return RDataFactory.createList(new Object[]{ri});
+    }
+
+    @Specialization(guards = {"isForeignObject(to)"})
+    protected RList doForeignObject(TruffleObject to) {
+        return RDataFactory.createList(new Object[]{to});
+    }
+
     public static CastListNode create() {
         return CastListNodeGen.create(true, true, true);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
index 03eda37330086b211fb655eaf8f39044fd8860df..1d8a29e9d0177c5ed84f70955de8b0cf4fa606e6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -35,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
@@ -151,6 +153,11 @@ public abstract class PrecedenceNode extends RBaseNode {
         return LIST_PRECEDENCE;
     }
 
+    @Specialization
+    protected int doRInteroptFloat(RInterop b, boolean recursive) {
+        return NO_PRECEDENCE;
+    }
+
     @Specialization(guards = "recursive")
     protected int doListRecursive(RList val, boolean recursive,
                     @Cached("createRecursive()") PrecedenceNode precedenceNode) {
@@ -205,6 +212,16 @@ public abstract class PrecedenceNode extends RBaseNode {
         return LIST_PRECEDENCE;
     }
 
+    @Specialization
+    protected int doRInterop(RInteropScalar ri, boolean recursive) {
+        return LIST_PRECEDENCE;
+    }
+
+    @Specialization(guards = {"isForeignObject(to)"})
+    protected int doForeignObject(TruffleObject to, boolean recursive) {
+        return LIST_PRECEDENCE;
+    }
+
     @Specialization(guards = {"!recursive", "args.getLength() == 1"})
     protected int doArgsValuesAndNames(RArgsValuesAndNames args, boolean recursive,
                     @Cached("createRecursive()") PrecedenceNode precedenceNode) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 8583792a6fa9bac94b31a98244a5b83cacf22be6..fbb3953558a93d1e1a604db5ce01d7ce14dc455e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -613,6 +613,7 @@ public final class RError extends RuntimeException {
         UNRECOGNIZED_FORMAT("unrecognized format specification '%s'"),
         INVALID_FORMAT_LOGICAL("invalid format '%s'; use format %%d or %%i for logical objects"),
         INVALID_FORMAT_INTEGER("invalid format '%s'; use format %%d, %%i, %%o, %%x or %%X for integer objects"),
+        POS_NOT_ALLOWED_WITH_NUMERIC("pos argument not allowed with a numeric value"),
         // the following list is incomplete (but like GNU-R)
         INVALID_FORMAT_DOUBLE("invalid format '%s'; use format %%f, %%e, %%g or %%a for numeric objects"),
         INVALID_LOGICAL("'%s' must be TRUE or FALSE"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 542a7976db4d7acd2514abdc426bad713a626cd0..d80fe43d1b3578985e0c98a8257f844cbd4db456 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -21,22 +21,31 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort;
 import com.oracle.truffle.r.runtime.data.RLogical;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 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.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -312,7 +321,7 @@ public class RRuntime {
     }
 
     public static String logicalToStringNoCheck(byte operand) {
-        assert operand == LOGICAL_TRUE || operand == LOGICAL_FALSE;
+        assert operand == LOGICAL_TRUE || operand == LOGICAL_FALSE : "operand: " + operand;
         return operand == LOGICAL_TRUE ? STRING_TRUE : STRING_FALSE;
     }
 
@@ -918,4 +927,66 @@ public class RRuntime {
         return xa.hasDimensions();
     }
 
+    public static Object java2R(Object obj) {
+        if (obj == null) {
+            obj = RNull.instance;
+        } else if (obj instanceof Boolean) {
+            obj = RRuntime.asLogical((boolean) obj);
+        } else if (obj instanceof Byte) {
+            obj = ((Byte) obj).intValue();
+        } else if (obj instanceof Short) {
+            obj = ((Short) obj).intValue();
+        } else if (obj instanceof Long) {
+            obj = (((Long) obj).doubleValue());
+        } else if (obj instanceof Float) {
+            obj = (((Float) obj).doubleValue());
+        } else if (obj instanceof Character) {
+            obj = ((Character) obj).toString();
+        }
+        return obj;
+    }
+
+    public static Object[] r2Java(Object[] objects) {
+        Object[] ret = new Object[objects.length];
+        for (int i = 0; i < objects.length; i++) {
+            ret[i] = RRuntime.r2Java(objects[i]);
+        }
+        return ret;
+    }
+
+    public static Object r2Java(Object obj) {
+        if (obj == RNull.instance) {
+            return JavaInterop.asTruffleObject(null);
+        } else if (obj instanceof Byte) {
+            return RRuntime.fromLogical((byte) obj);
+        } else if (obj instanceof RInteropByte) {
+            return ((RInteropByte) obj).getValue();
+        } else if (obj instanceof RInteropChar) {
+            return ((RInteropChar) obj).getValue();
+        } else if (obj instanceof RInteropFloat) {
+            return ((RInteropFloat) obj).getValue();
+        } else if (obj instanceof RInteropLong) {
+            return ((RInteropLong) obj).getValue();
+        } else if (obj instanceof RInteropShort) {
+            return ((RInteropShort) obj).getValue();
+        } else if (obj instanceof RAbstractAtomicVector && ((RAbstractAtomicVector) obj).getLength() == 1) {
+            if (obj instanceof RAbstractDoubleVector) {
+                RAbstractDoubleVector v = (RAbstractDoubleVector) obj;
+                return v.getDataAt(0);
+            } else if (obj instanceof RAbstractIntVector) {
+                RAbstractIntVector v = (RAbstractIntVector) obj;
+                return v.getDataAt(0);
+            } else if (obj instanceof RAbstractLogicalVector) {
+                RAbstractLogicalVector v = (RAbstractLogicalVector) obj;
+                return v.getDataAt(0) == RRuntime.LOGICAL_TRUE;
+            } else if (obj instanceof RAbstractRawVector) {
+                RAbstractRawVector v = (RAbstractRawVector) obj;
+                return v.getDataAt(0).getValue();
+            } else if (obj instanceof RAbstractStringVector) {
+                RAbstractStringVector v = (RAbstractStringVector) obj;
+                return v.getDataAt(0);
+            }
+        }
+        return obj;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
index ddf2a1e6c0cd6cfec7d8c887631006d9cb63978f..c4d03652bf2589339d29122b77bc67cd6709bc7d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
@@ -47,7 +47,12 @@ public enum RType {
     S4Object("S4", -1),
     Connection("connection", -1),
     Dots("...", -1),
-    TruffleObject("truffle.object", -1);
+    TruffleObject("truffle.object", -1),
+    RInteropByte("interopt.byte", -1),
+    RInteropChar("interopt.char", -1),
+    RInteropFloat("interopt.float", -1),
+    RInteropLong("interopt.long", -1),
+    RInteropShort("interopt.short", -1);
 
     public static final int NO_PRECEDENCE = -1;
     public static final int NUMBER_OF_PRECEDENCES = 9;
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
new file mode 100644
index 0000000000000000000000000000000000000000..e2f4a3bc4f353262e1549262b330a0cba60497e6
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2013, 2017, 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 2 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 2 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
+ * 2 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.runtime.data;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives.ValueType;
+import com.oracle.truffle.r.runtime.RType;
+
+@ValueType
+public abstract class RInteropScalar extends RScalar {
+
+    public abstract Object getRValue();
+
+    @ValueType
+    public static final class RInteropByte extends RInteropScalar {
+
+        private final byte value;
+
+        private RInteropByte(byte value) {
+            this.value = value;
+        }
+
+        public static RInteropByte valueOf(byte value) {
+            return new RInteropByte(value);
+        }
+
+        public byte getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return ((Byte) value).intValue();
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropByte;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Byte.toString(value);
+        }
+    }
+
+    @ValueType
+    public static final class RInteropChar extends RInteropScalar {
+
+        private final char value;
+
+        private RInteropChar(char value) {
+            this.value = value;
+        }
+
+        public static RInteropChar valueOf(char value) {
+            return new RInteropChar(value);
+        }
+
+        public char getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return Character.toString(value);
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropChar;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Character.toString(value);
+        }
+    }
+
+    @ValueType
+    public static final class RInteropFloat extends RInteropScalar {
+
+        private final float value;
+
+        private RInteropFloat(float value) {
+            this.value = value;
+        }
+
+        public static RInteropFloat valueOf(float value) {
+            return new RInteropFloat(value);
+        }
+
+        public float getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return ((Float) value).doubleValue();
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropFloat;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Float.toString(value);
+        }
+    }
+
+    @ValueType
+    public static final class RInteropLong extends RInteropScalar {
+
+        private final long value;
+
+        private RInteropLong(long value) {
+            this.value = value;
+        }
+
+        public static RInteropLong valueOf(long value) {
+            return new RInteropLong(value);
+        }
+
+        public long getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return ((Long) value).doubleValue();
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropLong;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Long.toString(value);
+        }
+    }
+
+    @ValueType
+    public static final class RInteropShort extends RInteropScalar {
+
+        private final short value;
+
+        private RInteropShort(short value) {
+            this.value = value;
+        }
+
+        public static RInteropShort valueOf(short value) {
+            return new RInteropShort(value);
+        }
+
+        public short getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return ((Short) value).intValue();
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropShort;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Short.toString(value);
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
index c7c9a3819d8f46b22196331fdc85c3c590d8f6d0..f11da3d123650f52a9ed9c974c93284153ae10de 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
@@ -26,6 +26,11 @@ import com.oracle.truffle.api.dsl.ImplicitCast;
 import com.oracle.truffle.api.dsl.TypeCast;
 import com.oracle.truffle.api.dsl.TypeCheck;
 import com.oracle.truffle.api.dsl.TypeSystem;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -47,7 +52,11 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  * @see RNode
  */
 @TypeSystem({
-                byte.class, RAbstractLogicalVector.class,
+                byte.class, RAbstractLogicalVector.class, RInteropByte.class,
+                RInteropChar.class,
+                RInteropFloat.class,
+                RInteropLong.class,
+                RInteropShort.class,
                 int.class, RAbstractIntVector.class,
                 double.class, RAbstractDoubleVector.class,
                 String.class, RAbstractStringVector.class,
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 384d1e505657731303dbe9c0856e379eebf748d0..23d2b3fefd7c2bfffbf65118820ea631da1b5eb9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -130560,6 +130560,606 @@ attr(,"is.truffle.object")
 attr(,"is.truffle.object")
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAllTypes#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
+[1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAllTypes#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
+[1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringObject }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringObject }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldChar }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharObject }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticChar }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharObject }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDouble }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleObject }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDouble }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleObject }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByte }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteObject }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByte }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteObject }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldInteger }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntegerObject }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticInteger }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntegerObject }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloat }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatObject }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloat }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatObject }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShort }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortObject }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShort }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortObject }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLong }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongObject }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLong }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongObject }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldNullObject }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNullObject }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NaN } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNaN }
+[1] NaN
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NaN } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNaNObject }
+[1] NaN
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanObject }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanObject }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringArray }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringObject() }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringObject() }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodChar() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodCharObject() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticChar() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticCharObject() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodDouble() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodDoubleObject() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticDouble() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticDoubleObject() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodByte() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodByteObject() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticByte() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticByteObject() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodInteger() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntegerObject() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticInteger() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntegerObject() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodFloat() }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodFloatObject() }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticFloat() }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticFloatObject() }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodShort() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodShortObject() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticShort() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticShortObject() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodLong() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodLongObject() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticLong() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticLongObject() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodReturnsNull() }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticReturnsNull() }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodBoolean() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodBooleanObject() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticBoolean() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticBooleanObject() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringArray() }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringArray() }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntArray() }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntArray() }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { tc <- .fastr.java.class('java.lang.Character'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'abc' } else { tc <- .fastr.java.class('java.lang.String'); t <- .fastr.interop.new(tc, 'abc'); t }
+[1] "abc"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'truffle.object' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNullClass'); t <- .fastr.interop.new(tc, NULL); class(t) }
+[1] "truffle.object"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Byte'); t <- .fastr.interop.new(tc, .fastr.interop.toByte(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Integer'); t <- .fastr.interop.new(tc, 1L); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Long'); t <- .fastr.interop.new(tc, .fastr.interop.toLong(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Short'); t <- .fastr.interop.new(tc, .fastr.interop.toShort(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { tc <- .fastr.java.class('java.lang.Double'); t <- .fastr.interop.new(tc, 1.1); t }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { tc <- .fastr.java.class('java.lang.Float'); t <- .fastr.interop.new(tc, .fastr.interop.toFloat(1.1)); t }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('java.lang.Boolean'); t <- .fastr.interop.new(tc, TRUE); t }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNonPrimitiveParameter#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$equals(t) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameter#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.Long } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull(1) }
+Error: object 'java.lang.Long' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameter#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull('string') }
+Error: object 'java.lang.String' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { boolean } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded(TRUE) }
+Error: object 'boolean' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded('string') }
+Error: object 'java.lang.String' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); class(v); }
+[1] "interopt.byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); typeof(v); }
+[1] "interopt.byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toByte(1.7976931348623157E308); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toByte(2147483647); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -128 } else { v <- .fastr.interop.toByte(-128); v; }
+[1] -128
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toByte(-2147483648); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toByte(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { v <- .fastr.interop.toByte(127); v; }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar('a'); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97.1); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'b' } else { v <- .fastr.interop.toChar('abc', 1); v; }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'b' } else { v <- .fastr.interop.toChar('abc', 1.1); v; }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97); class(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97); typeof(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); class(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); typeof(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0.0 } else { v <- .fastr.interop.toFloat(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { v <- .fastr.interop.toFloat(1.1); v; }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.401298464324817E-45 } else { v <- .fastr.interop.toFloat(1.4E-45); v; }
+[1] 1.401298e-45
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { v <- .fastr.interop.toFloat(3.4028235E38); v; }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { Inf } else { v <- .fastr.interop.toFloat(1.7976931348623157E308); v; }
+[1] Inf
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); class(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); typeof(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -2147483648 } else { v <- .fastr.interop.toLong(-2147483648); v; }
+[1] -2147483648
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toLong(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { v <- .fastr.interop.toLong(2147483647); v; }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { v <- .fastr.interop.toLong(1.7976931348623157E308); v; }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); class(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); typeof(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(1.7976931348623157E308); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(2147483647); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -32768 } else { v <- .fastr.interop.toShort(-32768); v; }
+[1] -32768
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toShort(-2147483648); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toShort(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { v <- .fastr.interop.toShort(32767); v; }
+[1] 32767
+
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { { f<-function(x) .fastr.refcountinfo(x); f(c(1,2)) } }
 [1] 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
index 21d6e39b32118f9e58899eee2962eff22cb8e6ad..1eb1faf9b642b24dbb7711d5c867c97feea8e5bc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
@@ -49,6 +49,7 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.test.generate.FastRSession;
 import com.oracle.truffle.r.test.generate.GnuROneShotRSession;
 import com.oracle.truffle.r.test.generate.TestOutputManager;
+import java.io.OutputStream;
 
 /**
  * Base class for all unit tests. The unit tests are actually arranged as a collection of
@@ -469,8 +470,16 @@ public class TestBase {
     }
 
     // support testing of FastR-only functionality (equivalent GNU R output provided separately)
+    protected void assertEvalFastR(TestTrait trait1, String input, String gnuROutput) {
+        evalAndCompare(getAssertEvalFastR(gnuROutput, input), trait1);
+    }
+
     protected void assertEvalFastR(String input, String gnuROutput) {
-        evalAndCompare(new String[]{"if (length(grep(\"FastR\", R.Version()$version.string)) != 1) { " + gnuROutput + " } else { " + input + " }"});
+        evalAndCompare(getAssertEvalFastR(gnuROutput, input));
+    }
+
+    private static String[] getAssertEvalFastR(String gnuROutput, String input) {
+        return new String[]{"if (length(grep(\"FastR\", R.Version()$version.string)) != 1) { " + gnuROutput + " } else { " + input + " }"};
     }
 
     /*
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
new file mode 100644
index 0000000000000000000000000000000000000000..22d14b31b44934768f4dcc9d5283193f23c15c02
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2015, 2017, 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 2 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 2 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
+ * 2 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.test.library.fastr;
+
+import com.oracle.truffle.r.runtime.RType;
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class TestJavaInterop extends TestBase {
+
+    private static final String TEST_CLASS = TestClass.class.getName();
+
+    @Test
+    public void testToByte() {
+        assertEvalFastR("v <- .fastr.interop.toByte(1L); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toByte(1.1); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toByte(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toByte(1.1); class(v);", "'" + RType.RInteropByte.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toByte(1.1); typeof(v);", "'" + RType.RInteropByte.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Byte.MAX_VALUE + "); v;", "" + Byte.MAX_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Byte.MIN_VALUE + "); v;", "" + Byte.MIN_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).byteValue());
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).byteValue());
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).byteValue());
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).byteValue());
+    }
+
+    @Test
+    public void testToFloat() {
+        assertEvalFastR("v <- .fastr.interop.toFloat(1L); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); v;", "1.1");
+        assertEvalFastR("v <- .fastr.interop.toFloat(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); class(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); typeof(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1L); class(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1L); typeof(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toFloat(" + Float.MAX_VALUE + "); v;", "" + Float.MAX_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toFloat(" + Float.MIN_VALUE + "); v;", "" + (double) Float.MIN_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toFloat(" + Double.MAX_VALUE + "); v;", "Inf");
+        assertEvalFastR("v <- .fastr.interop.toFloat(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).floatValue());
+    }
+
+    @Test
+    public void testToLong() {
+        assertEvalFastR("v <- .fastr.interop.toLong(1L); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toLong(1.1); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toLong(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toLong(1.1); class(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toLong(1.1); typeof(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toLong(1L); class(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toLong(1L); typeof(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toLong(" + Integer.MAX_VALUE + "); v;", "" + Integer.MAX_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toLong(" + Integer.MIN_VALUE + "); v;", "" + Integer.MIN_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toLong(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).longValue());
+        assertEvalFastR("v <- .fastr.interop.toLong(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).longValue());
+    }
+
+    @Test
+    public void testToShort() {
+        assertEvalFastR("v <- .fastr.interop.toShort(1L); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toShort(1.1); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toShort(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toShort(1.1); class(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toShort(1.1); typeof(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toShort(1L); class(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toShort(1L); typeof(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Short.MAX_VALUE + "); v;", "" + Short.MAX_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Short.MIN_VALUE + "); v;", "" + Short.MIN_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).shortValue());
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).shortValue());
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).shortValue());
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).shortValue());
+    }
+
+    @Test
+    public void testToChar() {
+        assertEvalFastR("v <- .fastr.interop.toChar(97L); v;", "'a'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97.1); v;", "'a'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97.1, 1); v;", "cat('Error in .fastr.interop.toChar(97.1, 1) : ', '\n', ' pos argument not allowed with a numeric value', '\n')");
+        assertEvalFastR("v <- .fastr.interop.toChar(97L, 1); v;", "cat('Error in .fastr.interop.toChar(97L, 1) : ','\n',' pos argument not allowed with a numeric value', '\n')");
+        assertEvalFastR("v <- .fastr.interop.toChar('abc', 1); v;", "'b'");
+        assertEvalFastR("v <- .fastr.interop.toChar('abc', 1.1); v;", "'b'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97.1); class(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97.1); typeof(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97L); class(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97L); typeof(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toChar('a'); v;", "'a'");
+    }
+
+    @Test
+    public void testNew() {
+        assertEvalFastR("tc <- .fastr.java.class('" + Boolean.class.getName() + "'); t <- .fastr.interop.new(tc, TRUE); t", "TRUE");
+        assertEvalFastR("tc <- .fastr.java.class('" + Byte.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toByte(1)); t", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Character.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t", "'a'");
+        assertEvalFastR("tc <- .fastr.java.class('" + Double.class.getName() + "'); t <- .fastr.interop.new(tc, 1.1); t", "1.1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Float.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toFloat(1.1)); t", "1.1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Integer.class.getName() + "'); t <- .fastr.interop.new(tc, 1L); t", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Long.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toLong(1)); t", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Short.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toShort(1)); t", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + String.class.getName() + "'); t <- .fastr.interop.new(tc, 'abc'); t", "'abc'");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNullClass.class.getName() + "'); t <- .fastr.interop.new(tc, NULL); class(t)", "'" + RType.TruffleObject.getName() + "'");
+    }
+
+    @Test
+    public void testFields() throws IllegalArgumentException, IllegalAccessException {
+        TestClass t = new TestClass();
+        Field[] fields = t.getClass().getDeclaredFields();
+        for (Field f : fields) {
+            String name = f.getName();
+            if (name.startsWith("field")) {
+                testForValue(name, f.get(t));
+            }
+        }
+    }
+
+    @Test
+    public void testMethods() throws IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException {
+        TestClass t = new TestClass();
+        Method[] methods = t.getClass().getDeclaredMethods();
+        for (Method m : methods) {
+            if (m.getParameterCount() == 0) {
+                String name = m.getName();
+                if (name.startsWith("method")) {
+                    testForValue(name + "()", m.invoke(t));
+                }
+            }
+        }
+    }
+
+    private void testForValue(String member, Object value) {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + member, getRValue(value));
+    }
+
+    @Test
+    public void testAllTypes() {
+        getValueForAllTypesMethod("allTypesMethod");
+        getValueForAllTypesMethod("allTypesStaticMethod");
+    }
+
+    @Test
+    public void testNonPrimitiveParameter() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", getRValue(true));
+    }
+
+    private void getValueForAllTypesMethod(String method) {
+        boolean bo = true;
+        byte bt = Byte.MAX_VALUE;
+        char c = 'a';
+        short sh = Short.MAX_VALUE;
+        int i = Integer.MAX_VALUE;
+        long l = Long.MAX_VALUE;
+        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) + ")",
+                        getRValue("" + bo + bt + c + sh + i + l + d + f + s));
+    }
+
+    @Test
+    public void testNullParameter() {
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull('string')", "java.lang.String");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull(1)", "java.lang.Long");
+    }
+
+    @Test
+    public void testOverloaded() {
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isOverloaded(TRUE)", "boolean");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isOverloaded('string')", String.class.getName());
+        // TODO add remaining isOverloaded(...) calls once this is fixed
+    }
+
+    private String getRValue(Object value) {
+        if (value == null) {
+            return "NULL";
+        }
+        if (value instanceof Boolean) {
+            return value.toString().toUpperCase();
+        }
+        if (value instanceof String) {
+            return "\"" + value.toString() + "\"";
+        }
+        if (value instanceof Character) {
+            return "\"" + ((Character) value).toString() + "\"";
+        }
+        if (value.getClass().isArray()) {
+            StringBuilder sb = new StringBuilder();
+            int l = Array.getLength(value);
+            sb.append("cat('[1] ");
+            for (int i = 0; i < l; i++) {
+                sb.append(getRValue(Array.get(value, i)));
+                if (i < l - 1) {
+                    sb.append(" ");
+                }
+            }
+            sb.append("\\nattr(,\"is.truffle.object\")\\n[1] TRUE\\n')");
+            return sb.toString();
+        }
+
+        return value.toString();
+    }
+
+    private String getRValue(Object... values) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < values.length; i++) {
+            Object v = values[i];
+            sb.append(getRValue(v));
+            if (i < values.length - 1) {
+                sb.append(",");
+            }
+        }
+        return sb.toString();
+    }
+
+    public static class TestNullClass {
+        public TestNullClass(Object o) {
+            assert o == null;
+        }
+    }
+
+    public static class TestClass {
+
+        public static boolean fieldStaticBoolean = true;
+        public static byte fieldStaticByte = Byte.MAX_VALUE;
+        public static char fieldStaticChar = 'a';
+        public static short fieldStaticShort = Short.MAX_VALUE;
+        public static int fieldStaticInteger = Integer.MAX_VALUE;
+        public static long fieldStaticLong = Long.MAX_VALUE;
+        public static double fieldStaticDouble = Double.MAX_VALUE;
+        public static float fieldStaticFloat = Float.MAX_VALUE;
+
+        public static Boolean fieldStaticBooleanObject = fieldStaticBoolean;
+        public static Byte fieldStaticByteObject = fieldStaticByte;
+        public static Character fieldStaticCharObject = fieldStaticChar;
+        public static Short fieldStaticShortObject = fieldStaticShort;
+        public static Integer fieldStaticIntegerObject = fieldStaticInteger;
+        public static Long fieldStaticLongObject = fieldStaticLong;
+        public static Double fieldStaticDoubleObject = fieldStaticDouble;
+        public static Float fieldStaticFloatObject = fieldStaticFloat;
+        public static String fieldStaticStringObject = "a string";
+
+        public boolean fieldBoolean = fieldStaticBoolean;
+        public byte fieldByte = fieldStaticByte;
+        public char fieldChar = fieldStaticChar;
+        public short fieldShort = fieldStaticShort;
+        public int fieldInteger = fieldStaticInteger;
+        public long fieldLong = fieldStaticLong;
+        public double fieldDouble = fieldStaticDouble;
+        public float fieldFloat = fieldStaticFloat;
+
+        public Boolean fieldBooleanObject = fieldBoolean;
+        public Byte fieldByteObject = fieldByte;
+        public Character fieldCharObject = fieldChar;
+        public Short fieldShortObject = fieldShort;
+        public Integer fieldIntegerObject = fieldInteger;
+        public Long fieldLongObject = fieldLong;
+        public Double fieldDoubleObject = fieldDouble;
+        public Float fieldFloatObject = fieldFloat;
+        public String fieldStringObject = fieldStaticStringObject;
+
+        public static Double fieldStaticNaNObject = Double.NaN;
+        public static double fieldStaticNaN = Double.NaN;
+
+        public static int[] fieldStaticIntArray = new int[]{1, 2, 3};
+        public static String[] fieldStaticStringArray = new String[]{"a", "b", "c"};
+
+        public int[] fieldIntArray = fieldStaticIntArray;
+        public String[] fieldStringArray = fieldStaticStringArray;
+
+        public static Object fieldStaticNullObject = null;
+        public Object fieldNullObject = null;
+
+        public TestClass() {
+            this(true, Byte.MAX_VALUE, 'a', Double.MAX_VALUE, Float.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE, Short.MAX_VALUE, "a string");
+        }
+
+        public TestClass(boolean bo, byte bt, char c, double d, float f, int i, long l, short sh, String st) {
+            fieldStaticBoolean = bo;
+            fieldStaticByte = bt;
+            fieldStaticChar = c;
+            fieldStaticDouble = d;
+            fieldStaticFloat = f;
+            fieldStaticInteger = i;
+            fieldStaticLong = l;
+            fieldStaticShort = sh;
+            fieldStaticStringObject = st;
+
+            // fieldStaticIntArray = ia;
+            // fieldStaticStringArray = sta;
+
+            fieldStaticBooleanObject = fieldStaticBoolean;
+            fieldStaticByteObject = fieldStaticByte;
+            fieldStaticCharObject = fieldStaticChar;
+            fieldStaticShortObject = fieldStaticShort;
+            fieldStaticIntegerObject = fieldStaticInteger;
+            fieldStaticLongObject = fieldStaticLong;
+            fieldStaticDoubleObject = fieldStaticDouble;
+            fieldStaticFloatObject = fieldStaticFloat;
+
+            this.fieldBoolean = fieldStaticBoolean;
+            this.fieldByte = fieldStaticByte;
+            this.fieldChar = fieldStaticChar;
+            this.fieldShort = fieldStaticShort;
+            this.fieldInteger = fieldStaticInteger;
+            this.fieldLong = fieldStaticLong;
+            this.fieldDouble = fieldStaticDouble;
+            this.fieldFloat = fieldStaticFloat;
+
+            this.fieldBooleanObject = fieldBoolean;
+            this.fieldByteObject = fieldByte;
+            this.fieldCharObject = fieldChar;
+            this.fieldShortObject = fieldShort;
+            this.fieldIntegerObject = fieldInteger;
+            this.fieldLongObject = fieldLong;
+            this.fieldDoubleObject = fieldDouble;
+            this.fieldFloatObject = fieldFloat;
+            this.fieldStringObject = fieldStaticStringObject;
+
+            this.fieldIntArray = fieldStaticIntArray;
+            this.fieldStringArray = fieldStaticStringArray;
+        }
+
+        public static boolean methodStaticBoolean() {
+            return fieldStaticBoolean;
+        }
+
+        public static byte methodStaticByte() {
+            return fieldStaticByte;
+        }
+
+        public static char methodStaticChar() {
+            return fieldStaticChar;
+        }
+
+        public static short methodStaticShort() {
+            return fieldStaticShort;
+        }
+
+        public static int methodStaticInteger() {
+            return fieldStaticInteger;
+        }
+
+        public static long methodStaticLong() {
+            return fieldStaticLong;
+        }
+
+        public static double methodStaticDouble() {
+            return fieldStaticDouble;
+        }
+
+        public static float methodStaticFloat() {
+            return fieldStaticFloat;
+        }
+
+        public static String methodStaticStringObject() {
+            return fieldStaticStringObject;
+        }
+
+        public static String[] methodStaticStringArray() {
+            return fieldStaticStringArray;
+        }
+
+        public static int[] methodStaticIntArray() {
+            return fieldStaticIntArray;
+        }
+
+        public boolean methodBoolean() {
+            return fieldBoolean;
+        }
+
+        public byte methodByte() {
+            return fieldByte;
+        }
+
+        public char methodChar() {
+            return fieldChar;
+        }
+
+        public short methodShort() {
+            return fieldShort;
+        }
+
+        public int methodInteger() {
+            return fieldInteger;
+        }
+
+        public long methodLong() {
+            return fieldLong;
+        }
+
+        public double methodDouble() {
+            return fieldDouble;
+        }
+
+        public float methodFloat() {
+            return fieldFloat;
+        }
+
+        public String methodStringObject() {
+            return fieldStringObject;
+        }
+
+        public String[] methodStringArray() {
+            return fieldStringArray;
+        }
+
+        public int[] methodIntArray() {
+            return fieldIntArray;
+        }
+
+        public static Boolean methodStaticBooleanObject() {
+            return fieldStaticBooleanObject;
+        }
+
+        public static Byte methodStaticByteObject() {
+            return fieldStaticByteObject;
+        }
+
+        public static Character methodStaticCharObject() {
+            return fieldStaticCharObject;
+        }
+
+        public static Short methodStaticShortObject() {
+            return fieldStaticShortObject;
+        }
+
+        public static Integer methodStaticIntegerObject() {
+            return fieldStaticIntegerObject;
+        }
+
+        public static Long methodStaticLongObject() {
+            return fieldStaticLongObject;
+        }
+
+        public static Double methodStaticDoubleObject() {
+            return fieldStaticDoubleObject;
+        }
+
+        public static Float methodStaticFloatObject() {
+            return fieldStaticFloatObject;
+        }
+
+        public Boolean methodBooleanObject() {
+            return fieldBoolean;
+        }
+
+        public Byte methodByteObject() {
+            return fieldByteObject;
+        }
+
+        public Character methodCharObject() {
+            return fieldCharObject;
+        }
+
+        public Short methodShortObject() {
+            return fieldShortObject;
+        }
+
+        public Integer methodIntegerObject() {
+            return fieldIntegerObject;
+        }
+
+        public Long methodLongObject() {
+            return fieldLongObject;
+        }
+
+        public Double methodDoubleObject() {
+            return fieldDoubleObject;
+        }
+
+        public Float methodFloatObject() {
+            return fieldFloatObject;
+        }
+
+        public static Object methodStaticReturnsNull() {
+            return null;
+        }
+
+        public Object methodReturnsNull() {
+            return null;
+        }
+
+        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;
+        }
+
+        public static Object allTypesStaticMethod(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;
+        }
+
+        public String isNull(String s) {
+            return s == null ? String.class.getName() : null;
+        }
+
+        public String isNull(Long l) {
+            return l == null ? Long.class.getName() : null;
+        }
+
+        public boolean equals(TestClass tc) {
+            return tc == this;
+        }
+
+        public String isOverloaded(boolean b) {
+            return "boolean";
+        }
+
+        public String isOverloaded(Boolean b) {
+            return Boolean.class.getName();
+        }
+
+        public String isOverloaded(byte b) {
+            return "byte";
+        }
+
+        public String isOverloaded(Byte b) {
+            return Byte.class.getName();
+        }
+
+        public String isOverloaded(char c) {
+            return "char";
+        }
+
+        public String isOverloaded(Character c) {
+            return Character.class.getName();
+        }
+
+        public String isOverloaded(double l) {
+            return "double";
+        }
+
+        public String isOverloaded(Double l) {
+            return Double.class.getName();
+        }
+
+        public String isOverloaded(Float f) {
+            return Float.class.getName();
+        }
+
+        public String isOverloaded(float f) {
+            return "float";
+        }
+
+        public String isOverloaded(int c) {
+            return "int";
+        }
+
+        public String isOverloaded(Integer c) {
+            return Integer.class.getName();
+        }
+
+        public String isOverloaded(long l) {
+            return "long";
+        }
+
+        public String isOverloaded(Long l) {
+            return Long.class.getName();
+        }
+
+        public String isOverloaded(short c) {
+            return "short";
+        }
+
+        public String isOverloaded(Short c) {
+            return Short.class.getName();
+        }
+
+        public String isOverloaded(String s) {
+            return String.class.getName();
+        }
+    }
+}