diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java index 075d0dbb0345c8a8fbb981fac42b4732aa436adb..501d4a283f10f8a9cddbee1d34879ff4cc9c8de8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java @@ -31,7 +31,9 @@ import java.util.function.IntPredicate; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Fallback; +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.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -53,6 +55,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public class IsFiniteFunctions { + @ImportStatic(RRuntime.class) public abstract static class Adapter extends RBuiltinNode.Arg1 { @Child private GetDimAttributeNode getDims = GetDimAttributeNode.create(); @@ -83,6 +86,12 @@ public class IsFiniteFunctions { return doFunConstant(x, RRuntime.LOGICAL_FALSE); } + @Specialization(guards = "isForeignObject(obj)") + @TruffleBoundary + protected byte doIsForeign(@SuppressWarnings("unused") TruffleObject obj) { + throw error(RError.Message.DEFAULT_METHOD_NOT_IMPLEMENTED_FOR_TYPE, "external object"); + } + @Fallback @TruffleBoundary protected Object doIsFiniteOther(Object x) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java index c08de1b1f10abdba38904bb6e90c461d64b64727..166728e6642771dc131f3944539d2638e4ad2bc0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java @@ -29,7 +29,9 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Fallback; +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.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode; @@ -53,6 +55,7 @@ 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.RAbstractVector; +@ImportStatic(RRuntime.class) @RBuiltin(name = "is.na", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE) public abstract class IsNA extends RBuiltinNode.Arg1 { @@ -195,6 +198,11 @@ public abstract class IsNA extends RBuiltinNode.Arg1 { return RDataFactory.createEmptyLogicalVector(); } + @Specialization(guards = "isForeignObject(obj)") + protected byte isNA(@SuppressWarnings("unused") TruffleObject obj) { + return RRuntime.LOGICAL_FALSE; + } + // Note: all the primitive values have specialization, so we can only get RTypedValue in // fallback @Fallback diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java index 74152f23bf2199922819321a77e4e70350476f6c..f966c9ab3c357134731cfa5fa331f6379f3c94ce 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java @@ -31,7 +31,9 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; +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.api.object.DynamicObject; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode; @@ -100,6 +102,7 @@ public class IsTypeFunctions { } } + @ImportStatic(RRuntime.class) @RBuiltin(name = "is.recursive", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) public abstract static class IsRecursive extends MissingAdapter { @@ -126,6 +129,11 @@ public class IsTypeFunctions { return arg instanceof RListBase; } + @Specialization(guards = "isForeignObject(obj)") + protected byte isRecursive(@SuppressWarnings("unused") TruffleObject obj) { + return RRuntime.LOGICAL_FALSE; + } + @Fallback protected byte isRecursiveFallback(@SuppressWarnings("unused") Object value) { return RRuntime.LOGICAL_TRUE; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java index 1df443ba8c97ea0df8b9b11c2f42a9540d0b1608..c2e606b1f73a542fce854d221e417ee5848b8d36 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java @@ -62,6 +62,11 @@ public abstract class TypeofNode extends UnaryNode { return RType.Missing; } + @Specialization(guards = "isForeignObject(object)") + protected RType doTruffleObject(@SuppressWarnings("unused") TruffleObject object) { + return RType.TruffleObject; + } + @Specialization(guards = {"operand.getClass() == cachedClass"}, limit = "NUMBER_OF_CACHED_CLASSES") protected static RType doCachedTyped(Object operand, @Cached("getTypedValueClass(operand)") Class<? extends RTypedValue> cachedClass) { @@ -82,11 +87,6 @@ public abstract class TypeofNode extends UnaryNode { return operand.getRType(); } - @Specialization(guards = "isForeignObject(object)") - protected RType doTruffleObject(@SuppressWarnings("unused") TruffleObject object) { - return RType.TruffleObject; - } - protected static boolean isForeignObject(Object obj) { return RRuntime.isForeignObject(obj); } 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 f9852832d2f60e5024c9e54cda373f4d034e6794..dd2d584e5b43bf6515adab3e789d6798ae427c13 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 @@ -329,7 +329,7 @@ public class TestJavaInterop extends TestBase { } @Test - public void testNamesForJavaObject() { + public void testNamesForForeignObject() { assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassNoMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL"); assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassNoPublicMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL"); assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); sort(names(tc))", "c('staticField', 'staticMethod')"); @@ -340,6 +340,63 @@ public class TestJavaInterop extends TestBase { assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassMap.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t$m()))", "c('one', 'two')"); } + @Test + public void testIsXXXForForeignObject() { + // missing: is.element, is.empty.model, is.leaf, is.loaded, is.na.data.frame, + // is.na.numeric_version, is.na.POSIXlt + + assertPassingForeighObjectToFunction("is.array", "FALSE"); + assertPassingForeighObjectToFunction("is.atomic", "FALSE"); + assertPassingForeighObjectToFunction("is.call", "FALSE"); + assertPassingForeighObjectToFunction("is.character", "FALSE"); + assertPassingForeighObjectToFunction("is.complex", "FALSE"); + assertPassingForeighObjectToFunction("is.data.frame", "FALSE"); + assertPassingForeighObjectToFunction("is.double", "FALSE"); + assertPassingForeighObjectToFunction("is.environment", "FALSE"); + assertPassingForeighObjectToFunction("is.expression", "FALSE"); + assertPassingForeighObjectToFunction("is.factor", "FALSE"); + assertPassingForeighObjectToFunction("is.function", "FALSE"); + assertPassingForeighObjectToFunction("is.integer", "FALSE"); + assertPassingForeighObjectToFunction("is.language", "FALSE"); + assertPassingForeighObjectToFunction("is.logical", "FALSE"); + assertPassingForeighObjectToFunction("is.matrix", "FALSE"); + assertPassingForeighObjectToFunction("is.mts", "FALSE"); + assertPassingForeighObjectToFunction("is.na", "FALSE"); + assertPassingForeighObjectToFunction("is.name", "FALSE"); + assertPassingForeighObjectToFunction("is.null", "FALSE"); + assertPassingForeighObjectToFunction("is.numeric", "FALSE"); + assertPassingForeighObjectToFunction("is.numeric.Date", "FALSE"); + assertPassingForeighObjectToFunction("is.numeric.difftime", "FALSE"); + assertPassingForeighObjectToFunction("is.numeric.POSIXt", "FALSE"); + assertPassingForeighObjectToFunction("is.numeric_version", "FALSE"); + assertPassingForeighObjectToFunction("is.object", "FALSE"); + assertPassingForeighObjectToFunction("is.ordered", "FALSE"); + assertPassingForeighObjectToFunction("is.package_version", "FALSE"); + assertPassingForeighObjectToFunction("is.pairlist", "FALSE"); + assertPassingForeighObjectToFunction("is.primitive", "FALSE"); + assertPassingForeighObjectToFunction("is.qr", "FALSE"); + assertPassingForeighObjectToFunction("is.raster", "FALSE"); + assertPassingForeighObjectToFunction("is.raw", "FALSE"); + assertPassingForeighObjectToFunction("is.recursive", "FALSE"); + assertPassingForeighObjectToFunction("is.relistable", "FALSE"); + assertPassingForeighObjectToFunction("is.stepfun", "FALSE"); + assertPassingForeighObjectToFunction("is.symbol", "FALSE"); + assertPassingForeighObjectToFunction("is.table", "FALSE"); + assertPassingForeighObjectToFunction("is.ts", "FALSE"); + assertPassingForeighObjectToFunction("is.tskernel", "FALSE"); + assertPassingForeighObjectToFunction("is.unsorted", "FALSE"); + assertPassingForeighObjectToFunction("is.vector", "FALSE"); + + assertPassingForeighObjectToFunction("is.nan", "cat('Error in is.nan(to) : ', '\n', ' default method not implemented for type \\'external object\\'\n', sep='')"); + assertPassingForeighObjectToFunction("is.finite", "cat('Error in is.finite(to) : ', '\n', ' default method not implemented for type \\'external object\\'\n', sep='')"); + assertPassingForeighObjectToFunction("is.infinite", "cat('Error in is.infinite(to) : ', '\n', ' default method not implemented for type \\'external object\\'\n', sep='')"); + + } + + private void assertPassingForeighObjectToFunction(String function, String expectedOutput) { + assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); " + function + "(to)", expectedOutput); + } + @Test public void testAttributes() { assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); attributes(to)", "NULL");