diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index 9fbc99886e15a80afb408dab067cabdf1ea63e59..8ea54305d44ca160b38b920c4a3218e829220f40 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -85,6 +85,7 @@ import com.oracle.truffle.r.runtime.VirtualEvalFrame; import com.oracle.truffle.r.runtime.context.Engine; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RFunction; @@ -99,6 +100,7 @@ import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -594,13 +596,19 @@ final class REngine implements Engine, Engine.Timings { result = RRuntime.asAbstractVector(result); if (result instanceof RTypedValue || result instanceof TruffleObject) { Object resultValue = evaluatePromise(result); - Object printMethod = REnvironment.globalEnv().findFunction("print"); - RFunction function = (RFunction) evaluatePromise(printMethod); if (resultValue instanceof RShareable && !((RShareable) resultValue).isSharedPermanent()) { ((RShareable) resultValue).incRefCount(); } MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame(); - CallRFunctionNode.executeSlowpath(function, RCaller.createInvalid(callingFrame), callingFrame, new Object[]{resultValue, RMissing.instance}, null); + if (result instanceof RAttributable && ((RAttributable) result).isS4()) { + Object printMethod = REnvironment.getRegisteredNamespace("methods").get("show"); + RFunction function = (RFunction) evaluatePromise(printMethod); + CallRFunctionNode.executeSlowpath(function, RCaller.createInvalid(callingFrame), callingFrame, new Object[]{resultValue}, null); + } else { + Object printMethod = REnvironment.globalEnv().findFunction("print"); + RFunction function = (RFunction) evaluatePromise(printMethod); + CallRFunctionNode.executeSlowpath(function, RCaller.createInvalid(callingFrame), callingFrame, new Object[]{resultValue, RMissing.instance}, null); + } if (resultValue instanceof RShareable && !((RShareable) resultValue).isSharedPermanent()) { ((RShareable) resultValue).decRefCount(); } @@ -610,6 +618,27 @@ final class REngine implements Engine, Engine.Timings { } } + /* + * This abstracts the calling convention, etc. behind the RASTBuilder, but creating large + * amounts of CallTargets during testing is too much overhead at the moment. + */ + @SuppressWarnings("unused") + private void printAlternative(Object result) { + Object printFunction; + if (result instanceof RAttributable && ((RAttributable) result).isS4()) { + printFunction = REnvironment.getRegisteredNamespace("methods").get("show"); + } else { + printFunction = REnvironment.getRegisteredNamespace("base").get("print"); + } + RFunction function = (RFunction) evaluatePromise(printFunction); + + MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame(); + // create a piece of AST to perform the call + RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder(); + RSyntaxNode call = builder.call(RSyntaxNode.LAZY_DEPARSE, builder.constant(RSyntaxNode.LAZY_DEPARSE, function), builder.constant(RSyntaxNode.LAZY_DEPARSE, result)); + doMakeCallTarget(call.asRNode(), RSource.Internal.EVAL_WRAPPER.string, false, false).call(callingFrame); + } + private static String toString(Object originalResult) { Object result = evaluatePromise(originalResult); result = RRuntime.asAbstractVector(result); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java index eeb9eae3cee9a745ea131db97efcf185b99ab545..6e97897494f4ef361aa6fb24f55a7d6abcbcaa7e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java @@ -43,8 +43,7 @@ public class TestBuiltin_setS4Object extends TestBase { @Test public void testsetS4Object5() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c('nonStructure', 'ANY', 'ANY', 'ANY'), .Names = c(NA_character_, NA_character_, NA_character_, NA_character_), package = character(0), class = structure('signature', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval("argv <- list(structure(c('nonStructure', 'ANY', 'ANY', 'ANY'), .Names = c(NA_character_, NA_character_, NA_character_, NA_character_), package = character(0), class = structure('signature', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java index 20799e15560ddbacd8e4ba9d6909ade207729891..83b5944db3f68f4e5f3b6946121656056a36ab44 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestMiscBuiltins.java @@ -144,19 +144,14 @@ public class TestMiscBuiltins extends TestBase { assertEval("{ m <- { matrix( as.raw(11:16), nrow=2 ) } ; diag(m) <- c(as.raw(1),as.raw(2)) ; m }"); } - //@formatter:off private static final String[] BASIC_TYPES = new String[]{ - "call", "character", "complex", "double", "expression", "function", "integer", "list", - "logical", "name", "symbol", "null", "pairlist", "raw", + "call", "character", "complex", "double", "expression", "function", "integer", "list", "logical", "name", "symbol", "null", "pairlist", "raw", }; private static final String[] BASIC_TYPE_VALUES = new String[]{ - "call(\"foo\")", "\"1\"", "1i", "1", "expression(x + 1)", "function() { }", - "1L", "list()", "TRUE", "quote(x)", "NULL", "pairlist()", "raw()" + "call(\"foo\")", "\"1\"", "1i", "1", "expression(x + 1)", "function() { }", "1L", "list()", "TRUE", "quote(x)", "NULL", "pairlist()", "raw()" }; - //@formatter:on - @Test public void testBasicTypes() { // cross-product of all basic types and values