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 335338ad4e1d64314b62dfff57eafe05c474f622..e1cc075cb7b0ca5506a25df67b4dc46925e77106 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 @@ -255,6 +255,11 @@ public class FastRInterop { public byte isNull(TruffleObject obj) { return RRuntime.asLogical(ForeignAccess.sendIsNull(node, obj)); } + + @Fallback + public byte isNull(Object obj) { + return RRuntime.asLogical(false); + } } @RBuiltin(name = "is.external.executable", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) @@ -270,6 +275,11 @@ public class FastRInterop { public byte isExecutable(TruffleObject obj) { return RRuntime.asLogical(ForeignAccess.sendIsExecutable(node, obj)); } + + @Fallback + public byte isExecutable(Object obj) { + return RRuntime.asLogical(false); + } } @RBuiltin(name = "as.external.byte", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) 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 ac34216e446012ba1f06857ec4b2c129855479e1..24f399344e17ce51fdbcd358552f47acc586395b 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 @@ -130825,6 +130825,42 @@ Error in eval.external(, "abc", ) : invalid mimeType argument ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport# #if (!any(R.version$engine == "FastR")) { invisible() } else { export('foo', new.env()) } +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable# +#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.executable() } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable# +#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.executable(NULL) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable# +#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.executable(c(1)) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable# +#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.executable(list(1)) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable# +#if (!any(R.version$engine == "FastR")) { TRUE } else { is.external.executable(sum) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalNull# +#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.null() } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalNull# +#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.null(c(1)) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalNull# +#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.null(list(1)) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalNull# +#if (!any(R.version$engine == "FastR")) { TRUE } else { is.external.null(NULL) } +[1] TRUE + ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting# #if (!any(R.version$engine == "FastR")) { c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue') } else { v <- import('testPOJO'); names(v) } [1] "intValue" "longValue" "charValue" "shortValue" "booleanValue" @@ -132901,7 +132937,7 @@ In if (c(T, F)) print("OK") : #if (!any(R.version$engine == "FastR")) { 'abc' } else { tc <- new.java.class('java.lang.String'); t <- new.external(tc, 'abc'); t } [1] "abc" -##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew# +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#Ignored.Unknown# #if (!any(R.version$engine == "FastR")) { 'truffle.object' } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNullClass'); t <- new.external(tc, NULL); class(t) } [1] "truffle.object" @@ -132937,6 +132973,30 @@ In if (c(T, F)) print("OK") : #if (!any(R.version$engine == "FastR")) { TRUE } else { tc <- new.java.class('java/lang/Boolean'); t <- new(tc, TRUE); t } [1] TRUE +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalExecutable# +#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.executable(to$fieldBoolean) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalExecutable# +#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.executable(to) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalExecutable# +#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.executable(to$methodBoolean) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalNull# +#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.null(to$methodReturnsNull) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalNull# +#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.null(to) } +[1] FALSE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalNull# +#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.null(to$methodReturnsNull()) } +[1] TRUE + ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject# #if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.array(to) } [1] FALSE diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java index ea7ba39d215c9b70769ddd65a781c6fafd61bf6a..42a8a05bd16b6282d4ef61e0e1e0f64b30b8caf3 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java @@ -66,6 +66,23 @@ public class TestInterop extends TestBase { assertEvalFastR("export('foo', new.env())", "invisible()"); } + @Test + public void testIsExternalExecutable() { + assertEvalFastR("is.external.executable(sum)", "TRUE"); + assertEvalFastR("is.external.executable(NULL)", "FALSE"); + assertEvalFastR("is.external.executable(c(1))", "FALSE"); + assertEvalFastR("is.external.executable(list(1))", "FALSE"); + assertEvalFastR("is.external.executable()", "FALSE"); + } + + @Test + public void testIsExternalNull() { + assertEvalFastR("is.external.null(NULL)", "TRUE"); + assertEvalFastR("is.external.null(c(1))", "FALSE"); + assertEvalFastR("is.external.null(list(1))", "FALSE"); + assertEvalFastR("is.external.null()", "FALSE"); + } + @Test public void testInteropEvalFile() { assertEvalFastR("fileConn<-file(\"" + TEST_EVAL_FILE + "\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);eval.external(mimeType=\"application/x-r\", path=\"" + diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java index 6ac5634afde57abf29bc2ace4d80fa77dac4f8e5..f54c7aabf0b8f9089112d23b22bc8957e1514924 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java @@ -427,6 +427,20 @@ public class TestJavaInterop extends TestBase { assertEvalFastR(Ignored.ImplementationError, "tc <- new.java.class('" + TestNamesClassMap.class.getName() + "'); to <- new.external(tc); sort(names(to$m()))", "c('one', 'two')"); } + @Test + public void testIsExternalExecutable() { + assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.executable(to)", "FALSE"); + assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.executable(to$methodBoolean)", "TRUE"); + assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.executable(to$fieldBoolean)", "FALSE"); + } + + @Test + public void testIsExternalNull() { + assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.null(to)", "FALSE"); + assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.null(to$methodReturnsNull)", "FALSE"); + assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.null(to$methodReturnsNull())", "TRUE"); + } + @Test public void testIsXXXForForeignObject() { // missing: is.element, is.empty.model, is.leaf, is.loaded, is.na.data.frame, diff --git a/documentation/tutorials/interop/javaInteroperability.md b/documentation/tutorials/interop/javaInteroperability.md index 6db39953a2f67355bdf6a142b1e53ef770c1e461..4cbd543c431a3ddea9e796af49324c115dc66421 100644 --- a/documentation/tutorials/interop/javaInteroperability.md +++ b/documentation/tutorials/interop/javaInteroperability.md @@ -15,12 +15,12 @@ All following examples are meant to be executed in the R Console, no additional # Working with Java Classes and Objects ## Create a Java Class -By providing the fully qualified class name to he `new.java.class` function. +By providing the fully qualified class name to the `new.java.class` function. ``` > calendarClass <- new.java.class('java.util.GregorianCalendar') ``` -(Every requested class has to be on FastR`s classpath. Java JDK classes, like GregorianCalendar used above, work our of the box.) +(Every requested class has to be on FastR`s classpath. Java JDK classes, like GregorianCalendar used above, work out of the box.) The returned value is an external object representing a Java Class. @@ -30,12 +30,19 @@ By providing an external object representig a Java class to the `new.external` f > calendar <- new.external(calendarClass) ``` -in addition to the class it is also possible pass over additional constructor arguments +In addition to the class it is also possible to pass over additional constructor arguments. ``` > calendar <- new.external(calendarClass, year=2042L, moth=3L, day=1L) ``` +And apart from the interop builtins, the `new` function can be used as well. + +``` +calendar <- new("java.util.GregorianCalendar") +calendar <- new("java.util.GregorianCalendar", year=2042L, moth=3L, day=1L) +``` + ## Accessing Fields and Methods Access to static and instance fields and methods is provided by the `$` and `[` operators. @@ -51,7 +58,7 @@ Access to static and instance fields and methods is provided by the `$` and `[` > calendar$setTime(currentTime) ``` -External objects returned from a field, method or created via `new.external` are either automatically converted into according R values or they live on as external objects in the FastR environment. If necessary, they can be again passed over to java. +External objects returned from a field, method or created via `new` or `new.external` are either automatically converted into according R values or they live on as external objects in the FastR environment. If necessary, they can be passed over to java. ``` > cet <- new.java.class("java.util.TimeZone")$getTimeZone("CET") @@ -79,7 +86,7 @@ also > interopShort <- as.external.short(1) ``` -R integer values map directly to Java int/Integer, R numeric to Java double/Double, R logical to Java boolean/Boolean and R character to Java String. +R `integer` values map directly to Java `int`/`Integer`, R `numeric` to Java `double`/`Double`, R `logical` to Java `boolean`/`Boolean` and R `character` to Java `String`. ### Inspecting external objects The `names` function can be used to obtain a list of instance and static members from an external Java Object or Java Class. @@ -132,7 +139,7 @@ The resulting array component type is either automatically given by the accordin ``` ### Converting Java Arrays to R objects -Unlike Java primitives or their wrappers, java arrays aren't on access automatically converted into a R vector or list of the according type. Nevertheless, when appropriate they can be handled by FastR builtin functions the same way as native R objects. +Unlike Java primitives or their wrappers, java arrays aren't on access automatically converted into a R vector. Nevertheless, when appropriate they can be handled by FastR builtin functions the same way as native R objects. ``` > sapply(intArray, function(e) { e }) > length(stringArray) @@ -145,7 +152,7 @@ By providing a Java Array to the `as.vector` function. > intVec <- as.vector(intArray) ``` -Arrays where the component type is a Java primitive, a primitive wrapper or String are converted into a R vector of an according R data type, otherwise a list containing the array elements is created. +Arrays where the component type is a Java primitive, a primitive wrapper or String are converted into a R vector, otherwise a list containing the array elements is created. See also ```