Skip to content
Snippets Groups Projects
Commit 37fee5f2 authored by Tomas Stupka's avatar Tomas Stupka
Browse files

[GR-4667] Can't create java arrays for primitive types.

parents 3fd5e360 326a96d9
No related branches found
No related tags found
No related merge requests found
...@@ -411,6 +411,7 @@ public class BasePackage extends RBuiltinPackage { ...@@ -411,6 +411,7 @@ public class BasePackage extends RBuiltinPackage {
add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create); add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create);
add(FastRInterop.IsExternal.class, FastRInteropFactory.IsExternalNodeGen::create); add(FastRInterop.IsExternal.class, FastRInteropFactory.IsExternalNodeGen::create);
add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create); add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
add(FastRInterop.JavaClassName.class, FastRInteropFactory.JavaClassNameNodeGen::create);
add(FastRInterop.IsForeignArray.class, FastRInteropFactory.IsForeignArrayNodeGen::create); add(FastRInterop.IsForeignArray.class, FastRInteropFactory.IsForeignArrayNodeGen::create);
add(FastRInterop.NewJavaArray.class, FastRInteropFactory.NewJavaArrayNodeGen::create); add(FastRInterop.NewJavaArray.class, FastRInteropFactory.NewJavaArrayNodeGen::create);
add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create); add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create);
......
...@@ -456,6 +456,35 @@ public class FastRInterop { ...@@ -456,6 +456,35 @@ public class FastRInterop {
} }
} }
@ImportStatic({RRuntime.class})
@RBuiltin(name = ".fastr.java.className", visibility = ON, kind = PRIMITIVE, parameterNames = {"class"}, behavior = COMPLEX)
public abstract static class JavaClassName extends RBuiltinNode.Arg1 {
static {
Casts.noCasts(JavaClassName.class);
}
@Specialization(guards = {"isJavaObject(obj)"})
@TruffleBoundary
public Object javaClassName(TruffleObject obj) {
Object o = JavaInterop.asJavaObject(Object.class, obj);
if (o == null) {
return RNull.instance;
}
return o.getClass().getName();
}
protected boolean isJavaObject(TruffleObject obj) {
return JavaInterop.isJavaObject(obj);
}
@Fallback
public String javaClassName(@SuppressWarnings("unused") Object obj) {
throw error(RError.Message.GENERIC, "unsupported type");
}
}
@ImportStatic({Message.class, RRuntime.class}) @ImportStatic({Message.class, RRuntime.class})
@RBuiltin(name = ".fastr.interop.isArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX) @RBuiltin(name = ".fastr.interop.isArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
public abstract static class IsForeignArray extends RBuiltinNode.Arg1 { public abstract static class IsForeignArray extends RBuiltinNode.Arg1 {
...@@ -489,21 +518,22 @@ public class FastRInterop { ...@@ -489,21 +518,22 @@ public class FastRInterop {
@Specialization @Specialization
@TruffleBoundary @TruffleBoundary
public Object newArray(String clazz, int length) { public Object newArray(String clazz, int length) {
try { return JavaInterop.asTruffleObject(Array.newInstance(getClazz(clazz), length));
// 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());
}
} }
@Specialization @Specialization
@TruffleBoundary @TruffleBoundary
public Object newArray(String clazz, RAbstractIntVector dim) { public Object newArray(String clazz, RAbstractIntVector dim) {
int[] dima = new int[dim.getLength()];
for (int i = 0; i < dima.length; i++) {
dima[i] = dim.getDataAt(i);
}
return JavaInterop.asTruffleObject(Array.newInstance(getClazz(clazz), dima));
}
private Class<?> getClazz(String className) throws RError {
try { try {
int[] dima = new int[dim.getLength()]; return classForName(className);
// TODO new via ForeignAccess
return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), dima));
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage()); throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
} }
...@@ -607,38 +637,6 @@ public class FastRInterop { ...@@ -607,38 +637,6 @@ public class FastRInterop {
return R2ForeignNodeGen.create(); return R2ForeignNodeGen.create();
} }
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 static int[] getDim(boolean flat, RAbstractVector vec) { private static int[] getDim(boolean flat, RAbstractVector vec) {
int[] dims; int[] dims;
if (flat) { if (flat) {
...@@ -673,7 +671,7 @@ public class FastRInterop { ...@@ -673,7 +671,7 @@ public class FastRInterop {
@TruffleBoundary @TruffleBoundary
public Object toArray(TruffleObject obj, @SuppressWarnings("unused") RMissing missing, @SuppressWarnings("unused") boolean flat, public Object toArray(TruffleObject obj, @SuppressWarnings("unused") RMissing missing, @SuppressWarnings("unused") boolean flat,
@Cached("WRITE.createNode()") Node write) { @Cached("WRITE.createNode()") Node write) {
if (JavaInterop.isJavaObject(Object.class, obj)) { if (JavaInterop.isJavaObject(obj)) {
if (JavaInterop.isArray(obj)) { if (JavaInterop.isArray(obj)) {
// TODO should return copy? // TODO should return copy?
return obj; return obj;
...@@ -698,6 +696,14 @@ public class FastRInterop { ...@@ -698,6 +696,14 @@ public class FastRInterop {
throw error(RError.Message.GENERIC, "unsupported type"); throw error(RError.Message.GENERIC, "unsupported type");
} }
private Class<?> getClazz(String className) throws RError {
try {
return classForName(className);
} catch (ClassNotFoundException e) {
throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
}
}
} }
@ImportStatic({Message.class, RRuntime.class}) @ImportStatic({Message.class, RRuntime.class})
...@@ -793,4 +799,32 @@ public class FastRInterop { ...@@ -793,4 +799,32 @@ public class FastRInterop {
return RRuntime.LOGICAL_FALSE; return RRuntime.LOGICAL_FALSE;
} }
} }
private static Class<?> classForName(String className) throws ClassNotFoundException {
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;
}
return Class.forName(className);
}
} }
...@@ -176,6 +176,50 @@ public class TestJavaInterop extends TestBase { ...@@ -176,6 +176,50 @@ public class TestJavaInterop extends TestBase {
assertEvalFastR(Ignored.Unimplemented, "a <- .fastr.java.toArray(1L,,F); a;", getRValue(new int[]{1})); assertEvalFastR(Ignored.Unimplemented, "a <- .fastr.java.toArray(1L,,F); a;", getRValue(new int[]{1}));
} }
@Test
public void testNewArray() {
testNewArray("java.lang.Boolean");
testNewArray("java.lang.Byte");
testNewArray("java.lang.Character");
testNewArray("java.lang.Double");
testNewArray("java.lang.Float");
testNewArray("java.lang.Integer");
testNewArray("java.lang.Long");
testNewArray("java.lang.Short");
testNewArray("java.lang.String");
testNewArray("boolean");
testNewArray("byte");
testNewArray("char");
testNewArray("double");
testNewArray("float");
testNewArray("int");
testNewArray("long");
testNewArray("short");
testNewArray("com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass");
}
public void testNewArray(String className) {
assertEvalFastR("a <- .fastr.java.newArray('" + className + "', 10L); .fastr.interop.isArray(a);", "TRUE");
assertEvalFastR("a <- .fastr.java.newArray('" + className + "', 10L); length(a);", "10L");
assertEvalFastR("a <- .fastr.java.newArray('" + className + "', 10L); .fastr.java.className(a);", toArrayClassName(className, 1));
assertEvalFastR("a <- .fastr.java.newArray('" + className + "', c(2L, 3L)); .fastr.interop.isArray(a);", "TRUE");
assertEvalFastR("a <- .fastr.java.newArray('" + className + "', c(2L, 3L)); length(a);", "2L");
assertEvalFastR("a <- .fastr.java.newArray('" + className + "', c(2L, 3L)); length(a[1]);", "3L");
assertEvalFastR("a <- .fastr.java.newArray('" + className + "', c(2L, 3L)); .fastr.java.className(a);", toArrayClassName(className, 2));
}
@Test
public void testGetClass() {
assertEvalFastR(CREATE_TRUFFLE_OBJECT + ".fastr.java.className(to)", "'com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'");
assertEvalFastR(CREATE_TRUFFLE_OBJECT + ".fastr.java.className(to$methodReturnsNull())", "cat('Error in .fastr.java.className(to$methodReturnsNull()) : unsupported type', '\n')");
assertEvalFastR(".fastr.java.className(NULL)", "cat('Error in .fastr.java.className(NULL) : unsupported type', '\n')");
assertEvalFastR(".fastr.java.className(1)", "cat('Error in .fastr.java.className(1) : unsupported type', '\n')");
}
@Test @Test
public void testFromArray() { public void testFromArray() {
testFromArray("fieldStaticBooleanArray", "logical"); testFromArray("fieldStaticBooleanArray", "logical");
...@@ -764,6 +808,46 @@ public class TestJavaInterop extends TestBase { ...@@ -764,6 +808,46 @@ public class TestJavaInterop extends TestBase {
return ""; return "";
} }
private String toArrayClassName(String className, int dims) {
StringBuilder sb = new StringBuilder();
sb.append("'");
for (int i = 0; i < dims; i++) {
sb.append("[");
}
switch (className) {
case "boolean":
sb.append("Z");
break;
case "byte":
sb.append("B");
break;
case "char":
sb.append("C");
break;
case "double":
sb.append("D");
break;
case "float":
sb.append("F");
break;
case "int":
sb.append("I");
break;
case "long":
sb.append("J");
break;
case "short":
sb.append("S");
break;
default:
sb.append('L');
sb.append(className);
sb.append(';');
}
sb.append('\'');
return sb.toString();
}
public static class TestNamesClass { public static class TestNamesClass {
public Object field; public Object field;
public static Object staticField; public static Object staticField;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment