diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java index 4be0aeba052f8c8ce93e7a755e78b6114aa83f9d..a9e57bb24b883f6227834accc249dae5183ea44c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java @@ -18,7 +18,9 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.access.*; import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.nodes.builtin.base.UseMethodFactory.*; import com.oracle.truffle.r.nodes.control.*; +import com.oracle.truffle.r.nodes.unary.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.*; @@ -48,25 +50,13 @@ public abstract class UseMethod extends RBuiltinNode { controlVisibility(); if (useMethodNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - useMethodNode = insert(new UseMethodUninitializedNode()); - } - return useMethodNode.execute(frame, generic, arg); - } - - private static final class UseMethodUninitializedNode extends UseMethodNode { - @Override - public Object execute(VirtualFrame frame, final String generic, Object obj) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - return specialize(obj).execute(frame, generic, obj); - } - - private UseMethodNode specialize(Object obj) { - CompilerAsserts.neverPartOfCompilation(); - if (obj instanceof RMissing) { - return this.replace(new UseMethodGenericOnlyNode()); + if (arg instanceof RMissing) { + useMethodNode = insert(new UseMethodGenericOnlyNode()); + } else { + useMethodNode = insert(new UseMethodGenericAndObjectNode()); } - return this.replace(new UseMethodGenericAndObjectNode()); } + throw new ReturnException(useMethodNode.execute(frame, generic, arg)); } /* @@ -83,7 +73,7 @@ public abstract class UseMethod extends RBuiltinNode { } Object enclosingArg = RArguments.getArgument(frame, 0); initDispatchedCallNode(generic); - throw new ReturnException(dispatchedCallNode.execute(frame, getClassHierarchy(enclosingArg))); + return dispatchedCallNode.execute(frame, classHierarchyNode.execute(frame, enclosingArg)); } } @@ -92,13 +82,14 @@ public abstract class UseMethod extends RBuiltinNode { @Override public Object execute(VirtualFrame frame, final String generic, Object obj) { initDispatchedCallNode(generic); - throw new ReturnException(dispatchedCallNode.execute(frame, getClassHierarchy(obj))); + return dispatchedCallNode.execute(frame, classHierarchyNode.execute(frame, obj)); } } private abstract static class UseMethodNode extends RNode { @Child protected DispatchedCallNode dispatchedCallNode; + @Child ClassHierarchyNode classHierarchyNode = ClassHierarchyNodeFactory.create(null); protected String lastGenericName; @Override @@ -115,28 +106,41 @@ public abstract class UseMethod extends RBuiltinNode { } } - protected RStringVector getClassHierarchy(Object anObj) { - if (anObj instanceof RAbstractContainer) { - return ((RAbstractContainer) anObj).getClassHierarchy(); - } - if (anObj instanceof Byte) { - return RDataFactory.createStringVector(RRuntime.TYPE_LOGICAL); - } - if (anObj instanceof String) { - return RDataFactory.createStringVector(RRuntime.TYPE_CHARACTER); - } - if (anObj instanceof Integer) { - return RDataFactory.createStringVector(RRuntime.TYPE_INTEGER); - } - if (anObj instanceof Double) { - return RDataFactory.createStringVector(RRuntime.CLASS_DOUBLE, RDataFactory.COMPLETE_VECTOR); - } - if (anObj instanceof RComplex) { - return RDataFactory.createStringVector(RRuntime.TYPE_COMPLEX); - } - throw new AssertionError(); + public abstract Object execute(VirtualFrame frame, final String generic, final Object o); + } + + protected abstract static class ClassHierarchyNode extends UnaryNode { + + public abstract RStringVector execute(VirtualFrame frame, Object arg); + + @Specialization(order = 0) + public RStringVector getClassHr(RAbstractContainer arg) { + return arg.getClassHierarchy(); } - public abstract Object execute(VirtualFrame frame, final String generic, final Object o); + @Specialization + public RStringVector getClassHr(@SuppressWarnings("unused") byte arg) { + return RDataFactory.createStringVector(RRuntime.TYPE_LOGICAL); + } + + @Specialization + public RStringVector getClassHr(@SuppressWarnings("unused") String arg) { + return RDataFactory.createStringVector(RRuntime.TYPE_CHARACTER); + } + + @Specialization + public RStringVector getClassHr(@SuppressWarnings("unused") int arg) { + return RDataFactory.createStringVector(RRuntime.TYPE_INTEGER); + } + + @Specialization + public RStringVector getClassHr(@SuppressWarnings("unused") double arg) { + return RDataFactory.createStringVector(RRuntime.CLASS_DOUBLE, RDataFactory.COMPLETE_VECTOR); + } + + @Specialization + public RStringVector getClassHr(@SuppressWarnings("unused") RComplex arg) { + return RDataFactory.createStringVector(RRuntime.TYPE_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 d766979e4a6636d6186bd0cce12ceb8b67daab4a..11f58623677bf1e01fa1dc0696c2f7505574ccd7 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 @@ -10003,6 +10003,10 @@ f second 1 ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testUseMethodSimple #{f <- function(x){ UseMethod("f",x); };f.first <- function(x){cat("f first",x)};f.second <- function(x){cat("f second",x)};obj <-1;attr(obj,"class") <- "first";f(obj);attr(obj,"class") <- "second";} f first 1 +##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testUseMethodSimple +#{f<-function(x){UseMethod("f")};f.logical<-function(x){print("logical")};f(TRUE)} +[1] "logical" + ##com.oracle.truffle.r.test.simple.TestSimpleBuiltins.testVectorConstructor #{ vector("integer") } integer(0) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java index dc3535b68973d0d1dcb1f0ff23421509f24b640e..609c718e213e19ab7126433d42c860172c492f16 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/all/AllTests.java @@ -12403,6 +12403,11 @@ public class AllTests extends TestBase { assertEval("{f <- function(x){ UseMethod(\"f\",x); };f.first <- function(x){cat(\"f first\",x)};f.second <- function(x){cat(\"f second\",x)};obj <-1;attr(obj,\"class\") <- \"first\";f(obj);attr(obj,\"class\") <- \"second\";}"); } + @Test + public void TestSimpleBuiltins_testUseMethodSimple_24e4b6579385856080f94ac48ee5406f() { + assertEval("{f<-function(x){UseMethod(\"f\")};f.logical<-function(x){print(\"logical\")};f(TRUE)}"); + } + @Test public void TestSimpleBuiltins_testVectorConstructor_629fc5f98d9d6659735740d0b0894210() { assertEval("{ vector() }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java index 42a620ec19910ad5ffa1842ede2fd13924db113c..0c25e086089d35378afdd078ff507dc6e0e04d44 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/TestSimpleBuiltins.java @@ -2586,6 +2586,7 @@ public class TestSimpleBuiltins extends TestBase { // Basic UseMethod assertEval("{f <- function(x){ UseMethod(\"f\",x); };" + "f.first <- function(x){cat(\"f first\",x)};" + "f.second <- function(x){cat(\"f second\",x)};" + "obj <-1;" + "attr(obj,\"class\") <- \"first\";" + "f(obj);" + "attr(obj,\"class\") <- \"second\";}"); + assertEval("{f<-function(x){UseMethod(\"f\")};f.logical<-function(x){print(\"logical\")};f(TRUE)}"); } @Test