diff --git a/ci.hocon b/ci.hocon index 9e85b47df51380e4d3737037c9d54df84d1f5a1d..5c04f82cf99d06dc864f4b1ae2ae87a4c3721224 100644 --- a/ci.hocon +++ b/ci.hocon @@ -7,6 +7,7 @@ java7 : {name : oraclejdk, version : "7", platformspecific: true} # java 8 must be a jvmci enabled variant java8 : {name : labsjdk, version : "8-jvmci-latest", platformspecific: true} +java9 : {name : labsjdk, version : "9-ea+168", platformspecific: true} java8Downloads : { downloads : { @@ -17,6 +18,16 @@ java8Downloads : { } } +java9Downloads : { + downloads : { + EXTRA_JAVA_HOMES : { pathlist :[ + ${java7} + ${java8} + ]} + JAVA_HOME : ${java9} + } +} + logfiles : [ "fastr_errors.log" "results.json" @@ -123,6 +134,12 @@ gateTestManagedLinux: ${common} { ] } +gateTestJava9Linux : ${java9Downloads} ${gateTestCommon} { + downloads : { + JAVA_HOME : ${java9Downloads.downloads.JAVA_HOME} + EXTRA_JAVA_HOMES : ${java9Downloads.downloads.EXTRA_JAVA_HOMES} + } +} # This performs a number of "style" checks on the code to ensure it confirms to the project standards. @@ -171,4 +188,5 @@ builds = [ ${rbcheck} {capabilities : [linux, amd64], targets : [gate], name: "gate-rbcheck-linux-amd64"} ${internalPkgtest} {capabilities : [linux, amd64], targets : [gate], name: "gate-internal-pkgtest-linux-amd64"} ${gateTestManagedLinux} {capabilities : [linux, amd64, fast], targets : [gate], name: "gate-test-managed-linux-amd64"} + ${gateTestJava9Linux} {capabilities : [linux, amd64, fast], targets : [gate], name: "gate-test-java9-linux-amd64"} ] 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 a1027bfdc9013d56578f9aab0f743c2c6e10bd77..49bbcb8c54d4552a613aba0b86ca1a448fe35f6e 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 @@ -390,7 +390,7 @@ final class REngine implements Engine, Engine.Timings { } lastValue = calls[i].call(new Object[]{executionFrame != null ? executionFrame : newContext.stateREnvironment.getGlobalFrame()}); } - return lastValue; + return RRuntime.r2Java(lastValue); } catch (ReturnException ex) { return ex.getResult(); } catch (DebugExitException | JumpToTopLevelException | ExitException | ThreadDeath e) { diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java index ed08560e6b131206d1d416026031cdf0a9c24215..7c242944350bfebdceda6e44619e119485e7d8c3 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java @@ -438,7 +438,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { // This checks for the specific structure of replacements RLanguage replacement = ReplacementDispatchNode.getRLanguage(rl); RLanguage elem = replacement == null ? rl : replacement; - String string = RDeparse.deparse(elem, RDeparse.DEFAULT_Cutoff, true, RDeparse.KEEPINTEGER, -1); + String string = RDeparse.deparse(elem, RDeparse.DEFAULT_CUTOFF, true, RDeparse.KEEPINTEGER, -1); return string.split("\n")[0]; } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java index ee9a96bf866b4d36ef569b37630685bcfd81a6af..7a858d921322dde03302073b288e8218cebf7a06 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java @@ -148,7 +148,7 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> implements return (String) unwrapped; } if (unwrapped instanceof RTypedValue) { - return RDeparse.deparse(unwrapped); + return RDeparse.deparse(unwrapped, RDeparse.MAX_CUTOFF, true, RDeparse.KEEPINTEGER, -1, 1024 * 1024); } return RRuntime.toString(unwrapped); } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REmptyMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REmptyMR.java new file mode 100644 index 0000000000000000000000000000000000000000..99277bbbcfbee60a210c5d0eacf8c530faa4dae0 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REmptyMR.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.engine.interop; + +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.Resolve; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.runtime.data.REmpty; + +@MessageResolution(receiverType = REmpty.class, language = TruffleRLanguage.class) +public class REmptyMR { + + @Resolve(message = "IS_BOXED") + public abstract static class REmptyIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") REmpty receiver) { + return false; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class REmptyHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") REmpty receiver) { + return false; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class REmptyIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") REmpty receiver) { + return false; + } + } + + @CanResolve + public abstract static class REmptyCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof REmpty; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java index 9082fefc169f2c968b3d4eb6e6b27411e2ed162c..fa203c367ab06940717e8f66f02b92fb8910150b 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java @@ -29,22 +29,24 @@ import com.oracle.truffle.api.interop.MessageResolution; import com.oracle.truffle.r.engine.TruffleRLanguage; import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base; import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE; -import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_UpCallsRFFIImpl; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RForeignAccessFactory; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDouble; +import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RInteger; +import com.oracle.truffle.r.runtime.data.RInteropScalar; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTruffleObject; import com.oracle.truffle.r.runtime.data.RUnboundValue; @@ -125,6 +127,12 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory { return RLanguageMRForeign.ACCESS; } else if (obj instanceof ActiveBinding) { return ActiveBindingMRForeign.ACCESS; + } else if (obj instanceof RInteropScalar) { + return RInteropScalarMRForeign.ACCESS; + } else if (obj instanceof RMissing) { + return RMissingMRForeign.ACCESS; + } else if (obj instanceof REmpty) { + return REmptyMRForeign.ACCESS; } else { if (obj instanceof RAbstractVector) { diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropScalarMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropScalarMR.java new file mode 100644 index 0000000000000000000000000000000000000000..d904aa2171893fb5433e80805af01b2c8eff4291 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropScalarMR.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.engine.interop; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.Resolve; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.RInteropScalar; + +@MessageResolution(receiverType = RInteropScalar.class) +public class RInteropScalarMR { + + @Resolve(message = "IS_BOXED") + public abstract static class RInteropScalarIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") RInteropScalar receiver) { + return true; + } + } + + @Resolve(message = "UNBOX") + public abstract static class RInteropScalarUnboxNode extends Node { + private final ValueProfile classProfile = ValueProfile.createClassProfile(); + + protected Object access(RInteropScalar receiver) { + RInteropScalar t = classProfile.profile(receiver); + if (t instanceof RInteropScalar.RInteropByte) { + return ((RInteropScalar.RInteropByte) t).getValue(); + } else if (t instanceof RInteropScalar.RInteropChar) { + return ((RInteropScalar.RInteropChar) t).getValue(); + } else if (t instanceof RInteropScalar.RInteropFloat) { + return ((RInteropScalar.RInteropFloat) t).getValue(); + } else if (t instanceof RInteropScalar.RInteropLong) { + return ((RInteropScalar.RInteropLong) t).getValue(); + } else if (t instanceof RInteropScalar.RInteropShort) { + return ((RInteropScalar.RInteropShort) t).getValue(); + } + throw RInternalError.unimplemented("missing RInteropScalar : " + receiver.getClass().getName()); + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class RInteropScalarHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") RInteropScalar receiver) { + return false; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class RInteropScalarIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") RInteropScalar receiver) { + return false; + } + } + + @CanResolve + public abstract static class RInteropScalarCheck extends Node { + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RInteropScalar; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RMissingMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RMissingMR.java new file mode 100644 index 0000000000000000000000000000000000000000..656843ed0c421fa4281d00467a90ca850a28203d --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RMissingMR.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.engine.interop; + +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.Resolve; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.runtime.data.RMissing; + +@MessageResolution(receiverType = RMissing.class, language = TruffleRLanguage.class) +public class RMissingMR { + + @Resolve(message = "IS_BOXED") + public abstract static class RMissingIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") RMissing receiver) { + return false; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class RMissingHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") RMissing receiver) { + return false; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class RMissingIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") RMissing receiver) { + return false; + } + } + + @CanResolve + public abstract static class RMissingCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RMissing; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java index cc668a856e86c2abd0db1876c3b47278f2739e20..c47155062d8634fd1b9d7b965304af8a6ccc7779 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java @@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; * have be lazy about that. * */ -public class EmbeddedConsoleHandler implements ConsoleHandler { +public class EmbeddedConsoleHandler extends ConsoleHandler { private final RStartParams startParams; /** diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java index 2c18397bf7f432a3a4d80572fef3d634c022cdb6..eaeeb329ea451ca404e91fe0c99f69592298e2e8 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java @@ -22,20 +22,23 @@ */ package com.oracle.truffle.r.engine.shell; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.context.ConsoleHandler; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.RCloseable; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; + import jline.console.completer.Completer; public class JLineConsoleCompleter implements Completer { @@ -64,50 +67,54 @@ public class JLineConsoleCompleter implements Completer { return cursor; } - private static int completeImpl(String buffer, int cursor, List<CharSequence> candidates) { + @SuppressWarnings("try") + private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) { if (buffer.isEmpty()) { return cursor; } - REnvironment utils = REnvironment.getRegisteredNamespace("utils"); - Object o = utils.get(".completeToken"); - if (o instanceof RPromise) { - o = PromiseHelperNode.evaluateSlowPath(null, (RPromise) o); - } - RFunction completeToken; - if (o instanceof RFunction) { - completeToken = (RFunction) o; - } else { - return cursor; - } + try (RCloseable c = RContext.withinContext(console.getContext())) { - o = utils.get(".CompletionEnv"); - if (!(o instanceof RPromise)) { - return cursor; - } - REnvironment env = (REnvironment) PromiseHelperNode.evaluateSlowPath(null, (RPromise) o); - int start = getStart(buffer, env, cursor); - env.safePut("start", start); - env.safePut("end", cursor); - env.safePut("linebuffer", buffer); - env.safePut("token", buffer.substring(start, cursor)); - - MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame(); - RContext.getEngine().evalFunction(completeToken, callingFrame, RCaller.createInvalid(callingFrame), null, new Object[]{}); - - o = env.get("comps"); - if (!(o instanceof RAbstractStringVector)) { - return cursor; - } + REnvironment utils = REnvironment.getRegisteredNamespace("utils"); + Object o = utils.get(".completeToken"); + if (o instanceof RPromise) { + o = PromiseHelperNode.evaluateSlowPath(null, (RPromise) o); + } + RFunction completeToken; + if (o instanceof RFunction) { + completeToken = (RFunction) o; + } else { + return cursor; + } + + o = utils.get(".CompletionEnv"); + if (!(o instanceof RPromise)) { + return cursor; + } + REnvironment env = (REnvironment) PromiseHelperNode.evaluateSlowPath(null, (RPromise) o); + int start = getStart(buffer, env, cursor); + env.safePut("start", start); + env.safePut("end", cursor); + env.safePut("linebuffer", buffer); + env.safePut("token", buffer.substring(start, cursor)); + + MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame(); + RContext.getEngine().evalFunction(completeToken, callingFrame, RCaller.createInvalid(callingFrame), null, new Object[]{}); + + o = env.get("comps"); + if (!(o instanceof RAbstractStringVector)) { + return cursor; + } - RAbstractStringVector comps = (RAbstractStringVector) o; - List<String> ret = new ArrayList<>(comps.getLength()); - for (int i = 0; i < comps.getLength(); i++) { - ret.add(comps.getDataAt(i)); + RAbstractStringVector comps = (RAbstractStringVector) o; + List<String> ret = new ArrayList<>(comps.getLength()); + for (int i = 0; i < comps.getLength(); i++) { + ret.add(comps.getDataAt(i)); + } + Collections.sort(ret, String.CASE_INSENSITIVE_ORDER); + candidates.addAll(ret); + return start; } - Collections.sort(ret, String.CASE_INSENSITIVE_ORDER); - candidates.addAll(ret); - return start; } private static int getStart(String buffer, REnvironment env, int cursor) { diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java index 18ced0d667c767e10df4217d3bdd630da2cbb77e..6353be6e9a9fc9199ef8dea6a3744c386a8f8908 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java @@ -39,7 +39,7 @@ import jline.console.UserInterruptException; import jline.console.history.FileHistory; import jline.console.history.History; -class JLineConsoleHandler implements ConsoleHandler { +class JLineConsoleHandler extends ConsoleHandler { private final ConsoleReader console; private final boolean isInteractive; private final PrintWriter printWriter; diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java index 9f159f813512fb6ae93d57a02795069172011266..0f98a4dbcbd93f27024760beeb60afca1f0b1afe 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java @@ -54,11 +54,13 @@ import com.oracle.truffle.r.runtime.Utils.DebugExitException; import com.oracle.truffle.r.runtime.context.ConsoleHandler; import com.oracle.truffle.r.runtime.context.ContextInfo; import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler; +import com.oracle.truffle.r.runtime.context.Engine; import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException; import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.ContextKind; import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RStringVector; import jline.console.UserInterruptException; @@ -190,6 +192,7 @@ public class RCommand { private static final Source GET_ECHO = RSource.fromTextInternal("invisible(getOption('echo'))", RSource.Internal.GET_ECHO); private static final Source QUIT_EOF = RSource.fromTextInternal("quit(\"default\", 0L, TRUE)", RSource.Internal.QUIT_EOF); + private static final Source GET_CONTINUE_PROMPT = RSource.fromTextInternal("invisible(getOption('continue'))", RSource.Internal.GET_CONTINUE_PROMPT); /** * The read-eval-print loop, which can take input from a console, command line expression or a @@ -221,10 +224,10 @@ public class RCommand { continue; } - String continuePrompt = getContinuePrompt(); + String continuePrompt = getContinuePrompt(vm); StringBuffer sb = new StringBuffer(input); Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT); - boolean hasExecutor = RContext.getInstance().hasExecutor(); + boolean hasExecutor = hasExectuor(vm); while (true) { lastStatus = 0; try { @@ -308,7 +311,9 @@ public class RCommand { private static boolean doEcho(PolyglotEngine vm) { PolyglotEngine.Value echoValue = vm.eval(GET_ECHO); Object echo = echoValue.get(); - if (echo instanceof TruffleObject) { + if (echo instanceof Boolean) { + return (boolean) echo; + } else if (echo instanceof TruffleObject) { RLogicalVector echoVec = echoValue.as(RLogicalVector.class); return RRuntime.fromLogical(echoVec.getDataAt(0)); } else if (echo instanceof Byte) { @@ -318,7 +323,21 @@ public class RCommand { } } - private static String getContinuePrompt() { - return RRuntime.asString(RRuntime.asAbstractVector(RContext.getInstance().stateROptions.getValue("continue"))); + private static String getContinuePrompt(PolyglotEngine vm) { + PolyglotEngine.Value echoValue = vm.eval(GET_CONTINUE_PROMPT); + Object echo = echoValue.get(); + if (echo instanceof String) { + return (String) echo; + } else if (echo instanceof TruffleObject) { + RStringVector promptVec = echoValue.as(RStringVector.class); + return promptVec.getDataAt(0); + } else { + throw RInternalError.shouldNotReachHere(); + } } + + private static boolean hasExectuor(PolyglotEngine vm) { + return vm.eval(Engine.GET_CONTEXT).as(RContext.class).hasExecutor(); + } + } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java index 51af0bead26b43b0fa393bd666900a01a7a1fcc2..271b69345df92e9297e4d81391d5fece14eff410 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java @@ -28,13 +28,15 @@ import java.util.List; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.context.ConsoleHandler; +import com.oracle.truffle.r.runtime.context.RContext; -class StringConsoleHandler implements ConsoleHandler { +class StringConsoleHandler extends ConsoleHandler { private final PrintStream output; private final List<String> lines; private final String inputDescription; private String prompt; private int currentLine; + private RContext ctx; StringConsoleHandler(List<String> lines, OutputStream output, String inputDescription) { this.lines = lines; @@ -103,4 +105,14 @@ class StringConsoleHandler implements ConsoleHandler { public String getInputDescription() { return inputDescription; } + + @Override + public void setContext(RContext ctx) { + this.ctx = ctx; + } + + @Override + public RContext getContext() { + return ctx; + } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java index 1f297581c409dd3eb1c7e4bf0c1f3cf691fefcd5..016b8d9e98c8d7a83c1ede405b736cd431eb03d5 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java @@ -25,6 +25,8 @@ package com.oracle.truffle.r.library.fastrGrid; import com.oracle.truffle.r.library.fastrGrid.DisplayList.LGetDisplayListElement; import com.oracle.truffle.r.library.fastrGrid.DisplayList.LInitDisplayList; import com.oracle.truffle.r.library.fastrGrid.DisplayList.LSetDisplayListOn; +import com.oracle.truffle.r.library.fastrGrid.PaletteExternals.CPalette; +import com.oracle.truffle.r.library.fastrGrid.PaletteExternals.CPalette2; import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCairo; import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCurr; import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush; @@ -75,6 +77,10 @@ public final class FastRGridExternalLookup { return SavePlot.create(); case "X11": return new InitWindowedDevice(); + case "palette": + return CPalette.create(); + case "palette2": + return CPalette2.create(); default: return null; } @@ -94,6 +100,8 @@ public final class FastRGridExternalLookup { return LValidUnit.create(); case "L_pretty": return LPretty.create(); + case "L_stringMetric": + return LStringMetric.create(); // Viewport management case "L_upviewport": diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java index f826ccd696f2f509374b4b9c2b072fa9ab75957c..48e5ca2d58fcd3da897908e0acc74003041ee96d 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java @@ -18,6 +18,7 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod; import java.util.Arrays; import java.util.function.Function; +import com.oracle.truffle.r.library.fastrGrid.GridState.GridPalette; import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext; import com.oracle.truffle.r.library.fastrGrid.device.DrawingContextDefaults; import com.oracle.truffle.r.library.fastrGrid.device.GridColor; @@ -25,6 +26,7 @@ import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; @@ -264,7 +266,22 @@ public final class GPar { } private GridColor getGridColor(int listIndex) { - GridColor color = GridColorUtils.gridColorFromString(GridUtils.asString(data[listIndex], index)); + Object value = data[listIndex]; + GridColor color = getPaletteColor(value); + if (color != null) { + return color; + } + + String strValue = null; + if (value instanceof String) { + strValue = (String) value; + } else if (value instanceof RAbstractStringVector && ((RAbstractStringVector) value).getLength() > 0) { + strValue = ((RAbstractStringVector) value).getDataAt(index % ((RAbstractStringVector) value).getLength()); + } else { + return GridColor.TRANSPARENT; + } + + color = GridColorUtils.gridColorFromString(strValue); double alpha = asDouble(data[GP_ALPHA], index); if (alpha != 1.) { int newAlpha = Math.min(255, (int) (alpha * ((color.getAlpha() / 255.0) * 255))); @@ -274,6 +291,44 @@ public final class GPar { } } + private GridColor getPaletteColor(Object colorIdIn) { + Object colorId = colorIdIn; + if (colorId instanceof RAbstractVector) { + RAbstractVector vec = (RAbstractVector) colorId; + colorId = vec.getDataAtAsObject(index % vec.getLength()); + } + int paletteIdx = RRuntime.INT_NA; + if (colorId instanceof Integer) { + paletteIdx = (int) colorId; + } else if (colorId instanceof Double && !RRuntime.isNA((Double) colorId)) { + paletteIdx = (int) (double) colorId; + } else if (colorId instanceof String && !RRuntime.isNA((String) colorId)) { + paletteIdx = paletteIdxFromString((String) colorId); + } else if (colorId instanceof Byte && !RRuntime.isNA((byte) colorId)) { + paletteIdx = (int) (byte) colorId; + } + if (RRuntime.isNA(paletteIdx)) { + return null; + } + if (paletteIdx < 0) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, Utils.stringFormat("numerical color values must be >= 0, found %d", paletteIdx)); + } + if (paletteIdx == 0) { + return GridColor.TRANSPARENT; + } + GridPalette palette = GridContext.getContext().getGridState().getPalette(); + GridColor result = palette.colors[(paletteIdx - 1) % palette.colors.length]; + return result; // one based index + } + + private int paletteIdxFromString(String colorId) { + try { + return Integer.parseInt(colorId, 10); + } catch (NumberFormatException ex) { + return RRuntime.INT_NA; + } + } + private static final byte[] DASHED_LINE = new byte[]{4, 4}; private static final byte[] DOTTED_LINE = new byte[]{1, 3}; private static final byte[] DOTDASH_LINE = new byte[]{1, 3, 4, 3}; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java index 939a90546e5b2cfcb1ef3155d6c352519e64fe16..1ec25bf728686609acfa0232c2515f4f09818363 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java @@ -14,15 +14,36 @@ package com.oracle.truffle.r.library.fastrGrid; import java.util.HashMap; import java.util.Locale; +import com.oracle.truffle.r.library.fastrGrid.GridState.GridPalette; import com.oracle.truffle.r.library.fastrGrid.device.GridColor; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; public final class GridColorUtils { + + private static GridPalette defaultPalette; + private GridColorUtils() { // only static members } + public static GridPalette getDefaultPalette() { + if (defaultPalette == null) { + // Note: default palette copied from GNU R + defaultPalette = new GridPalette(new String[]{ + "black", + "red", + "green3", + "blue", + "cyan", + "magenta", + "yellow", + "grey" + }); + } + return defaultPalette; + } + /** * Converts the representation of color used within R, e.g. as value for * {@code gpar(col='value')}, to our internal representation that grid device should understand. @@ -34,6 +55,11 @@ public final class GridColorUtils { return parseHex(value); } + if (value.equals("NA")) { + // special case value, we want to check only for "NA", not "na". + return GridColor.TRANSPARENT; + } + Object result = findByName(value); if (result == null) { throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid color '" + value + "'."); @@ -84,7 +110,6 @@ public final class GridColorUtils { static { NAMES.put("transparent", GridColor.TRANSPARENT); - NAMES.put("NA", GridColor.TRANSPARENT); NAMES.put("white", "#FFFFFF"); NAMES.put("aliceblue", "#F0F8FF"); NAMES.put("antiquewhite", "#FAEBD7"); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java index 63585c18374f5b8e04e6325d8730b9afa1619a1b..20027f98003ddadbf07e640aa24cea53f7afe6b0 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java @@ -13,6 +13,7 @@ package com.oracle.truffle.r.library.fastrGrid; import java.util.function.Supplier; +import com.oracle.truffle.r.library.fastrGrid.device.GridColor; import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; @@ -21,6 +22,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment; public final class GridState { private REnvironment gridEnv; private GridDeviceState devState; + private GridPalette palette; /** * Current grob being drawn (for determining the list of grobs to search when evaluating a @@ -87,6 +89,14 @@ public final class GridState { devState.displayListIndex = newValue; } + public GridPalette getPalette() { + return palette == null ? GridColorUtils.getDefaultPalette() : palette; + } + + public void setPalette(GridPalette palette) { + this.palette = palette; + } + public void init(REnvironment gridEnv) { this.gridEnv = gridEnv; this.currentGrob = RNull.instance; @@ -153,6 +163,28 @@ public final class GridState { return devState.scale; } + public static final class GridPalette { + public final GridColor[] colors; + public final String[] colorNames; + + public GridPalette(String[] colorNames) { + this.colorNames = colorNames; + colors = new GridColor[colorNames.length]; + for (int i = 0; i < colorNames.length; i++) { + colors[i] = GridColorUtils.gridColorFromString(colorNames[i]); + } + } + + public GridPalette(int[] colors) { + this.colors = new GridColor[colors.length]; + colorNames = new String[colors.length]; + for (int i = 0; i < colors.length; i++) { + this.colors[i] = GridColor.fromRawValue(colors[i]); + colorNames[i] = GridColorUtils.gridColorToRString(this.colors[i]); + } + } + } + static final class GridDeviceState { private boolean isDeviceInitialized = false; private RList gpar; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java index 284a98450523ea60c5e2c57de3a91fd81070ab25..e88b9cf5a61311e6d7e7e7d1a013a1a2ff686476 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java @@ -15,6 +15,8 @@ import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2; import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.data.RAttributable; @@ -40,6 +42,16 @@ final class GridUtils { return coord - size * justification; } + static double getStringWidth(DrawingContext drawingContext, GridDevice dev, String str) { + String[] lines; + double result = 0; + lines = str.split("\n"); + for (String line : lines) { + result = Math.max(result, dev.getStringWidth(drawingContext, line)); + } + return result; + } + /** * Returns the amount of justification required. I.e. transforms the justification from value * between 0 and 1 to the value within size. diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LStringMetric.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LStringMetric.java new file mode 100644 index 0000000000000000000000000000000000000000..c4fb977c581e268f818ed9542aa4c051b360b06c --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LStringMetric.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; + +import java.util.Arrays; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; + +/** + * Returns a list with string's width, ascent and descent all in inches. + */ +public abstract class LStringMetric extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(LStringMetric.class); + casts.arg(0).mustBe(stringValue()).asStringVector(); + } + + public static LStringMetric create() { + return LStringMetricNodeGen.create(); + } + + @Specialization + @TruffleBoundary + public Object execute(RAbstractStringVector text) { + int len = text.getLength(); + + // Needs to be determined if ascent/descent are actually used by anyone without knowing the + // actual string height + double[] ascent = new double[len]; + double[] descent = new double[len]; + Arrays.fill(ascent, 0.); + Arrays.fill(descent, 0.); + + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + double[] width = new double[len]; + for (int i = 0; i < text.getLength(); i++) { + width[i] = GridUtils.getStringWidth(gpar.getDrawingContext(i), dev, text.getDataAt(i)); + } + + return RDataFactory.createList(new Object[]{asVec(ascent), asVec(descent), asVec(width)}); + } + + private static RAbstractDoubleVector asVec(double[] data) { + return RDataFactory.createDoubleVector(data, RDataFactory.COMPLETE_VECTOR); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java new file mode 100644 index 0000000000000000000000000000000000000000..67646f37e38032e5de2d49ee72515a1d44ed6aa1 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java @@ -0,0 +1,121 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 1997-2014, The R Core Team + * Copyright (c) 2003, The R Foundation + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.GridState.GridPalette; +import com.oracle.truffle.r.library.fastrGrid.PaletteExternalsFactory.CPalette2NodeGen; +import com.oracle.truffle.r.library.fastrGrid.PaletteExternalsFactory.CPaletteNodeGen; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public final class PaletteExternals { + private PaletteExternals() { + // only static members + } + + /** + * Implements external {@code C_palette} used in palette R function. + */ + public abstract static class CPalette extends RExternalBuiltinNode.Arg1 { + + static { + Casts casts = new Casts(CPalette.class); + casts.arg(0).mustBe(stringValue()); + } + + public static CPalette create() { + return CPaletteNodeGen.create(); + } + + @Specialization + @TruffleBoundary + public RStringVector updatePalette(RAbstractStringVector palette) { + GridState state = GridContext.getContext().getGridState(); + GridPalette newPalette = null; + if (palette.getLength() == 1) { + if (palette.getDataAt(0).toLowerCase().equals("default")) { + newPalette = GridColorUtils.getDefaultPalette(); + } else { + throw error(Message.GENERIC, "unknown palette (need >= 2 colors)"); + } + } else if (palette.getLength() > 1) { + newPalette = new GridPalette(palette.materialize().getDataCopy()); + } + + String[] original = state.getPalette().colorNames; + if (newPalette != null) { + // the contract is that if the argument's length is zero, we only return the palette + // and + // do not set anything. + state.setPalette(newPalette); + } + // don't know the completeness, assume the worst rather than finding out + RStringVector result = RDataFactory.createStringVector(original, RDataFactory.INCOMPLETE_VECTOR); + result.makeSharedPermanent(); + return result; + } + } + + /** + * Implements external {@code C_palette2} used only internally in grDevices, the parameter are + * colors encoded in integer already. + */ + public abstract static class CPalette2 extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(CPalette2.class); + casts.arg(0).mustBe(abstractVectorValue()); + } + + public static CPalette2 create() { + return CPalette2NodeGen.create(); + } + + @Specialization + @TruffleBoundary + public RIntVector updatePalette(RAbstractVector palette) { + GridState state = GridContext.getContext().getGridState(); + int[] newPalette = null; + if (palette.getLength() > 0) { + RAbstractIntVector data = GridUtils.asIntVector(palette); + newPalette = data.materialize().getDataCopy(); + } + RIntVector result = getResult(state); + if (newPalette != null) { + state.setPalette(new GridPalette(newPalette)); + } + return result; + } + + private static RIntVector getResult(GridState state) { + GridPalette palette = state.getPalette(); + int[] result = new int[palette.colors.length]; + boolean complete = true; + for (int i = 0; i < result.length; i++) { + result[i] = palette.colors[i].getRawValue(); + complete &= !RRuntime.isNA(result[i]); + } + return RDataFactory.createIntVector(result, complete); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java index 1d6405efaf78e1942d91018099ea19e6c5df9c42..23a7f92db67eb6c30eff8b842730e90b8bbf7ab7 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java @@ -213,11 +213,7 @@ public final class Unit { case STRINGWIDTH: case MYSTRINGWIDTH: str = RRuntime.asString(data.getDataAt(0)); - lines = str.split("\n"); - for (String line1 : lines) { - result = Math.max(result, ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), line1)); - } - return value * result; + return value * GridUtils.getStringWidth(ctx.gpar.getDrawingContext(index), ctx.device, str); case STRINGHEIGHT: case MYSTRINGHEIGHT: str = RRuntime.asString(data.getDataAt(0)); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java index 28abf944f1eae6088260398ccf7c9103c7118733..ec11023ea1248c6471f9a92947c56543c8f91882 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java @@ -33,6 +33,10 @@ public final class GridColor { private final int value; + private GridColor(int value) { + this.value = value; + } + public GridColor(int red, int green, int blue, int alpha) { value = ((alpha & 0xFF) << 24) | ((red & 0xFF) << 16) | @@ -40,6 +44,10 @@ public final class GridColor { (blue & 0xFF); } + public static GridColor fromRawValue(int value) { + return new GridColor(value); + } + public int getRed() { return (value >> 16) & 0xFF; } @@ -56,6 +64,10 @@ public final class GridColor { return (value >> 24) & 0xff; } + public int getRawValue() { + return value; + } + @Override public boolean equals(Object obj) { return obj instanceof GridColor && value == ((GridColor) obj).value; diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c index ebf731f63f9664d3921bba9ba643b1af4c6206d0..88a5b6e9b3ba8e93b958ce16d0e495bf87d60b1d 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c @@ -22,6 +22,7 @@ static jclass RegisteredNativeSymbolClass; static jmethodID registerRoutinesID; static jmethodID registerCCallableID; +static jmethodID getCCallableID; static jmethodID useDynamicSymbolsID; static jmethodID forceSymbolsID; static jmethodID setDotSymbolValuesID; @@ -36,6 +37,7 @@ void init_dynload(JNIEnv *env) { registerRoutinesID = checkGetMethodID(env, JNI_PkgInitClass, "registerRoutines", "(Lcom/oracle/truffle/r/runtime/ffi/DLL$DLLInfo;IIJ)V", 1); registerCCallableID = checkGetMethodID(env, JNI_PkgInitClass, "registerCCallable", "(Ljava/lang/String;Ljava/lang/String;J)V", 1); + getCCallableID = checkGetMethodID(env, JNI_PkgInitClass, "getCCallable", "(Ljava/lang/String;Ljava/lang/String;)J", 1); useDynamicSymbolsID = checkGetMethodID(env, JNI_PkgInitClass, "useDynamicSymbols", "(Lcom/oracle/truffle/r/runtime/ffi/DLL$DLLInfo;I)I", 1); forceSymbolsID = checkGetMethodID(env, JNI_PkgInitClass, "forceSymbols", "(Lcom/oracle/truffle/r/runtime/ffi/DLL$DLLInfo;I)I", 1); setDotSymbolValuesID = checkGetMethodID(env, JNI_PkgInitClass, "setDotSymbolValues", "(Ljava/lang/String;JI)Lcom/oracle/truffle/r/runtime/ffi/DLL$DotSymbol;", 1); @@ -139,8 +141,10 @@ Rboolean R_forceSymbols(DllInfo *dllInfo, Rboolean value) { } DL_FUNC R_GetCCallable(const char *package, const char *name) { - unimplemented("R_GetCCallable"); - return NULL; + JNIEnv *thisenv = getEnv(); + jstring packageString = (*thisenv)->NewStringUTF(thisenv, package); + jstring nameString = (*thisenv)->NewStringUTF(thisenv, name); + return (DL_FUNC) (*thisenv)->CallStaticObjectMethod(thisenv, JNI_PkgInitClass, getCCallableID, packageString, nameString); } DL_FUNC R_FindSymbol(char const *name, char const *pkg, diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source index 2bd5a0a98a36cc08ada88b804d3be047e6aa5b8a..409940768f2a684935a7d15a29f96e82c487f439 100644 --- a/com.oracle.truffle.r.native/version.source +++ b/com.oracle.truffle.r.native/version.source @@ -1 +1 @@ -22 +23 diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java index f76be777345451de573b7888e29b873a5e3065d9..ece1e6e7b936fc80923e638d3442b69f5492dd5d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java @@ -74,7 +74,7 @@ public abstract class AsCharacter extends RBuiltinNode.Arg2 { } else if (elem instanceof RStringVector && ((RStringVector) elem).getLength() == 1) { data[i] = ((RStringVector) elem).getDataAt(0); } else { - data[i] = RDeparse.deparse(elem, RDeparse.MAX_Cutoff, true, RDeparse.SIMPLEDEPARSE, -1); + data[i] = RDeparse.deparse(elem, RDeparse.MAX_CUTOFF, true, RDeparse.SIMPLEDEPARSE, -1); } if (RRuntime.isNA(data[i])) { complete = RDataFactory.INCOMPLETE_VECTOR; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java index e746de2a76368f54daa0461ad94e6659a1f0cfd7..fab198672dd600476fc59d33672bfe909ac5b20b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java @@ -32,6 +32,7 @@ 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.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.GetAttributeNode; @@ -48,6 +49,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; @@ -136,6 +138,8 @@ public abstract class Attr extends RBuiltinNode.Arg3 { protected Object attr(Object object, Object name, Object exact) { if (object instanceof RAttributable) { return attrRA((RAttributable) object, intern.execute((String) name), (boolean) exact); + } else if (RRuntime.isForeignObject(object)) { + throw RError.error(this, Message.OBJ_CANNOT_BE_ATTRIBUTED); } else { throw RError.nyi(this, "object cannot be attributed"); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java index c2e894809ced2e2442a1f0f9cb861a4604d390d7..5f3aee4e78d586e8754665ea9e0e3f6a480975a3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java @@ -84,7 +84,7 @@ public abstract class Attributes extends RBuiltinNode.Arg1 { } else { return createResult((RAttributable) object, false); } - } else if (object == RNull.instance) { + } else if (object == RNull.instance || RRuntime.isForeignObject(object)) { return RNull.instance; } else { throw RError.nyi(this, "object cannot be attributed"); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index c30232bc10d3b97eb4bb95c78daf7a29c4dfcc8e..2bf4e37ed7d34b898ab99c5a2c8da89f5987f94c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -102,6 +102,8 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfo; import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfoNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRSlotAssign; import com.oracle.truffle.r.nodes.builtin.fastr.FastRSlotAssignNodeGen; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRSourceInfo; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRSourceInfoNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTrace; import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTraceNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfAttr; @@ -391,6 +393,7 @@ public class BasePackage extends RBuiltinPackage { add(FastRInterop.ToShort.class, FastRInteropFactory.ToShortNodeGen::create); add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::create); add(FastRPkgSource.class, FastRPkgSourceNodeGen::create); + add(FastRSourceInfo.class, FastRSourceInfoNodeGen::create); add(FastRStackTrace.class, FastRStackTraceNodeGen::create); add(FastRProfAttr.class, FastRStatsFactory.FastRProfAttrNodeGen::create); add(FastRProfTypecounts.class, FastRStatsFactory.FastRProfTypecountsNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java index d0361a493fd9fba3da09709a9e967e9334354574..13f43b742006fdade1fcc006389fc993d931ed34 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java @@ -52,7 +52,7 @@ public abstract class DPut extends RBuiltinNode.Arg3 { @Specialization @TruffleBoundary protected Object dput(Object x, int file, int opts) { - String string = RDeparse.deparse(x, RDeparse.DEFAULT_Cutoff, true, opts, -1); + String string = RDeparse.deparse(x, RDeparse.DEFAULT_CUTOFF, true, opts, -1); try (RConnection openConn = RConnection.fromIndex(file).forceOpen("wt")) { openConn.writeString(string, true); } catch (IOException ex) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java index fdd7a26615bc8c8b22a40276dca4f24dcdb20cc5..a258e75f8ed951e14f99225759e4f55a1e34de67 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java @@ -42,9 +42,9 @@ public abstract class Deparse extends RBuiltinNode.Arg5 { @TruffleBoundary protected RStringVector deparse(Object expr, int widthCutoffArg, boolean backtick, int control, int nlines) { int widthCutoff = widthCutoffArg; - if (widthCutoff == RRuntime.INT_NA || widthCutoff < RDeparse.MIN_Cutoff || widthCutoff > RDeparse.MAX_Cutoff) { + if (widthCutoff == RRuntime.INT_NA || widthCutoff < RDeparse.MIN_CUTOFF || widthCutoff > RDeparse.MAX_CUTOFF) { warning(RError.Message.DEPARSE_INVALID_CUTOFF); - widthCutoff = RDeparse.DEFAULT_Cutoff; + widthCutoff = RDeparse.DEFAULT_CUTOFF; } String[] data = RDeparse.deparse(expr, widthCutoff, backtick, control, nlines).split("\n"); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java index a05fba7d0a78b52737beb2200532f51fb97e55e3..ef414d42b61e114ba26cc3a4c5960b2a0bf0aa56 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java @@ -66,9 +66,11 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RS4Object; +import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -316,6 +318,8 @@ public class GetFunctions { @Specialization protected RList mget(VirtualFrame frame, RAbstractStringVector xv, REnvironment envir, RAbstractStringVector mode, RList ifNotFound, boolean inherits, + @Cached("createBinaryProfile()") ConditionProfile argsAndValuesProfile, + @Cached("createBinaryProfile()") ConditionProfile missingProfile, @Cached("createBinaryProfile()") ConditionProfile inheritsProfile) { State state = checkArgs(xv, mode, ifNotFound); for (int i = 0; i < state.svLength; i++) { @@ -330,7 +334,7 @@ public class GetFunctions { while (env != REnvironment.emptyEnv()) { env = env.getParent(); if (env != REnvironment.emptyEnv()) { - r = helper.checkPromise(frame, env.get(x), x); + r = handleMissingAndVarargs(helper.checkPromise(frame, env.get(x), x), argsAndValuesProfile, missingProfile); if (r != null && RRuntime.checkType(r, modeType)) { break; } @@ -343,7 +347,7 @@ public class GetFunctions { state.data[i] = r; } } else { - Object r = helper.checkPromise(frame, envir.get(x), x); + Object r = handleMissingAndVarargs(helper.checkPromise(frame, envir.get(x), x), argsAndValuesProfile, missingProfile); if (r != null && RRuntime.checkType(r, modeType)) { state.data[i] = r; } else { @@ -356,9 +360,11 @@ public class GetFunctions { @Specialization protected RList mget(VirtualFrame frame, RAbstractStringVector xv, RS4Object s4Envir, RAbstractStringVector mode, RList ifNotFound, boolean inherits, + @Cached("createBinaryProfile()") ConditionProfile argsAndValuesProfile, + @Cached("createBinaryProfile()") ConditionProfile missingProfile, @Cached("createBinaryProfile()") ConditionProfile inheritsProfile, @Cached("new()") S4ToEnvNode s4ToEnv) { - return mget(frame, xv, (REnvironment) s4ToEnv.execute(s4Envir), mode, ifNotFound, inherits, inheritsProfile); + return mget(frame, xv, (REnvironment) s4ToEnv.execute(s4Envir), mode, ifNotFound, inherits, argsAndValuesProfile, missingProfile, inheritsProfile); } private void doIfNotFound(VirtualFrame frame, State state, int i, String x, RList ifNotFound) { @@ -380,5 +386,20 @@ public class GetFunctions { return callCache.execute(frame, ifnFunc, RCaller.create(frame, RCallerHelper.createFromArguments(ifnFunc, args)), callerFrame, new Object[]{x}, formals.getSignature(), ifnFunc.getEnclosingFrame(), null); } + + private static Object handleMissingAndVarargs(Object value, ConditionProfile argsAndValuesProfile, ConditionProfile missingProfile) { + if (argsAndValuesProfile.profile(value instanceof RArgsValuesAndNames)) { + if (((RArgsValuesAndNames) value).getLength() == 0) { + return RSymbol.MISSING; + } else { + // GNUR also puts raw promises in the list + return RDataFactory.createList(((RArgsValuesAndNames) value).getArguments()); + } + } + if (missingProfile.profile(value == RMissing.instance)) { + return RSymbol.MISSING; + } + return value; + } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java index 8a5446c3d6af500002450e0b5686860bd2c4f872..f309975878a3af3f16c66c8e2a099601b24bb498 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java @@ -35,9 +35,11 @@ import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; 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.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -47,6 +49,9 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; * * TODO Can we find a way to efficiently write the specializations as generics? The code is * identical except for the argument type. + * + * TODO: GNU R preserves the corresponding values of names attribute. There are (ignored) tests for + * this in TestBuiltin_split. */ @RBuiltin(name = "split", kind = INTERNAL, parameterNames = {"x", "f"}, behavior = PURE) public abstract class Split extends RBuiltinNode.Arg2 { @@ -62,9 +67,37 @@ public abstract class Split extends RBuiltinNode.Arg2 { Casts.noCasts(Split.class); } - public static class SplitTemplate { - @SuppressWarnings("unused") private int[] collectResultsSize; - @SuppressWarnings("unused") private int nLevels; + @Specialization + protected RList split(RAbstractListVector x, RAbstractIntVector f) { + int[] factor = f.materialize().getDataWithoutCopying(); + RStringVector names = getLevelNode.execute(f); + final int nLevels = getNLevels(names); + + // initialise result arrays + Object[][] collectResults = new Object[nLevels][]; + int[] collectResultSize = new int[nLevels]; + for (int i = 0; i < collectResults.length; i++) { + collectResults[i] = new Object[INITIAL_SIZE]; + } + + // perform split + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { + int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + Object[] collect = collectResults[resultIndex]; + if (collect.length == collectResultSize[resultIndex]) { + collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR); + collect = collectResults[resultIndex]; + } + collect[collectResultSize[resultIndex]++] = x.getDataAt(i); + } + + // assemble result vectors and level names + Object[] results = new Object[nLevels]; + for (int i = 0; i < nLevels; i++) { + results[i] = RDataFactory.createList(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i])); + } + + return RDataFactory.createList(results, names); } @Specialization @@ -199,6 +232,39 @@ public abstract class Split extends RBuiltinNode.Arg2 { return RDataFactory.createList(results, names); } + @Specialization + protected RList split(RRawVector x, RAbstractIntVector f) { + int[] factor = f.materialize().getDataWithoutCopying(); + RStringVector names = getLevelNode.execute(f); + final int nLevels = getNLevels(names); + + // initialise result arrays + byte[][] collectResults = new byte[nLevels][]; + int[] collectResultSize = new int[nLevels]; + for (int i = 0; i < collectResults.length; i++) { + collectResults[i] = new byte[INITIAL_SIZE]; + } + + // perform split + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { + int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + byte[] collect = collectResults[resultIndex]; + if (collect.length == collectResultSize[resultIndex]) { + collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR); + collect = collectResults[resultIndex]; + } + collect[collectResultSize[resultIndex]++] = x.getDataAt(i).getValue(); + } + + // assemble result vectors and level names + Object[] results = new Object[nLevels]; + for (int i = 0; i < nLevels; i++) { + results[i] = RDataFactory.createRawVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i])); + } + + return RDataFactory.createList(results, names); + } + private static int getNLevels(RStringVector levels) { return levels != null ? levels.getLength() : 0; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java index 1b8e654595860dd72bb9c1a41276a552536ace64..50fce23643fd2166344fa2b9128ea88834da9480 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java @@ -32,6 +32,7 @@ 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.Specialization; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; @@ -47,6 +48,7 @@ import com.oracle.truffle.r.nodes.unary.CastToVectorNode; import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; import com.oracle.truffle.r.nodes.unary.GetNonSharedNode; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -243,6 +245,8 @@ public abstract class UpdateAttr extends RBuiltinNode.Arg3 { attributable.setAttr(internedName, value); } return object; + } else if (RRuntime.isForeignObject(obj)) { + throw RError.error(this, Message.OBJ_CANNOT_BE_ATTRIBUTED); } else { throw RError.nyi(this, "object cannot be attributed"); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java index 82ddd8f26ff0f5bda65d6705a7185f065090e358..bc050bed9d46661b295b32889e4b192304e8daa8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,6 @@ final class LanguagePrinter extends AbstractValuePrinter<RLanguage> { @Override @TruffleBoundary protected void printValue(RLanguage language, PrintContext printCtx) throws IOException { - printCtx.output().print(RDeparse.deparse(language, RDeparse.DEFAULT_Cutoff, true, RDeparse.KEEPINTEGER, -1)); + printCtx.output().print(RDeparse.deparse(language, RDeparse.DEFAULT_CUTOFF, true, RDeparse.KEEPINTEGER, -1)); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java index 19451dfcbf5e7dc936254d14ef4d57b7af44566e..0bf416f5573f48cfaec6cfc6e328d1531e4f90a1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,6 @@ final class SymbolPrinter extends AbstractValuePrinter<RSymbol> { @Override @TruffleBoundary protected void printValue(RSymbol value, PrintContext printCtx) throws IOException { - printCtx.output().print(RDeparse.deparse(value, RDeparse.DEFAULT_Cutoff, true, RDeparse.SIMPLEDEPARSE, -1)); + printCtx.output().print(RDeparse.deparse(value, RDeparse.DEFAULT_CUTOFF, true, RDeparse.SIMPLEDEPARSE, -1)); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java index 6beeea072ece55a1284ae5c7f54a4f8d4131a51b..662a227111f22dc328e300f21616f61edfd10dae 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java @@ -101,7 +101,6 @@ public final class ValuePrinterNode extends RBaseNode { @Child private Node unboxNode = com.oracle.truffle.api.interop.Message.UNBOX.createNode(); @Child private Node keysNode = com.oracle.truffle.api.interop.Message.KEYS.createNode(); @Child private SetFixedAttributeNode namesAttrSetter = SetFixedAttributeNode.createNames(); - @Child private SetFixedAttributeNode isTruffleObjAttrSetter = SetFixedAttributeNode.create("is.truffle.object"); @TruffleBoundary public Object convert(TruffleObject obj) { @@ -303,7 +302,6 @@ public final class ValuePrinterNode extends RBaseNode { super(length); DynamicObject attrs = RAttributesLayout.createNames(names); initAttributes(attrs); - isTruffleObjAttrSetter.execute(attrs, RRuntime.LOGICAL_TRUE); } @Override @@ -377,32 +375,47 @@ public final class ValuePrinterNode extends RBaseNode { } private Object convertTruffleObject(Object o) { - if (o instanceof TruffleObject && !(o instanceof RTypedValue)) { + if (RRuntime.isForeignObject(o)) { if (convertTruffleObject == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); convertTruffleObject = insert(new ConvertTruffleObjectNode()); } return convertTruffleObject.convert((TruffleObject) o); } - return o; + return null; } public String execute(Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) { try { - prettyPrint(convertTruffleObject(o), new PrintParameters(digits, quote, naPrint, printGap, right, max, useSource, noOpt), RWriter::new); + PrintParameters printParams = new PrintParameters(digits, quote, naPrint, printGap, right, max, useSource, noOpt); + + PrintContext printCtx = PrintContext.enter(this, printParams, RWriter::new); + try { + prettyPrint(o, printCtx); + Object foreignObjectWrapper = convertTruffleObject(o); + if (foreignObjectWrapper != null) { + prettyPrint(foreignObjectWrapper, printCtx); + } + } finally { + PrintContext.leave(); + } return null; } catch (IOException ex) { throw RError.ioError(this, ex); } } + @TruffleBoundary + private static void prettyPrint(Object o, PrintContext printCtx) throws IOException { + ValuePrinters.INSTANCE.print(o, printCtx); + ValuePrinters.printNewLine(printCtx); + } + private abstract static class TruffleObjectWrapper extends RAttributeStorage implements RAbstractVector { private final int length; TruffleObjectWrapper(int length) { - initAttributes().define("is.truffle.object", RRuntime.LOGICAL_TRUE); - this.length = length; } @@ -548,22 +561,6 @@ public final class ValuePrinterNode extends RBaseNode { } } - private String prettyPrint(Object o, PrintParameters printParams, WriterFactory wf) throws IOException { - PrintContext printCtx = PrintContext.enter(this, printParams, wf); - try { - prettyPrint(o, printCtx); - return null; - } finally { - PrintContext.leave(); - } - } - - @TruffleBoundary - private static void prettyPrint(Object o, PrintContext printCtx) throws IOException { - ValuePrinters.INSTANCE.print(o, printCtx); - ValuePrinters.printNewLine(printCtx); - } - @SuppressWarnings("deprecation") public static String prettyPrint(final Object value) { return (String) Truffle.getRuntime().createCallTarget(new RootNode(TruffleLanguage.class, null, null) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java index c59f4dbc43c325a0046106d0e04140d1123b77f4..3594b6ceaaeb548248103ca47531d29805e995b6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java @@ -98,7 +98,7 @@ public class FastRContext { private static void handleSharedContexts(ContextKind contextKind) { if (contextKind == ContextKind.SHARE_ALL) { RContext current = RContext.getInstance(); - if (EvalThread.threads.size() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) { + if (EvalThread.threadCnt.get() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) { ContextInfo.resetMultiSlotIndexGenerator(); } else { throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Shared contexts can be created only if no other child contexts exist"); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..ed3430a7b325f4ad1d1f6abd39ecc8fb61e57102 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.nodes.builtin.fastr; + +import static com.oracle.truffle.r.runtime.RVisibility.ON; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.builtins.RBehavior; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RNull; + +/** + * Allows to show the actual location of the source section of a provided function. + */ +@RBuiltin(name = ".fastr.srcinfo", visibility = ON, kind = PRIMITIVE, parameterNames = "fun", behavior = RBehavior.IO) +public abstract class FastRSourceInfo extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(FastRSourceInfo.class); + } + + @Specialization + public Object srcInfo(@SuppressWarnings("unused") RNull fun) { + return RNull.instance; + } + + @Specialization + public Object srcInfo(RFunction fun) { + SourceSection ss = fun.getRootNode().getSourceSection(); + if (ss != null) { + String path = ss.getSource().getPath(); + if (path != null) { + return path + "#" + ss.getStartLine(); + } else { + return ss.getSource().getName(); + } + } + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java index 75684febae6ee8df37d7d1fd758169b6a918569f..b50be670aff64e6194a116cffdf175381e241629 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java @@ -598,11 +598,14 @@ public class DebugHandling { public void onEnter(EventContext context, VirtualFrame frame) { if (!RContext.getInstance().stateInstrumentation.debugGloballyDisabled()) { CompilerDirectives.transferToInterpreter(); - FunctionDefinitionNode fdn = (FunctionDefinitionNode) context.getInstrumentedNode().getRootNode(); - FunctionStatementsEventListener ensureSingleStep = ensureSingleStep(fdn); + RootNode rootNode = context.getInstrumentedNode().getRootNode(); + if (rootNode instanceof FunctionDefinitionNode) { + FunctionDefinitionNode fdn = (FunctionDefinitionNode) rootNode; + FunctionStatementsEventListener ensureSingleStep = ensureSingleStep(fdn); - functionStatementsEventListener.clearStepInstrument(); - ensureSingleStep.onEnter(context, frame); + functionStatementsEventListener.clearStepInstrument(); + ensureSingleStep.onEnter(context, frame); + } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R index 2d3ebf6b49a58ea052b43953b3c3e1c47aaaad39..02940b6a2aa6d27bf3fc7b34d79558e58f26a8c3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R @@ -111,4 +111,10 @@ stopCluster.SHAREDcluster <- function(cl) { } } +## manually register S3 generic methods +registerS3method("closeNode", "SHAREDnode", closeNode.SHAREDnode) +registerS3method("sendData", "SHAREDnode", sendData.SHAREDnode) +registerS3method("recvData", "SHAREDnode", recvData.SHAREDnode) +registerS3method("recvOneData", "SHAREDcluster", recvOneData.SHAREDcluster) +registerS3method("stopCluster", "SHAREDcluster", stopCluster.SHAREDcluster) }), asNamespace("parallel")) diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java index 1f317668577066be9db826c1ae0ee1dce1e65fa2..0a8d63ec7ed252318654e764ef1e79573fbcfcf3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java @@ -150,7 +150,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 { } private static RString deparseSymbolOrLang(Object val) { - return RString.valueOf(RDeparse.deparse(val, RDeparse.MAX_Cutoff, false, RDeparse.KEEPINTEGER, -1)); + return RString.valueOf(RDeparse.deparse(val, RDeparse.MAX_CUTOFF, false, RDeparse.KEEPINTEGER, -1)); } protected BinaryBooleanNode createRecursive() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java index 92e4c8dfa0d50926b61d8bc4fb57cf5097917278..7c2fefce91fa49c3feb87db49592190fa9eebbde 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java @@ -672,7 +672,7 @@ public class ArgumentMatcher { assert suppliedName != null && !suppliedName.isEmpty(); for (int i = 0; i < formalsSignature.getLength(); i++) { String formalName = formalsSignature.getName(i); - if (formalName != null) { + if (!formalsSignature.isVarArg(i) && formalName != null) { if (formalName.equals(suppliedName)) { if (resultPermutation[i] != MatchPermutation.UNMATCHED) { if (builtin != null && builtin.getKind() == RBuiltinKind.PRIMITIVE && hasVarArgs) { diff --git a/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION b/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION new file mode 100644 index 0000000000000000000000000000000000000000..22b6b722cc2bf4bf2c7ee8830d129ea8a50f8272 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION @@ -0,0 +1,11 @@ +Package: rJava +Type: Package +Title: FastR rJava compatibility layer +Version: 1.0 +Date: 2017-05-18 +Author: Tomas Stupka +Maintainer: Tomas Stupka <tomas.stupka@oracle.com> +Description: Provides rJava R interface backed by FastR interoperability builtins. +License: GPL-2 +Suggests: testthat +RoxygenNote: 6.0.1 diff --git a/com.oracle.truffle.r.pkgs/rJava/NAMESPACE b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE new file mode 100644 index 0000000000000000000000000000000000000000..20c27039014d4fc3a4125f92e4f5960410723234 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE @@ -0,0 +1,16 @@ +# Generated by roxygen2: do not edit by hand + +export(.jarray) +export(.jbyte) +export(.jcall) +export(.jchar) +export(.jcheck) +export(.jevalArray) +export(.jfield) +export(.jfloat) +export(.jinit) +export(.jlong) +export(.jnew) +export(.jnull) +export(.jshort) +export(.jsimplify) diff --git a/com.oracle.truffle.r.pkgs/rJava/R/rj.R b/com.oracle.truffle.r.pkgs/rJava/R/rj.R new file mode 100644 index 0000000000000000000000000000000000000000..eb18a8713c1f47f2d7739a9fd41cf8bbbc28590d --- /dev/null +++ b/com.oracle.truffle.r.pkgs/rJava/R/rj.R @@ -0,0 +1,119 @@ +## + # This material is distributed under the GNU General Public License + # Version 2. You may review the terms of this license at + # http://www.gnu.org/licenses/gpl-2.0.html + # + # Copyright (c) 2006 Simon Urbanek <simon.urbanek@r-project.org> + # Copyright (c) 2017, Oracle and/or its affiliates + # + # All rights reserved. +## + +#' @export +.jnew <- function (class, ..., check = TRUE, silent = !check) +{ + class <- gsub("/", ".", as.character(class)) + co <- .fastr.java.class(class) + o <- .fastr.interop.new(co, ...) + invisible(o) +} + +#' @export +.jcall <- function (obj, returnSig = "V", method, ..., evalArray = TRUE, + evalString = TRUE, check = TRUE, interface = "RcallMethod", + simplify = FALSE, use.true.class = FALSE) +{ + if(is.character(obj)) { + co <- .fastr.java.class(obj) + r <- co[method](...) + } else { + r <- obj[method](...) + } + r +} + +#' @export +.jfield <- function (obj, sig = NULL, name, true.class = is.null(sig), convert = TRUE) +{ + if(is.character(obj)) { + co <- .fastr.java.class(obj) + r <- co[name] + } else { + r <- obj[name] + } + r +} + +#' @export +.jarray <- function (x, contents.class = NULL, dispatch = FALSE) +{ + .fastr.java.toArray(x, ,TRUE) +} + +#' @export +.jevalArray <- function (x, contents.class = NULL, dispatch = FALSE) +{ + .fastr.java.fromArray(x) +} + +#' @export +.jbyte <- function (x) +{ + x <- .fastr.interop.toByte(x) + invisible(x) +} + +#' @export +.jchar <- function (x) +{ + x <- .fastr.interop.toChar(x) + invisible(x) +} + +#' @export +.jshort <- function (x) +{ + x <- .fastr.interop.toShort(x) + invisible(x) +} + +#' @export +.jlong <- function (x) +{ + x <- .fastr.interop.toLong(x) + invisible(x) +} + +#' @export +.jfloat <- function (x) +{ + x <- .fastr.interop.toFloat(x) + invisible(x) +} + +# +# noop stubs +# + +#' @export +.jinit <- function () +{ + # do nothing +} + +#' @export +.jsimplify <- function (x) +{ + x +} + +#' @export +.jcheck <- function(silent = FALSE) { + FALSE +} + +#' @export +.jnull <- function (class) +{ + # do nothing +} diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R new file mode 100644 index 0000000000000000000000000000000000000000..46b38886ec61b333475eda982a77f68ac0bdd59a --- /dev/null +++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R @@ -0,0 +1,5 @@ +library(testthat) +library(rjava) + +test_check("rjava") +typeName \ No newline at end of file diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R new file mode 100644 index 0000000000000000000000000000000000000000..d0581b43c8330e550bca70c78820096bfb5ad1ff --- /dev/null +++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R @@ -0,0 +1,102 @@ +# prerequisites: +# - 'testthat' package has to be installed: install.packages("testthat") +# - FastR`s rJava package has to be installed: bin/r CMD INSTALL com.oracle.truffle.r.pkgs/rjava +# - mxbuild/dists/fastr-unit-tests.jar has to be on FastR classpath + +library(testthat) +library(rJava) + +testName <- "test .jarray" +test_that(testName, { + cat(paste0(testName, "\n")) + + a <- .jarray(c(1.1, 2.1, 3.1)) + expect_true(.fastr.java.isArray(a)) + expect_equal(length(a), 3) + expect_equal(a[1], c(1.1)) + expect_equal(a[2], c(2.1)) + expect_equal(a[3], c(3.1)) + + a <- .jarray(c(1L, 2L, 3L)) + expect_true(.fastr.java.isArray(a)) + expect_equal(length(a), 3) + expect_equal(a[1], c(1)) + expect_equal(a[2], c(2)) + expect_equal(a[3], c(3)) + + a <- .jarray(c(TRUE, FALSE)) + expect_true(.fastr.java.isArray(a)) + expect_equal(length(a), 2) + expect_equal(a[1], TRUE) + expect_equal(a[2], FALSE) + + a <- .jarray(c(.jbyte(1), .jchar("a"), .jfloat(1.1), .jlong(2), .jshort(123))) + expect_true(.fastr.java.isArray(a)) + expect_equal(length(a), 5) + expect_equal(a[1], 1) + expect_equal(a[2], "a") + expect_true((a[3] - 1.1)^2 < 1e-8) + expect_equal(a[4], 2) + expect_equal(a[5], 123) + + to <- .jnew('java.util.ArrayList') + a <- .jarray(to) + expect_true(.fastr.java.isArray(a)) + expect_equal(length(a), 1) + # fails at the moment + # expect_equal(a[1], to) + + to <- .jnew('java.util.ArrayList') + a <- .jarray(c(to, to)) + expect_true(.fastr.java.isArray(a)) + expect_equal(length(a), 2) + # fails at the moment + # expect_equal(a[1], to) + # expect_equal(a[2], to) + + a <- .jarray(list(1, 2, 3)) + expect_true(.fastr.java.isArray(a)) + expect_equal(length(a), 3) + expect_equal(a[1], 1) + expect_equal(a[2], 2) + expect_equal(a[3], 3) +}) + +testName <- "test .jevalArray" +test_that(testName, { + cat(paste0(testName, "\n")) + + expectedValues <- list( + Boolean=list("logical", TRUE, FALSE, TRUE), + Byte=list("integer", 1,2,3), + Char=list("character", "a", "b", "c"), + Double=list("double",1.1, 2.1, 3.1), + Float=list("double", 1.1, 2.1, 3.1), + Int=list("integer",1,2,3), + Long=list("double", 1,2,3), + Short=list("integer",1,2,3), + String=list("character", "a", "b", "c")) + testClassName <- "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" + t<-.jnew(class=testClassName) + + for(expectedName in names(expectedValues)) { + fieldName <- paste0("fieldStatic", expectedName, "Array") + ev<-expectedValues[expectedName][[1]] + arrayType <- ev[[1]] + arrayLength <- length(ev) - 1 + a<-t[fieldName] + expect_true(.fastr.java.isArray(a), info=paste0("the array was returned for ", fieldName), label=".fastr.java.isArray") + ae<-.jevalArray(a) + expect_true(is.vector(ae), info=paste0("the array was returned for ", fieldName), label="is.vector") + expect_equal(typeof(ae), arrayType, info=paste0("the array was returned for ", fieldName), label="typeof") + expect_equal(length(ae), arrayLength, info=paste0("the array was returned for ", fieldName), label="array length") + for(i in 1:arrayLength) { + if(expectedName != "Float") { + expect_equal(a[i], ev[[i+1]], info=paste0("the array was returned for ", fieldName), label=paste0("value at", i)) + } else { + expect_true((ev[[i+1]] - a[i])^2 < 1e-8, info=paste0("the array was returned for ", fieldName), label=paste0("value at", i)) + } + } + } + +}) \ No newline at end of file diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R new file mode 100644 index 0000000000000000000000000000000000000000..72945437d159500915125e077db805376574defe --- /dev/null +++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R @@ -0,0 +1,135 @@ +# prerequisites: +# - 'testthat' package has to be installed: install.packages("testthat") +# - FastR`s rJava package has to be installed: bin/r CMD INSTALL com.oracle.truffle.r.pkgs/rjava +# - mxbuild/dists/fastr-unit-tests.jar has to be on FastR classpath + +library(testthat) +library(rJava) + +bo <- TRUE +bt <- 123 +ch <- 'a' +d <- 1.123456 +f <- 1.123 +i <- 12345L +l <- 123456 +sh <- 1234 +st <- "a test string" + +jbt <- .jbyte(bt) +jch <- .jchar(ch) +jf <- .jfloat(f) +jl <- .jlong(l) +jsh <- .jshort(sh) + +primitiveTypeNames <- c("Boolean", "Byte", "Char", "Double", "Float", "Integer", "Long", "Short") +expectedValues <- list(bo, bt, ch, d, f, i, l, sh, st) + +testClassName <- "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" +t<-.jnew(class=testClassName, bo, jbt, jch, d, jf, i, jl, jsh, st) + +testForMember <- function(valueProvider, memberNameProvider, typeNames) { + for(idx in 1:length(typeNames)) { + typeName <- typeNames[idx] + member <- memberNameProvider(typeName) + expectedValue <- expectedValues[[idx]] + value <- valueProvider(t, member) + testValue(member, typeName, expectedValue, value) + } +} + +testValue <- function(memberName, typeName, expectedValue, value) { + cat(paste0(" ", memberName, " returned value [", value, "] and is expected to be [", expectedValue, "]"), "\n") + if(typeName != "Float") { + expect_that(expectedValue, equals(value), info=memberName, label=memberName) + } else { + expect_true((expectedValue - value)^2 < 1e-8, info=memberName, label=memberName) + } +} + +testName <- "test if primitive field access works" +test_that(testName, { + cat(paste0(testName, "\n")) + testForMember( valueProvider = function(t, member) { .jfield(t, , member) }, + memberNameProvider = function(typeName) { paste0("field", typeName) }, + primitiveTypeNames ) +}) + +testName <- "test if primitive static field access works" +test_that(testName, { + cat(paste0(testName, "\n")) + testForMember( valueProvider = function(t, member) { .jfield(t, , member) }, + memberNameProvider = function(typeName) { paste0("fieldStatic", typeName) }, + primitiveTypeNames ) +}) + +testName <- "test if static field access works" +test_that("test if static field access works", { + testForMember( valueProvider = function(t, member) { .jfield(t, , member) }, + memberNameProvider = function(typeName) { paste0("fieldStatic", typeName, "Object") }, + c(primitiveTypeNames, "String") ) +}) + +testName <- "test if field access works" +test_that(testName, { + cat(paste0(testName, "\n")) + testForMember( valueProvider = function(t, member) { .jfield(t, , member) }, + memberNameProvider = function(typeName) { paste0("field", typeName, "Object")}, + c(primitiveTypeNames, "String") ) +}) + +testName <- "test if calling static method returning primitive values works" +test_that(testName, { + cat(paste0(testName, "\n")) + testForMember( valueProvider = function(t, member) { .jcall(t, , member) }, + memberNameProvider = function(typeName) { paste0("methodStatic", typeName) }, + primitiveTypeNames ) +}) + +testName <- "test if calling method returning primitive values works" +test_that(testName, { + cat(paste0(testName, "\n")) + testForMember( valueProvider = function(t, member) { .jcall(t, , member) }, + memberNameProvider = function(typeName) { paste0("method", typeName) }, + primitiveTypeNames ) +}) + +testName <- "test if calling static method returning object values works" +test_that(testName, { + cat(paste0(testName, "\n")) + testForMember( valueProvider = function(t, member) { .jcall(t, , member) }, + memberNameProvider = function(typeName) { paste0("methodStatic", typeName, "Object") }, + c(primitiveTypeNames, "String") ) +}) + +testName <- "test if calling method returning object values works" +test_that(testName, { + cat(paste0(testName, "\n")) + testForMember( valueProvider = function(t, member) { .jcall(t, , member) }, + memberNameProvider = function(typeName) { paste0("method", typeName, "Object") }, + c(primitiveTypeNames, "String") ) +}) + +testName <- "test if static access via class name works" +test_that(testName, { + cat(paste0(testName, "\n")) + value <- .jfield(testClassName, , "fieldStaticInteger") + testValue("fieldStaticInteger", "Integer", i, value) + + value <- .jcall(testClassName, , "methodStaticInteger") + testValue("methodStaticInteger", "Integer", i, value) +}) + +testName <- "test if calling method with all primitive type parameters + string works" +test_that(testName, { + cat(paste0(testName, "\n")) + value <- .jcall(t, , "allTypesMethod", bo, jbt, jch, d, jf, i, jl, jsh, st) + expect_false(is.null(value)) +}) + +testName <- "test if calling method with all primitive type parameters + string works" +test_that(testName, { + cat(paste0(testName, "\n")) + value <- .jcall(t, , "allTypesStaticMethod", bo, jbt, jch, d, jf, i, jl, jsh, st) + expect_false(is.null(value)) +}) \ No newline at end of file diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java index d5c2450edf354b3af039346cfa290d3e68556823..0cf12986f0869a1a7d5bf39ec1c75cc62332af46 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,11 @@ */ package com.oracle.truffle.r.runtime.ffi.jni; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.CEntry; import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; @@ -43,13 +46,18 @@ final class JNI_PkgInit { @SuppressWarnings("unused") private static void registerCCallable(String pkgName, String functionName, long address) { - // TBD + DLLInfo lib = safeFindLibrary(pkgName); + lib.registerCEntry(new CEntry(functionName, new SymbolHandle(address))); } @SuppressWarnings("unused") - private static long getCCallable(String pkgName, String functionName) { - // TBD - throw RInternalError.unimplemented(); + public static long getCCallable(String pkgName, String functionName) { + DLLInfo lib = safeFindLibrary(pkgName); + CEntry result = lib.lookupCEntry(functionName); + if (result == null) { + throw RError.error(RError.NO_CALLER, Message.UNKNOWN_OBJECT, functionName); + } + return result.address.asAddress(); } /** @@ -77,4 +85,14 @@ final class JNI_PkgInit { public static int findSymbol(String name, String pkg, DLL.RegisteredNativeSymbol rns) { throw RInternalError.unimplemented(); } + + private static DLLInfo safeFindLibrary(String pkgName) { + DLLInfo lib = DLL.findLibrary(pkgName); + if (lib == null) { + // It seems GNU R would create an C entry even for non-existing package, we are more + // defensive + throw RError.error(RError.NO_CALLER, Message.DLL_NOT_LOADED, pkgName); + } + return lib; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java index 20acad69f07ff206c3be83053d1d928b41138016..d5b2a0fd389ec17fdc974497bfbca268f42cf772 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,6 +149,10 @@ public final class ArgumentsSignature implements Iterable<String> { return names[index] == UNMATCHED; } + public boolean isVarArg(int index) { + return this.isVarArg[index]; + } + /** * Returns the index of given name, {@code -1} if it is not present. The search key must be * interned string. diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java index 7c250e88e7fb001ded28431cf715138ffc026fcf..73ebc61f284e076ec2ef3fe10e19d66db4133e09 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java @@ -26,8 +26,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; -import javax.xml.bind.DatatypeConverter; - import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.RootNode; @@ -86,9 +84,9 @@ public class RDeparse { public static final int SIMPLEDEPARSE = 0; public static final int DEFAULTDEPARSE = 65; /* KEEPINTEGER | KEEPNA, used for calls */ - public static final int MIN_Cutoff = 20; - public static final int MAX_Cutoff = 500; - public static final int DEFAULT_Cutoff = 60; + public static final int MIN_CUTOFF = 20; + public static final int MAX_CUTOFF = 500; + public static final int DEFAULT_CUTOFF = 60; public static final char BACKTICK = '`'; public static final char DQUOTE = '"'; @@ -264,22 +262,29 @@ public class RDeparse { private final ArrayList<SourceSectionElement> sources; - private final int cutoff; + private final int listCutoff; + private final int debugCutoff; private final boolean backtick; private int opts; - @SuppressWarnings("unused") private final int nlines; + private final int nlines; private int inCurly = 0; private int inList = 0; private int indent = 0; private int lastLineStart = 0; + private int curLine = 1; DeparseVisitor(boolean storeSource, int cutoff, boolean backtick, int opts, int nlines) { - this.cutoff = cutoff; + this(storeSource, cutoff, backtick, opts, nlines, -1); + } + + DeparseVisitor(boolean storeSource, int cutoff, boolean backtick, int opts, int nlines, int debugCutoff) { + this.listCutoff = cutoff; this.backtick = backtick; this.opts = opts; this.nlines = nlines; this.sources = storeSource ? new ArrayList<>() : null; + this.debugCutoff = debugCutoff; } public String getContents() { @@ -304,13 +309,22 @@ public class RDeparse { return (opts & QUOTEEXPRESSIONS) != 0; } + private void checkLength(int nchar) { + if (debugCutoff >= 0 && sb.length() + nchar > debugCutoff) { + throw new MaxLengthReachedException(); + } + } + private DeparseVisitor append(char ch) { assert ch != '\n'; + checkLength(1); sb.append(ch); return this; } private DeparseVisitor append(String str) { + assert !str.contains("\n"); + checkLength(str.length()); sb.append(str); return this; } @@ -342,7 +356,7 @@ public class RDeparse { if (digest == null) { digest = MessageDigest.getInstance("SHA-256"); } - String printHexBinary = DatatypeConverter.printHexBinary(digest.digest(sb.toString().getBytes())); + String printHexBinary = Utils.toHexString(digest.digest(sb.toString().getBytes())); assert printHexBinary.length() > 10; // just use the first 10 hex digits to have a nicer file name @@ -357,6 +371,7 @@ public class RDeparse { if (!Files.exists(path)) { try (BufferedWriter bw = Files.newBufferedWriter(path, CREATE_NEW, WRITE)) { bw.write(sb.toString()); + bw.newLine(); } } return path; @@ -370,7 +385,9 @@ public class RDeparse { Path path = emitToFile(name); Source source = RSource.fromFile(path.toFile()); for (SourceSectionElement s : sources) { - s.element.setSourceSection(source.createSection(s.start, s.length)); + if (s.element.getLazySourceSection() == null || s.element.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) { + s.element.setSourceSection(source.createSection(s.start, s.length)); + } } } catch (IOException e) { RInternalError.reportError(e); @@ -406,13 +423,20 @@ public class RDeparse { public DeparseVisitor append(RSyntaxElement element) { try (C c = withContext(element)) { visitor.accept(element); + } catch (AbortDeparsingException e) { + // stop deparsing; indicate that there is something missing + sb.append("..."); } return this; } private void printline() { sb.append("\n"); + curLine++; lastLineStart = sb.length(); + if (nlines > 0 && curLine >= nlines) { + throw new MaxLinesReachedException(); + } for (int i = 0; i < indent; i++) { sb.append(i < 4 ? " " : " "); } @@ -436,9 +460,9 @@ public class RDeparse { return null; } - private boolean linebreak(boolean lbreak) { + private boolean listLinebreak(boolean lbreak) { boolean result = lbreak; - if ((sb.length() - lastLineStart) > cutoff) { + if ((sb.length() - lastLineStart) > listCutoff) { if (!lbreak) { result = true; indent++; @@ -719,7 +743,7 @@ public class RDeparse { if (i++ > 0) { append(", "); } - lbreak = linebreak(lbreak); + lbreak = listLinebreak(lbreak); if (arglist.getTag() != RNull.instance) { String argName = ((RSymbol) arglist.getTag()).getName(); if (!argName.isEmpty()) { @@ -784,7 +808,7 @@ public class RDeparse { if (i > start) { append(", "); } - lbreak = linebreak(lbreak); + lbreak = listLinebreak(lbreak); RSyntaxElement argument = args[i]; String name = signature.getName(i); @@ -821,22 +845,27 @@ public class RDeparse { Object value = RRuntime.asAbstractVector(v); assert value instanceof RTypedValue : v.getClass(); - RSyntaxElement element; - if (value instanceof RSymbol) { - element = RSyntaxLookup.createDummyLookup(RSyntaxNode.INTERNAL, ((RSymbol) value).getName(), false); - } else if (value instanceof RLanguage) { - element = ((RLanguage) value).getRep().asRSyntaxNode(); - } else if (value instanceof RMissing) { - element = RSyntaxLookup.createDummyLookup(null, "", false); - } else { - return appendConstant(value); - } - if (!quoteExpressions() || element instanceof RSyntaxConstant) { - append(element); - } else { - append("quote("); - append(element); - append(')'); + try { + RSyntaxElement element; + if (value instanceof RSymbol) { + element = RSyntaxLookup.createDummyLookup(RSyntaxNode.INTERNAL, ((RSymbol) value).getName(), false); + } else if (value instanceof RLanguage) { + element = ((RLanguage) value).getRep().asRSyntaxNode(); + } else if (value instanceof RMissing) { + element = RSyntaxLookup.createDummyLookup(null, "", false); + } else { + return appendConstant(value); + } + if (!quoteExpressions() || element instanceof RSyntaxConstant) { + append(element); + } else { + append("quote("); + append(element); + append(')'); + } + } catch (AbortDeparsingException e) { + // stop deparsing; indicate that there is something missing + sb.append("..."); } return this; } @@ -962,7 +991,7 @@ public class RDeparse { if (i > 0) { append(", "); } - lbreak = linebreak(lbreak); + lbreak = listLinebreak(lbreak); if (snames != null) { append(quotify(snames.getDataAt(i), '\"')); append(" = "); @@ -1042,12 +1071,12 @@ public class RDeparse { @TruffleBoundary public static String deparseSyntaxElement(RSyntaxElement element) { - return new DeparseVisitor(false, RDeparse.MAX_Cutoff, true, KEEPINTEGER, -1).append(element).getContents(); + return new DeparseVisitor(false, RDeparse.MAX_CUTOFF, true, KEEPINTEGER, -1).append(element).getContents(); } @TruffleBoundary public static String deparse(Object value) { - return new DeparseVisitor(false, RDeparse.MAX_Cutoff, true, KEEPINTEGER, -1).appendValue(value).getContents(); + return new DeparseVisitor(false, RDeparse.MAX_CUTOFF, true, KEEPINTEGER, -1).appendValue(value).getContents(); } @TruffleBoundary @@ -1055,6 +1084,11 @@ public class RDeparse { return new DeparseVisitor(false, cutoff, backtick, opts, nlines).appendValue(expr).getContents(); } + @TruffleBoundary + public static String deparse(Object expr, int cutoff, boolean backtick, int opts, int nlines, int debugCutoff) { + return new DeparseVisitor(false, cutoff, backtick, opts, nlines, debugCutoff).appendValue(expr).getContents(); + } + /** * Ensure that {@code node} has a {@link SourceSection} by deparsing if necessary. */ @@ -1070,11 +1104,11 @@ public class RDeparse { } } // try to generate the source from the root node and hopefully it includes this node - new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(nodeToFixup).fixupSources(); + new DeparseVisitor(true, RDeparse.MAX_CUTOFF, false, -1, 0).append(nodeToFixup).fixupSources(); // if not, we have to deparse the node in isolation if (node.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) { - new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources(); + new DeparseVisitor(true, RDeparse.MAX_CUTOFF, false, -1, 0).append(node).fixupSources(); } assert node.getLazySourceSection() != RSyntaxNode.LAZY_DEPARSE; } @@ -1134,4 +1168,16 @@ public class RDeparse { return 0; } } + + @SuppressWarnings("serial") + private static class AbortDeparsingException extends RuntimeException { + } + + @SuppressWarnings("serial") + private static final class MaxLinesReachedException extends AbortDeparsingException { + } + + @SuppressWarnings("serial") + private static final class MaxLengthReachedException extends AbortDeparsingException { + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index fbb3953558a93d1e1a604db5ce01d7ce14dc455e..4b34f2b46d44749447c232785181bc6f170c3b1e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -590,7 +590,6 @@ public final class RError extends RuntimeException { NROW_ZERO("nr(0 for non-null data"), CANNOT_EXCEED_X("'%s' cannot exceed %s(x) = %d"), SAMPLE_LARGER_THAN_POPULATION("cannot take a sample larger than the population when 'replace(FALSE'\n"), - SAMPLE_OBJECT_NOT_FOUND("object '%s' not found"), ERROR_IN_SAMPLE("Error in sample.int(x, size, replace, prob) : "), INCORRECT_NUM_PROB("incorrect number of probabilities"), NA_IN_PROB_VECTOR("NA in probability vector"), @@ -614,6 +613,7 @@ public final class RError extends RuntimeException { INVALID_FORMAT_LOGICAL("invalid format '%s'; use format %%d or %%i for logical objects"), INVALID_FORMAT_INTEGER("invalid format '%s'; use format %%d, %%i, %%o, %%x or %%X for integer objects"), POS_NOT_ALLOWED_WITH_NUMERIC("pos argument not allowed with a numeric value"), + OBJ_CANNOT_BE_ATTRIBUTED("external object cannot be attributed"), // the following list is incomplete (but like GNU-R) INVALID_FORMAT_DOUBLE("invalid format '%s'; use format %%f, %%e, %%g or %%a for numeric objects"), INVALID_LOGICAL("'%s' must be TRUE or FALSE"), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index eda8d1fee8af05be6eb5d8add2d77776f0b80202..8415803a341c9c2496490671d9afc65f6739c5be 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -1474,7 +1474,8 @@ public class RSerialize { attributes = null; } } - boolean hasTag = gnuRType == SEXPTYPE.CLOSXP || (gnuRType == SEXPTYPE.PROMSXP && !((RPromise) obj).isEvaluated()) || (type == SEXPTYPE.LISTSXP && !((RPairList) obj).isNullTag()); + boolean hasTag = gnuRType == SEXPTYPE.CLOSXP || gnuRType == SEXPTYPE.DOTSXP || (gnuRType == SEXPTYPE.PROMSXP && !((RPromise) obj).isEvaluated()) || + (type == SEXPTYPE.LISTSXP && !((RPairList) obj).isNullTag()); int gpbits = getGPBits(obj); int flags = Flags.packFlags(gnuRType, gpbits, isObject(obj), attributes != null, hasTag); stream.writeInt(flags); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java index e1ef2d2fc9afa9196652aa5e6cec3fb6600fdc12..16f3e223d16b0c343dba84208bd6e57da4c54d0e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java @@ -56,6 +56,7 @@ public class RSource { SHELL_INPUT("<shell_input>"), EXPRESSION_INPUT("<expression_input>"), GET_ECHO("<get_echo>"), + GET_CONTINUE_PROMPT("<get_continue_prompt>"), QUIT_EOF("<<quit_eof>>"), STARTUP_SHUTDOWN("<startup/shutdown>"), REPL_WRAPPER("<repl wrapper>"), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java index c30feafca92621778beef7300111b91d03aab0b7..cd21de478bcbbc641621ce8c4e41ec50082b40e5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java @@ -31,24 +31,27 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; * implementations for different contexts. Since I/O is involved, all methods are tagged with * {@link TruffleBoundary} as a hint that so should the associated implementation methods. */ -public interface ConsoleHandler { +public abstract class ConsoleHandler { + + private RContext ctx; + /** * Normal output with a new line. */ @TruffleBoundary - void println(String s); + public abstract void println(String s); /** * Normal output without a newline. */ @TruffleBoundary - void print(String s); + public abstract void print(String s); /** * Formatted output. */ @TruffleBoundary - default void printf(String format, Object... args) { + public void printf(String format, Object... args) { print(String.format(format, args)); } @@ -58,20 +61,20 @@ public interface ConsoleHandler { * @param s */ @TruffleBoundary - void printErrorln(String s); + public abstract void printErrorln(String s); /** * Error output without a newline. */ @TruffleBoundary - void printError(String s); + public abstract void printError(String s); /** * Read a line of input, newline is <b>NOT</b> included in result. Returns null if * {@link #isInteractive() == false}. TODO worry about "\r\n"? */ @TruffleBoundary - String readLine(); + public abstract String readLine(); /** * Denote whether the FastR instance is running in 'interactive' mode. This can be set in a @@ -79,27 +82,35 @@ public interface ConsoleHandler { * final once set. */ @TruffleBoundary - boolean isInteractive(); + public abstract boolean isInteractive(); /** * Get the current prompt. */ @TruffleBoundary - String getPrompt(); + public abstract String getPrompt(); /** * Set the R prompt. */ @TruffleBoundary - void setPrompt(String prompt); + public abstract void setPrompt(String prompt); + + public abstract String getInputDescription(); - String getInputDescription(); + public void setContext(RContext ctx) { + this.ctx = ctx; + } + + public RContext getContext() { + return ctx; + } - default void setHistoryFrom(@SuppressWarnings("unused") File file) { + public void setHistoryFrom(@SuppressWarnings("unused") File file) { // by default, do nothing } - default void flushHistory() { + public void flushHistory() { // by default, do nothing } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java index 93ef3ba544ff1b8f3799caae8fc1aa1ebf65e5d7..5a680554e95df9da0769f3809a8e8aedc9e2dff5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java @@ -94,6 +94,13 @@ public final class ContextInfo { } PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build(); this.vm = newVM; + + // retrieve context and set for console handler + if (consoleHandler != null) { + RContext ctx = newVM.eval(Engine.GET_CONTEXT).as(RContext.class); + consoleHandler.setContext(ctx); + } + return newVM; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java index 18f2a36cceb1ed6df87252416c914869ebb2d624..3bb4b182ccaf24cfbba29e1930d0fa3308614bf5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; -public class DefaultConsoleHandler implements ConsoleHandler { +public class DefaultConsoleHandler extends ConsoleHandler { private final BufferedReader in; private final PrintStream out; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java index 2a790546b7aeb33940bd9065e5bcea352b5f911e..aca66505b2857a49062c21ee187782489dc2e01f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java @@ -33,6 +33,7 @@ import java.util.TimeZone; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -265,10 +266,14 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl public static final Map<Integer, Thread> threads = new ConcurrentHashMap<>(); + /** We use a separate counter for threads since ConcurrentHashMap.size() is not reliable. */ + public static final AtomicInteger threadCnt = new AtomicInteger(0); + public EvalThread(ContextInfo info, Source source) { super(null); this.info = info; this.source = source; + threadCnt.incrementAndGet(); threads.put(info.getId(), this); } @@ -286,6 +291,7 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl } finally { vm.dispose(); threads.remove(info.getId()); + threadCnt.decrementAndGet(); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java index 884bd82b483ac87d172232764e2f24536d3431dd..85c44026426c8740cc9155fb4b5212df37939219 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java @@ -59,7 +59,6 @@ import com.oracle.truffle.r.runtime.data.RObjectSize.TypeCustomizer; public class AgentObjectSizeFactory extends ObjectSizeFactory { private final Map<Class<?>, ArrayList<Field>> objectFieldsMap = new HashMap<>(); - private static Map<Class<?>, TypeCustomizer> customizerMap = new HashMap<>(); // system wide public AgentObjectSizeFactory() { if (!ObjSizeAgent.isInitialized()) { @@ -208,19 +207,4 @@ public class AgentObjectSizeFactory extends ObjectSizeFactory { } } } - - private static TypeCustomizer getCustomizer(Class<?> objClass) { - for (Map.Entry<Class<?>, TypeCustomizer> entry : customizerMap.entrySet()) { - if (entry.getKey().isAssignableFrom(objClass)) { - return entry.getValue(); - } - } - return null; - - } - - @Override - public void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) { - customizerMap.put(klass, typeCustomizer); - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java index dc5b6529b927da17c556388083bd25322e654b8d..9de56a9bce0f448008af12b9b98b81bfee49e8ff 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java @@ -22,12 +22,16 @@ */ package com.oracle.truffle.r.runtime.data; +import java.util.ArrayList; + import com.oracle.truffle.r.runtime.FastRConfig; import com.oracle.truffle.r.runtime.data.RObjectSize.IgnoreObjectHandler; import com.oracle.truffle.r.runtime.data.RObjectSize.TypeCustomizer; public abstract class ObjectSizeFactory { + private static ArrayList<TypeCustomizerData> typeCustomizers = new ArrayList<>(); // system wide + static { String prop = System.getProperty("fastr.objectsize.factory.class"); if (prop == null) { @@ -56,6 +60,26 @@ public abstract class ObjectSizeFactory { */ public abstract long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler); - public abstract void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer); + public void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) { + typeCustomizers.add(new TypeCustomizerData(klass, typeCustomizer)); + } + + protected static TypeCustomizer getCustomizer(Class<?> objClass) { + for (TypeCustomizerData customizer : typeCustomizers) { + if (customizer.type.isAssignableFrom(objClass)) { + return customizer.customizer; + } + } + return null; + } + + private static final class TypeCustomizerData { + private final TypeCustomizer customizer; + private final Class<?> type; + private TypeCustomizerData(Class<?> type, TypeCustomizer customizer) { + this.customizer = customizer; + this.type = type; + } + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java index c5610b4945cca913c5e900bdb8458be8353432bb..1f874d0842786b2e9c4e944544a9815dc2941bab 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,9 @@ public final class RArgsValuesAndNames extends Arguments<Object> implements RTyp @Override public int getTypedValueInfo() { - throw RInternalError.shouldNotReachHere(); + // RArgsValuesAndNames can get serialized under specific circumstances (ggplot2 does that) + // and getTypedValueInfo() must be defined for this to work. + return 0; } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java index 6f5d17a46638257c775d94e706d334cadf5426f5..9df6c25f3cc4b19d98f7a2168e4c717c71179112 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java @@ -22,8 +22,6 @@ */ package com.oracle.truffle.r.runtime.data; -import java.util.HashMap; - import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.data.RObjectSize.IgnoreObjectHandler; @@ -40,16 +38,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; * Very simple object size calculation that does not need an instrumentation agent. */ public class SimpleObjectSizeFactory extends ObjectSizeFactory { - private HashMap<Class<?>, TypeCustomizer> typeCustomizers; - @Override public long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler) { RError.warning(RError.NO_CALLER, Message.OBJECT_SIZE_ESTIMATE); // Customizers - for (Class<?> klass : typeCustomizers.keySet()) { - if (obj.getClass().equals(klass)) { - return typeCustomizers.get(klass).getObjectSize(obj); - } + TypeCustomizer customizer = getCustomizer(obj.getClass()); + if (customizer != null) { + return customizer.getObjectSize(obj); } // Well known vector types if (obj instanceof RAbstractDoubleVector) { @@ -76,12 +71,4 @@ public class SimpleObjectSizeFactory extends ObjectSizeFactory { } return 4; } - - @Override - public void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) { - if (typeCustomizers == null) { - typeCustomizers = new HashMap<>(); - } - typeCustomizers.put(klass, typeCustomizer); - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java index d44fd73c8796a4725c679e55032c7030a1be91f6..c93bf6935e6818f563f04f9fb608e2a658bee006 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.env; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.MessageResolution; @@ -31,6 +32,7 @@ import com.oracle.truffle.api.interop.Resolve; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.metadata.ScopeProvider.AbstractScope; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -39,6 +41,7 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; /** @@ -103,10 +106,9 @@ public final class RScope extends AbstractScope { @Override protected AbstractScope findParent() { - if (this.env == REnvironment.emptyEnv()) { + if (env == REnvironment.emptyEnv() || env.getParent() == REnvironment.emptyEnv()) { return null; } - return new RScope(env.getParent()); } @@ -136,8 +138,16 @@ public final class RScope extends AbstractScope { return new RScope(node.getRootNode(), getEnv(frame)); } - private static Object getInteropValue(Object value) { - return value; + /** + * Explicitly convert some known types to interop types. + */ + private static Object getInteropValue(Object obj) { + if (obj instanceof Frame) { + MaterializedFrame materialized = ((Frame) obj).materialize(); + assert RArguments.isRFrame(materialized); + return REnvironment.frameToEnvironment(materialized); + } + return obj; } static final class VariablesMapObject implements TruffleObject { @@ -167,11 +177,13 @@ public final class RScope extends AbstractScope { @TruffleBoundary public Object access(VariablesMapObject varMap) { + String[] names; if (varMap.argumentsOnly) { - return new ArgumentNamesObject(collectArgs(varMap.env)); + names = collectArgs(varMap.env); } else { - return new VariableNamesObject(varMap.env); + names = ls(varMap.env); } + return new ArgumentNamesObject(names); } } @@ -223,6 +235,9 @@ public final class RScope extends AbstractScope { if (varMap.env == null) { throw UnsupportedMessageException.raise(Message.WRITE); } + if (!(value instanceof RTypedValue)) { + throw UnsupportedTypeException.raise(new Object[]{value}); + } try { varMap.env.put(name, value); return value; @@ -235,60 +250,6 @@ public final class RScope extends AbstractScope { } } - static final class VariableNamesObject implements TruffleObject { - - private final REnvironment env; - - private VariableNamesObject(REnvironment env) { - this.env = env; - } - - @Override - public ForeignAccess getForeignAccess() { - return VariableNamesMessageResolutionForeign.ACCESS; - } - - public static boolean isInstance(TruffleObject obj) { - return obj instanceof VariableNamesObject; - } - - @MessageResolution(receiverType = VariableNamesObject.class) - static final class VariableNamesMessageResolution { - - @Resolve(message = "HAS_SIZE") - abstract static class VarNamesHasSizeNode extends Node { - - @SuppressWarnings("unused") - public Object access(VariableNamesObject varNames) { - return true; - } - } - - @Resolve(message = "GET_SIZE") - abstract static class VarNamesGetSizeNode extends Node { - - public Object access(VariableNamesObject varNames) { - return ls(varNames.env).length; - } - } - - @Resolve(message = "READ") - abstract static class VarNamesReadNode extends Node { - - @TruffleBoundary - public Object access(VariableNamesObject varNames, int index) { - String[] names = ls(varNames.env); - if (index >= 0 && index < names.length) { - return names[index]; - } else { - throw UnknownIdentifierException.raise(Integer.toString(index)); - } - } - } - - } - } - static final class ArgumentNamesObject implements TruffleObject { private final String[] names; @@ -331,8 +292,9 @@ public final class RScope extends AbstractScope { @TruffleBoundary public Object access(ArgumentNamesObject varNames, int index) { - if (index >= 0 && index < varNames.names.length) { - return varNames.names[index]; + String[] names = varNames.names; + if (index >= 0 && index < names.length) { + return names[index]; } else { throw UnknownIdentifierException.raise(Integer.toString(index)); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java index 2bb5d9a64ae5afc53428ec640de1594bb98a051a..b6969e1e37aca0b51d612c706f7f30191e31d3cc 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java @@ -17,8 +17,8 @@ import java.util.concurrent.atomic.AtomicInteger; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; @@ -180,6 +180,7 @@ public class DLL { private boolean dynamicLookup; private boolean forceSymbols; private final DotSymbol[][] nativeSymbols = new DotSymbol[NativeSymbolType.values().length][]; + private ArrayList<CEntry> cEntryTable = null; private DLLInfo(String name, String path, boolean dynamicLookup, Object handle) { this.id = ID.getAndIncrement(); @@ -229,6 +230,24 @@ public class DLL { } } + public void registerCEntry(CEntry entry) { + if (cEntryTable == null) { + cEntryTable = new ArrayList<>(); + } + cEntryTable.add(entry); + } + + public CEntry lookupCEntry(String symbol) { + if (cEntryTable != null) { + for (CEntry entry : cEntryTable) { + if (entry.symbol.equals(symbol)) { + return entry; + } + } + } + return null; + } + /** * Return array of values that can be plugged directly into an {@code RList}. */ @@ -256,7 +275,7 @@ public class DLL { } } - public static class SymbolInfo { + public static final class SymbolInfo { public final DLLInfo libInfo; public final String symbol; public final SymbolHandle address; @@ -305,6 +324,21 @@ public class DLL { } } + /** + * R has an interface for exporting and importing functions between packages' native code. The + * functions have to be exported, i.e. registered in a directory, called CEntry table in GNU R. + * Another package can they as the directory for address or a function with specified name. + */ + public static final class CEntry { + public final String symbol; + public final SymbolHandle address; + + public CEntry(String symbol, SymbolHandle address) { + this.symbol = symbol; + this.address = address; + } + } + /** * Abstracts the way that DLL function symbols are represented, either as a machine address ( * {@link Long}) or a {@link TruffleObject}. At the present time, both forms can exists within a 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 c700f6b474620a0bc5151920c9259f33a5920e76..ad6a7f6d381ca1e8949a34b3864d8283eab9cbc3 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 @@ -36123,6 +36123,16 @@ list sys.call(1) +##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGetWithVarArgs# +#{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));func <- function(...) find_args(...);func(); } + ... +FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGetWithVarArgs# +#{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));func <- function(...) find_args(...);func(a=3); } + ... +TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# #min(c(1,NA,2), na.rm=NA) [1] 1 @@ -62402,6 +62412,10 @@ Error in seq.int(NaN) : 'from' cannot be NA, NaN or infinite #argv <- list(from = 0, to = 0.793110173512391, length.out = FALSE);do.call('seq.int', argv); integer(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testSerializeWithPromises# +#{ f <- function(...) serialize(mget('...'),NULL); length(unserialize(f(a=3,b=2,c=1))[[1]]); } +[1] 3 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#Ignored.ImplementationError# #options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL) [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 07 03 00 00 04 02 00 00 00 @@ -64259,6 +64273,14 @@ $`2` [1] 2 4 6 8 10 +##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplit# +#{ split(as.raw(1:10), as.factor(c('a', 'b', 'a')); } +Error: unexpected ';' in "{ split(as.raw(1:10), as.factor(c('a', 'b', 'a'));" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplit# +#{ split(list(1, 2L, 'x', T), as.factor(c('a', 'b', 'a')); } +Error: unexpected ';' in "{ split(list(1, 2L, 'x', T), as.factor(c('a', 'b', 'a'));" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplit# #{ x <- factor(c("a", "b", "a")); attr(x, "levels")<-c(7L, 42L) ; split(1:3, x) } $`7` @@ -64268,6 +64290,24 @@ $`42` [1] 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplitWithNames#Ignored.Unimplemented# +#{ split(list(q=1, w=2L, e='x', r=T), as.factor(c('a', 'b', 'a')); } +Error: unexpected ';' in "{ split(list(q=1, w=2L, e='x', r=T), as.factor(c('a', 'b', 'a'));" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplitWithNames#Ignored.Unimplemented# +#{ tmp <- c(1,2,3); names(tmp) <- c('x','y','z'); split(tmp, as.factor(c('a','b'))); } +$a +x z +1 3 + +$b +y +2 + +Warning message: +In split.default(tmp, as.factor(c("a", "b"))) : + data length is not a multiple of split variable + ##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit1# #argv <- list(1:6, structure(1:2, .Label = c('1', '2'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]])) $`1` @@ -76753,6 +76793,12 @@ Error in rnorm(s = 1, s = 1) : #{ f <- match.fun(length) ; f(c(1,2,3)) } [1] 3 +##com.oracle.truffle.r.test.functions.TestFunctions.testMatching# +#list(`...`=NULL); +$... +NULL + + ##com.oracle.truffle.r.test.functions.TestFunctions.testMatching# #{ f <- function(a) { a } ; f(1,2) } Error in f(1, 2) : unused argument (2) @@ -79115,6 +79161,42 @@ Error in get("x") : object 'x' not found #{ pi/180; pi } [1] 3.141593 +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(1, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(2, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(3, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(4, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(5, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(6, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(7, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(8, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + +##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster# +#fun <- function(data) { cl <- makeCluster(9, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100) +Error in fun(1:100) : could not find function "makeCluster" + ##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testArithmeticUpdate# #{ x <- 3 ; f <- function(z) { if (z) { x <- 1 } ; x <- 1L + x ; x } ; f(FALSE) } [1] 4 @@ -130465,10 +130547,10 @@ NULL [1] "Error reading file: /a/b.R" ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("testScript.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("testScript.R") } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("_testInteropEvalFile_testScript_.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("_testInteropEvalFile_testScript_.R") } 1 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("testScript.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("testScript.R","application/x-r") } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("_testInteropEvalFile_testScript_.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("_testInteropEvalFile_testScript_.R","application/x-r") } 1 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport# #if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 'foo') } @@ -130488,7 +130570,8 @@ NULL [6] "stringValue" ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('$intValue\n[1] 1\n\n$longValue\n[1] 123412341234\n\n$charValue\n[1] "R"\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$stringValue\n[1] "foo"\n\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testPOJO'); print(v) } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n$intValue\n[1] 1\n\n$longValue\n[1] 123412341234\n\n$charValue\n[1] "R"\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$stringValue\n[1] "foo"\n\n') } else { v <- .fastr.interop.import('testPOJO'); print(v) } +[external object] $intValue [1] 1 @@ -130507,26 +130590,21 @@ $booleanValue $stringValue [1] "foo" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 -5 199\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testIntArray'); print(v) } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 -5 199\n') } else { v <- .fastr.interop.import('testIntArray'); print(v) } +[external object] [1] 1 -5 199 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 -5 199\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testIntArray'); v } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 -5 199\n') } else { v <- .fastr.interop.import('testIntArray'); v } +[external object] [1] 1 -5 199 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "" "foo"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testStringArray'); print(v) } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "" "foo"\n') } else { v <- .fastr.interop.import('testStringArray'); print(v) } +[external object] [1] "a" "" "foo" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAllTypes# #if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") } @@ -130537,31 +130615,31 @@ attr(,"is.truffle.object") [1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1]; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { a <- .fastr.java.toArray(c(1,2,3)); a[1] } [1] 1 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]]; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { a <- .fastr.java.toArray(c(1,2,3)); a[[1]] } [1] 1 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[1] } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1]; } [1] 1 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[[1]] } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]]; } [1] 1 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1] } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { a <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1] } [1] 123 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1] } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { a <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]] } [1] 123 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]] } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1] } [1] 123 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# @@ -130589,16 +130667,26 @@ attr(,"is.truffle.object") NULL ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1] } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1] } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]] } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]] } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAttributes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); attributes(to) } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAttributes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in attr(to, "a") <- "a" : external object cannot be attributed<<<NEWLINE>>>') } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); attr(to, 'a')<-'a' } +Error in attr(to, "a") <- "a" : external object cannot be attributed + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAttributes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in attr(to, which = "a") : external object cannot be attributed<<<NEWLINE>>>') } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); attr(to, which = 'a') } +Error in attr(to, which = "a") : external object cannot be attributed ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter# #if (length(grep("FastR", R.Version()$version.string)) != 1) { "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$classAsArg(tc) } @@ -130789,112 +130877,94 @@ NULL [1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE FALSE TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE FALSE TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanArray } +[external object] [1] TRUE FALSE TRUE -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE FALSE TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE FALSE TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanArray } +[external object] [1] TRUE FALSE TRUE -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharArray } +[external object] [1] "a" "b" "c" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharArray } +[external object] [1] "a" "b" "c" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringArray } +[external object] [1] "a" "b" "c" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray } +[external object] [1] "a" "b" "c" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteArray } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongArray } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortArray } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteArray } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntArray } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongArray } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortArray } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleArray } +[external object] [1] 1.1 2.1 3.1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatArray } +[external object] [1] 1.1 2.1 3.1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleArray } +[external object] [1] 1.1 2.1 3.1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatArray } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatArray } +[external object] [1] 1.1 2.1 3.1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# #if (length(grep("FastR", R.Version()$version.string)) != 1) { "character" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticCharArray); typeof(v) } @@ -131159,28 +131229,24 @@ NULL [1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringArray() } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringArray() } +[external object] [1] "a" "b" "c" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringArray() } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringArray() } +[external object] [1] "a" "b" "c" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntArray() } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntArray() } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntArray() } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntArray() } +[external object] [1] 1 2 3 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject# #if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em) } @@ -131287,189 +131353,158 @@ Error: object 'java.lang.String' not found [1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE FALSE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(T, F)); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE FALSE\n') } else { a <- .fastr.java.toArray(c(T, F)); a; } +[external object] [1] TRUE FALSE -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE FALSE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(T, F),,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE FALSE\n') } else { a <- .fastr.java.toArray(c(T, F),,T); a; } +[external object] [1] TRUE FALSE -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c('a', 'b')); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b"\n') } else { a <- .fastr.java.toArray(c('a', 'b')); a; } +[external object] [1] "a" "b" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c('a', 'b'),,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b"\n') } else { a <- .fastr.java.toArray(c('a', 'b'),,T); a; } +[external object] [1] "a" "b" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray('a'); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a"\n') } else { a <- .fastr.java.toArray('a'); a; } +[external object] [1] "a" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray('a',,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a"\n') } else { a <- .fastr.java.toArray('a',,T); a; } +[external object] [1] "a" -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a; } +[external object] [1] 1 2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a; } +[external object] [1] 1 2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a; } +[external object] [1] 1 2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a; } +[external object] [1] 1 2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a; } +[external object] [1] 1 2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1L, 2L)); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(1L, 2L)); a; } +[external object] [1] 1 2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1L, 2L),,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(1L, 2L),,T); a; } +[external object] [1] 1 2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 1.2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2)); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 1.2\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2)); a; } +[external object] [1] 1.1 1.2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 1.2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2),,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 1.2\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2),,T); a; } +[external object] [1] 1.1 1.2 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.123 2.123\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.123 2.123\n') } else { a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a; } +[external object] [1] 1.123 2.123 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1.1); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1\n') } else { a <- .fastr.java.toArray(1.1); a; } +[external object] [1] 1.1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1.1,,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1\n') } else { a <- .fastr.java.toArray(1.1,,T); a; } +[external object] [1] 1.1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a); } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a); } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a; } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a; } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a; } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a; } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a; } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a); } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a); } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T); } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T); } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L); a; } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#Ignored.Unimplemented# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L,,F); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L,,F); a; } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L,,T); a; } +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L,,T); a; } +[external object] [1] 1 -attr(,"is.truffle.object") -[1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T); a; } -[1] TRUE -attr(,"is.truffle.object") +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T); a; } +[external object] [1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# -#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T,,T); a; } -[1] TRUE -attr(,"is.truffle.object") +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T,,T); a; } +[external object] [1] TRUE ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java index 1eb1faf9b642b24dbb7711d5c867c97feea8e5bc..6fa10c3bd8c69b28d712e5a989b84171be46d764 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java @@ -49,7 +49,6 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind; import com.oracle.truffle.r.test.generate.FastRSession; import com.oracle.truffle.r.test.generate.GnuROneShotRSession; import com.oracle.truffle.r.test.generate.TestOutputManager; -import java.io.OutputStream; /** * Base class for all unit tests. The unit tests are actually arranged as a collection of diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java index e27d7728fc5c1f0ad654ae6a0d25cf668c7bb9a3..27f45c65f1dcf52a61f9af79cde406208c08008e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java @@ -34,4 +34,11 @@ public class TestBuiltin_mget extends TestBase { assertEval("{ x<-mget(\"_foo_\", ifnotfound=list(function(x) sys.call(0))); print(x[[1]][[1]]); print(x[[1]][[2]]) }"); assertEval("{ x<-mget(\"_foo_\", ifnotfound=list(function(x) sys.call(1))); list(x[[1]][[1]], x[[1]][[2]], x[[1]][[3]][[1]], x[[1]][[3]][[2]][[1]], x[[1]][[3]][[2]][[2]], x[[1]][[3]][[2]][[3]]) }"); } + + @Test + public void testMGetWithVarArgs() { + assertEval(template("{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));" + + "func <- function(...) find_args(...);" + + "%0; }", new String[]{"func()", "func(a=3)"})); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java index 3e031ad10ee498a5d31a0b7b12cf40732aa86c79..018b22c6522e7f87fd641f22e554eb5fe53ca58d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java @@ -111,4 +111,9 @@ public class TestBuiltin_serialize extends TestBase { assertEval("{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) }"); } + + @Test + public void testSerializeWithPromises() { + assertEval("{ f <- function(...) serialize(mget('...'),NULL); length(unserialize(f(a=3,b=2,c=1))[[1]]); }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java index 234bd45d0266926805884872852794e57ed378de..d551d2225e677fb93c52e60517b814c17b2d78ff 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java @@ -116,5 +116,13 @@ public class TestBuiltin_split extends TestBase { assertEval("{ fu <- c(\"a\",\"b\") ; split(1:8,fu) }"); assertEval("{ g <- factor(round(c(0.4,1.3,0.6,1.8,2.5,4.1,2.2,1.0))) ; x <- c(0.1,3.2,1,0.6,1.9,3.3,1.6,1.7) + sqrt(as.numeric(g)) ; xg <- split(x, g) ; xg }"); assertEval("{ x <- factor(c(\"a\", \"b\", \"a\")); attr(x, \"levels\")<-c(7L, 42L) ; split(1:3, x) }"); + assertEval("{ split(list(1, 2L, 'x', T), as.factor(c('a', 'b', 'a')); }"); + assertEval("{ split(as.raw(1:10), as.factor(c('a', 'b', 'a')); }"); + } + + @Test + public void testSplitWithNames() { + assertEval(Ignored.Unimplemented, "{ split(list(q=1, w=2L, e='x', r=T), as.factor(c('a', 'b', 'a')); }"); + assertEval(Ignored.Unimplemented, "{ tmp <- c(1,2,3); names(tmp) <- c('x','y','z'); split(tmp, as.factor(c('a','b'))); }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_weekdaysDate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_weekdaysDate.java index 8ab38d35b6fa007071c805b3adece9147947dcb4..00e6bb6e1914232d71750858acce129c3c46be5b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_weekdaysDate.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_weekdaysDate.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2014, Purdue University - * Copyright (c) 2014, 2016, Oracle and/or its affiliates + * Copyright (c) 2014, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -13,6 +13,7 @@ package com.oracle.truffle.r.test.builtins; import org.junit.Test; import com.oracle.truffle.r.test.TestBase; +import java.util.Locale; // Checkstyle: stop line length check @@ -20,6 +21,11 @@ public class TestBuiltin_weekdaysDate extends TestBase { @Test public void testweekdaysDate1() { + // Explicit locale setting is a workaround to run this test on JDK9. + // Otherwise the test was returning "Thu" instead of "Thursday" + // due to JDK bug 8130845. + Locale.setDefault(Locale.ENGLISH); + assertEval("argv <- structure(list(x = structure(16352, class = 'Date')), .Names = 'x');do.call('weekdays.Date', argv)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e216b0d234ace50a4797da899c09b5a9b0c77035 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.engine.interop; + +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.vm.PolyglotEngine; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class RInteropScalarMRTest { + + @Test + public void testRInteroptScalar() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException { + testRIS("toByte", "" + Byte.MAX_VALUE, Byte.class); + testRIS("toChar", "'a'", Character.class); + testRIS("toFloat", "" + Float.MAX_VALUE, Float.class); + testRIS("toLong", "" + Long.MAX_VALUE, Long.class); + testRIS("toShort", "" + Short.MAX_VALUE, Short.class); + } + + private void testRIS(String toInteropScalarBuiltin, String value, Class<?> unboxedType) throws UnsupportedMessageException { + TruffleObject l = createRInteroptScalarTO(toInteropScalarBuiltin, value); + + assertFalse(ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), l)); + assertFalse(ForeignAccess.sendHasSize(Message.HAS_SIZE.createNode(), l)); + + assertTrue(ForeignAccess.sendIsBoxed(Message.IS_BOXED.createNode(), l)); + Object ub = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), l); + assertEquals(unboxedType, ub.getClass()); + } + + private TruffleObject createRInteroptScalarTO(String toInteropScalarBuiltin, String value) { + PolyglotEngine engine = PolyglotEngine.newBuilder().build(); + Source src = Source.newBuilder(".fastr.interop." + toInteropScalarBuiltin + "(" + value + ")").mimeType("text/x-r").name("test.R").build(); + PolyglotEngine.Value result = engine.eval(src); + return result.as(TruffleObject.class); + } + +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java index e7d55912a9dfb820431d590ee1ffa684acb7c531..015fa4ff405ce362e1a4378cbb4b82877f07e0e0 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java @@ -118,7 +118,8 @@ public class TestJLineConsoleCompleter { } } - private class DummyConsoleHandler implements ConsoleHandler { + private class DummyConsoleHandler extends ConsoleHandler { + @Override public void println(String s) { } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java index 8265d0daad743fd31606eca36322bfbe3c7629ab..19068de2cbd7721c7c16ebf3b64365df6616c799 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java @@ -240,6 +240,7 @@ public class TestFunctions extends TestBase { assertEval("{ foo <- function(xa, ...) list(xa=xa, ...); foo(x=4,xa=5); }"); // however, two partial matches produce error, even if one is "longer" assertEval("{ foo <- function(xaaa, ...) list(xaa=xaaa, ...); foo(xa=4,xaa=5); }"); + assertEval("list(`...`=NULL);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java index 0b51a3d92da5c30b1872b21f4e31c429aeaa6403..ca61843663b6891e0e6bfea2f7358a2495c30ee8 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java @@ -66,7 +66,7 @@ public final class FastRSession implements RSession { * A (virtual) console handler that collects the output in a {@link StringBuilder} for * comparison. It does not separate error output as the test analysis doesn't need it. */ - public static class TestConsoleHandler implements ConsoleHandler { + public static class TestConsoleHandler extends ConsoleHandler { private final StringBuilder buffer = new StringBuilder(); private final Deque<String> input = new ArrayDeque<>(); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java new file mode 100644 index 0000000000000000000000000000000000000000..22c14a3b209d3193f91d206d4f692c246a569823 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.library.base; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +// Checkstyle: stop line length check +public class TestSharedCluster extends TestBase { + + @Test + public void testSharedCluster() { + assertEval(TestBase.template("fun <- function(data) { cl <- makeCluster(%0, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)", "123456789".split(""))); + } + +} 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 0997d603ee8d5b361ee38ac003ee33fa13cb8362..6ce8c916abceface6107b8994e53e785f0abc5f7 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 @@ -39,10 +39,11 @@ public class TestInterop extends TestBase { private static final SeekableMemoryByteChannel CHANNEL = new SeekableMemoryByteChannel(); private static final String CHANNEL_NAME = "_fastr_channel0"; + private static final String TEST_EVAL_FILE = "_testInteropEvalFile_testScript_.R"; @After public void cleanup() { - File f = new File("testScript.R"); + File f = new File(TEST_EVAL_FILE); if (f.exists()) { f.delete(); } @@ -67,9 +68,11 @@ public class TestInterop extends TestBase { @Test public void testInteropEvalFile() { - assertEvalFastR("fileConn<-file(\"testScript.R\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"testScript.R\",\"application/x-r\")", + assertEvalFastR("fileConn<-file(\"" + TEST_EVAL_FILE + "\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"" + TEST_EVAL_FILE + + "\",\"application/x-r\")", + "x<-c(1);cat(x)"); + assertEvalFastR("fileConn<-file(\"" + TEST_EVAL_FILE + "\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"" + TEST_EVAL_FILE + "\")", "x<-c(1);cat(x)"); - assertEvalFastR("fileConn<-file(\"testScript.R\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"testScript.R\")", "x<-c(1);cat(x)"); assertEvalFastR("tryCatch(.fastr.interop.evalFile(\"/a/b.R\"), error = function(e) e$message)", "cat('[1] \"Error reading file: /a/b.R\"\\n')"); } @@ -108,7 +111,8 @@ public class TestInterop extends TestBase { @Test public void testPrinting() { - assertEvalFastR("v <- .fastr.interop.import('testPOJO'); print(v)", "cat('$intValue\\n" + + assertEvalFastR("v <- .fastr.interop.import('testPOJO'); print(v)", "cat('[external object]\\n" + + "$intValue\\n" + "[1] 1\\n" + "\\n" + "$longValue\\n" + @@ -124,19 +128,10 @@ public class TestInterop extends TestBase { "[1] TRUE\\n" + "\\n" + "$stringValue\\n" + - "[1] \"foo\"\\n" + - "\\n" + - "attr(,\"is.truffle.object\")\\n" + - "[1] TRUE\\n')"); - assertEvalFastR("v <- .fastr.interop.import('testStringArray'); print(v)", "cat('[1] \"a\" \"\" \"foo\"\\n" + - "attr(,\"is.truffle.object\")\\n" + - "[1] TRUE\\n')"); - assertEvalFastR("v <- .fastr.interop.import('testIntArray'); print(v)", "cat('[1] 1 -5 199\\n" + - "attr(,\"is.truffle.object\")\\n" + - "[1] TRUE\\n')"); - assertEvalFastR("v <- .fastr.interop.import('testIntArray'); v", "cat('[1] 1 -5 199\\n" + - "attr(,\"is.truffle.object\")\\n" + - "[1] TRUE\\n')"); + "[1] \"foo\"\\n\\n')"); + assertEvalFastR("v <- .fastr.interop.import('testStringArray'); print(v)", "cat('[external object]\\n[1] \"a\" \"\" \"foo\"\\n')"); + assertEvalFastR("v <- .fastr.interop.import('testIntArray'); print(v)", "cat('[external object]\\n[1] 1 -5 199\\n')"); + assertEvalFastR("v <- .fastr.interop.import('testIntArray'); v", "cat('[external object]\\n[1] 1 -5 199\\n')"); assertEvalFastR("v <- .fastr.interop.import('testPOJO'); names(v)", "c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue')"); } 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 05db254460ed61f551c61cb87e6f2fc1bcc1c1ba..4296cd975d7f5f4ce129f80438c5e621cba937ac 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 @@ -260,7 +260,8 @@ public class TestJavaInterop extends TestBase { @Test public void testClassAsParameter() { - assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS)); + // fails in testdownstream + assertEvalFastR(Ignored.ImplementationError, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS)); } private void getValueForAllTypesMethod(String method) { @@ -339,6 +340,13 @@ 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 testAttributes() { + assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); attributes(to)", "NULL"); + assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); attr(to, 'a')<-'a'", "cat('Error in attr(to, \"a\") <- \"a\" : external object cannot be attributed\n')"); + assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); attr(to, which = 'a')", "cat('Error in attr(to, which = \"a\") : external object cannot be attributed\n')"); + } + private String getRValue(Object value) { if (value == null) { return "NULL"; @@ -362,7 +370,7 @@ public class TestJavaInterop extends TestBase { } if (value.getClass().isArray()) { StringBuilder sb = new StringBuilder(); - sb.append("cat('[1] "); + sb.append("cat('[external object]\\n[1] "); int lenght = Array.getLength(value); for (int i = 0; i < lenght; i++) { if (lenght > 1 && value.getClass().getComponentType() == Boolean.TYPE && (boolean) Array.get(value, i)) { @@ -374,7 +382,7 @@ public class TestJavaInterop extends TestBase { sb.append(" "); } } - sb.append("\\nattr(,\"is.truffle.object\")\\n[1] TRUE\\n')"); + sb.append("\\n')"); return sb.toString(); } return value.toString(); diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index 3479fff1b86814164245efe99a1b38315fe81fe1..b2505b0cb646d5b616d1a72e2a6f7d02099ab07c 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -770,6 +770,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLine com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java,gnu_r_murrel_core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java,gnu_r.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index 16bd646f2ebe8403c5c61ecc2bd36e425a978db4..db642349a852df098c51eef7fbe99dc476f55188 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -29,7 +29,7 @@ suite = { { "name" : "truffle", "subdir" : True, - "version" : "acbe9ec935090e0824372e508563c122b0e46682", + "version" : "538d97d5e696be8a0f882cf970e70689674651c2", "urls" : [ {"url" : "https://github.com/graalvm/graal", "kind" : "git"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},